Created
April 13, 2020 05:11
-
-
Save gautamrege/3688cea23ed1675a7b6d5f0bd7d84e0b to your computer and use it in GitHub Desktop.
Hangman - Part 3 struct and receiver methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"net/http" | |
"strings" | |
"time" | |
) | |
var dev = flag.Bool("dev", false, "dev mode") | |
const ( | |
GAME_PLAY = iota // untyped int constants | |
GAME_WIN | |
GAME_LOSE | |
GAME_TIMEOUT | |
GAME_ERR | |
) | |
type Hangman struct { | |
Entries map[string]bool | |
Placeholder []string | |
chances int | |
word string | |
duration time.Duration // game duration | |
input io.Reader | |
} | |
func get_keys(entries map[string]bool) (keys []string) { | |
for k, _ := range entries { | |
keys = append(keys, k) | |
} | |
return | |
} | |
func get_word() string { | |
if *dev { | |
return "elephant" | |
} | |
resp, err := http.Get("https://random-word-api.herokuapp.com/word?number=5") | |
if err != nil { | |
return "elephant" | |
} | |
defer resp.Body.Close() | |
body, err := ioutil.ReadAll(resp.Body) | |
var words []string | |
err = json.Unmarshal(body, &words) | |
if err != nil { | |
// handle error | |
return "elephant" | |
} | |
//fmt.Println(words) | |
for _, word := range words { | |
if len(word) > 4 && len(word) < 9 { | |
return word | |
} | |
} | |
return words[0] | |
} | |
func (h *Hangman) Render(status uint) { | |
switch status { | |
case GAME_PLAY: | |
fmt.Println(h.Placeholder) // render the placeholder | |
fmt.Printf("Chances: %d\n", h.chances) // render the chances left | |
fmt.Printf("Entries: %v\n", get_keys(h.Entries)) // show the letters or words guessed till now. | |
fmt.Printf("Guess a letter or the word: ") | |
case GAME_WIN: | |
fmt.Println("You win!!") | |
case GAME_LOSE: | |
fmt.Println("You're out of chances") | |
fmt.Println("Word was: ", h.word) | |
fmt.Println("Game Over! Try again") | |
case GAME_ERR: | |
fmt.Println("Something wrong with getting input") | |
case GAME_TIMEOUT: | |
fmt.Println("Timedout... too bad!") | |
} | |
} | |
func (h *Hangman) GetInput() (str string) { | |
str = "" | |
fmt.Scanln(&str) | |
return | |
} | |
func get_input(input io.Reader) (str string, err error) { | |
scanner := bufio.NewScanner(input) | |
if scanner.Scan() { // scan one line | |
str = scanner.Text() | |
return | |
} | |
err = scanner.Err() | |
return | |
} | |
func play(h *Hangman, result chan bool) { | |
for { | |
// evaluate a loss! If user guesses a wrong letter or the wrong word, they lose a chance. | |
userInput := strings.Join(h.Placeholder, "") | |
if h.chances == 0 && userInput != h.word { | |
h.Render(GAME_LOSE) | |
result <- false | |
return | |
} | |
// evaluate a win! | |
if userInput == h.word { | |
h.Render(GAME_WIN) | |
result <- true | |
return | |
} | |
// Console display | |
h.Render(GAME_PLAY) | |
// Addon validation: Allow only alpha! | |
// Addon validation: manage case! | |
str := h.GetInput() | |
// if len(str) > 2, compare the word with the str | |
if len(str) > 2 { | |
if str == h.word { | |
h.Render(GAME_WIN) | |
result <- true | |
return | |
} else { | |
// you lose a chance | |
h.Entries[str] = true | |
h.chances -= 1 | |
continue | |
} | |
} | |
// compare and update entries, placeholder and chances. | |
_, ok := h.Entries[str] | |
if ok { | |
// key exists already; duplicate | |
continue | |
} | |
h.Entries[str] = true | |
// check if letter exists in the word! | |
found := false | |
for i, v := range h.word { | |
if str == string(v) { | |
h.Placeholder[i] = string(v) | |
found = true | |
} | |
} | |
if !found { | |
h.chances -= 1 | |
} | |
} | |
} | |
func main() { | |
flag.Parse() | |
h := Hangman{ | |
Entries: map[string]bool{}, | |
Placeholder: []string{}, | |
chances: 8, | |
duration: 2 * time.Minute, | |
} | |
h.word = get_word() | |
// get length of the word len(word) | |
// initialize slice with each element as "_" | |
for i := 0; i < len(h.word); i++ { | |
h.Placeholder = append(h.Placeholder, "_") | |
//placeholder[i] = "_" | |
} | |
t := time.NewTimer(h.duration) | |
result := make(chan bool) | |
go play(&h, result) | |
// Wait on either game to finish or timeout! | |
select { | |
case <-result: | |
case <-t.C: | |
h.Render(GAME_TIMEOUT) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment