Skip to content

Instantly share code, notes, and snippets.

@trafficone
Last active February 11, 2022 22:27
Show Gist options
  • Save trafficone/c76c1e63900b64dc7e30d3c8cfa46ebc to your computer and use it in GitHub Desktop.
Save trafficone/c76c1e63900b64dc7e30d3c8cfa46ebc to your computer and use it in GitHub Desktop.
Word Guessing Game
package main
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"math"
"math/rand"
"os"
"strings"
"time"
)
// grep '^\w\{5\}$' /usr/share/dict/words | tr '[:upper:]' '[:lower:]' | sort -u > five_letter_words
const WORDLEN = 5
const WORDFILE = "five_letter_words"
func load_words(wordfile string) (*[]string, error) {
file, err := ioutil.ReadFile(wordfile)
if err != nil {
return nil, fmt.Errorf("Could not read from file %s: error: %s", wordfile, err)
}
words := strings.Split(string(file[:]), "\n")
return &words, nil
}
func evaluate_guess(guess_str, actual_str string, words *[]string) (string, error) {
// First see if guess is in words, invalid guesses are rejected
// Since words is sorted, we binary search
i := 0
v := 0
found := false
guess := []rune(guess_str)
actual := []rune(actual_str)
words_length := len(*words)
running := true
for j := words_length - 2; running; j = int(math.Round(float64(j) / 2.0)) {
if j == 1 {
running = false
}
check_index := i + j
if check_index > words_length {
break
}
check := (*words)[check_index]
v = strings.Compare(guess_str, check)
if v == 0 {
found = true
break
} else if v > 0 {
i += j
}
}
if !found {
return "", errors.New("Guess not valid")
}
output := make([]rune, WORDLEN)
for i := 0; i < WORDLEN; i++ {
output[i] = rune('✖')
}
for i := 0; i < WORDLEN; i++ {
if guess[i] == actual[i] {
output[i] = rune('◎')
actual[i] = rune(' ')
}
}
for i := 0; i < WORDLEN; i++ {
for j := 0; j < WORDLEN; j++ {
if i != j && output[i] != rune('◎') && guess[i] == actual[j] {
output[i] = rune('〇')
actual[j] = rune(' ')
}
}
}
return string(output), nil
}
func main() {
fmt.Println("Welcome to WeirdIe")
fmt.Printf("Guess the %d letter word I'm thinking of\n", WORDLEN)
fmt.Println("In 6 guesses or fewer!")
rand.Seed(time.Now().UnixNano())
words, _ := load_words(WORDFILE)
actual := (*words)[rand.Intn(len(*words))]
reader := bufio.NewReader(os.Stdin)
for i := 1; i <= 6; i++ {
guess := ""
for {
fmt.Printf("%d > ", i)
guess, _ = reader.ReadString('\n')
guess = strings.Replace(guess, "\n", "", -1)
guess = strings.Replace(guess, "\r", "", -1)
if len(guess) != WORDLEN {
fmt.Printf("Guess must be %d letters, try again\n", WORDLEN)
continue
}
result, err := evaluate_guess(guess, actual, words)
if err != nil {
fmt.Println(err)
} else {
fmt.Printf(" %s\n", result)
break
}
}
if guess == actual {
fmt.Printf("You won in %d turns!\n", i)
return
}
}
fmt.Printf("Sorry, the word was \"%s\"\n", actual)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment