Hangman Game in Go

 

Hangman Game Example in Go

Here is the code for a hangman game in Go:

package main

import (
	"bufio"
	"fmt"
	"log"
	"math/rand"
	"os"
	"strings"
	"time"
)

var inputReader *bufio.Reader
var randSource rand.Source
var randomGen *rand.Rand

var hangmanPics [7]string

func initPics() {
	hangmanPics = [7]string{
		` +---+
              |
              |
              |
            ===`,
		` +---+
          O  |
             |
             |
           ===`,
		` +---+
	  O   |
	  |   |
	      |
	    ===`,
		` +---+
	  O   |
	 /|   |
	      |
	    ===`,
		`+---+
	 O   |
	/|\  |
             |
	   ===`,
		`+---+
	 O   |
	/|\  |
	/    |
	   ===`,
		`+---+
	 O   |
	/|\  |
	/ \  |
	   ===`}
}

func initRandomGen() {
	randSource = rand.NewSource(time.Now().UnixNano())
	randomGen = rand.New(randSource)
}

func readWordsFromFile(fileName string) *[]string {
	var words []string
	file, err := os.Open(fileName)
	if err != nil {
		log.Fatal(err)
	}
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		words = append(words, strings.TrimSpace(scanner.Text()))
	}
	return &words
}

func getInput() string {
	input, err := inputReader.ReadString('\n')
	if err != nil {
		log.Fatal(err)
	}
	input = strings.TrimSpace(input)
	return input
}

func printTopLevelMenu() {
	fmt.Println("Welcome to Hangman")
	fmt.Println("Enter 1 to start new game")
	fmt.Println("Enter q to quit")
}

func getWord(words *[]string) string {
	index := randomGen.Intn(len(*words))
	word := (*words)[index]
	return word
}

func getMatchingIndices(letter string, word string) *[]int {
	indices := make([]int, 0)
	guessedCharacter := ([]rune(letter))[0]
	for index, ch := range word {
		if ch == guessedCharacter {
			indices = append(indices, index)
		}
	}
	return &indices
}

func startRound(word string) {
	drawState := 0
	var matchingIndices *[]int
	var letter string
	complete := false
	maskedString := make([]string, 0)
	for _, _ = range word {
		maskedString = append(maskedString, "#")
	}
	fmt.Println(maskedString)
	hashCount := 0
	for !complete {
		hashCount = 0
		fmt.Println("Guess letter")
		letter = getInput()
		matchingIndices = getMatchingIndices(letter, word)
		if len(*matchingIndices) == 0 {
			fmt.Println("Incorrect guess")
			drawState++
		}
		for _, index := range *matchingIndices {
			maskedString[index] = letter
		}
		fmt.Println(maskedString)
		for _, let := range maskedString {
			if let == "#" {
				hashCount++
			}
		}
		if hashCount == 0 {
			complete = true
		} else {
			drawHangman(drawState)
			if drawState == 6 {
				fmt.Println("Sorry, you lost")
				fmt.Println("Word was ", word)
				break
			}
		}

	}
	if complete {
		fmt.Println("You won!")
	}
}

func drawHangman(drawState int) {
	fmt.Println(hangmanPics[drawState])
}

func startNewGame(usedWords *map[string]bool, words *[]string) {
	fmt.Println("Start New Game")
	word := getWord(words)
	_, ok := (*usedWords)[word]
	for ok {
		word = getWord(words)
		_, ok = (*usedWords)[word]
	}
	(*usedWords)[word] = true
	startRound(word)
}
func main() {
	usedWords := make(map[string]bool)
	initRandomGen()
	initPics()
	inputReader = bufio.NewReader(os.Stdin)
	inp := ""
	words := readWordsFromFile("words.txt")
	for inp != "q" {
		printTopLevelMenu()
		inp := getInput()
		if inp == "q" {
			return
		} else if inp == "1" {
			startNewGame(&usedWords, words)
		} else {
			return
		}
	}
} 

Comments

Popular posts from this blog

QTreeView and QTableView dynamic changes

C++ strings and string_view