diff --git a/game.go b/game.go new file mode 100644 index 0000000..39d855d --- /dev/null +++ b/game.go @@ -0,0 +1,103 @@ +package main + +import ( + "strings" +) + +type CellStatus int + +const ( + STATUS_EMPTY CellStatus = 0 + STATUS_CORRECT CellStatus = 1 + STATUS_INCORRECT CellStatus = 2 + STATUS_WRONG CellStatus = 3 +) + +type GridCell struct { + Letter string + Status CellStatus +} + +type Grid = [][]GridCell + +type Game interface { + Play(word string) (bool, error) + HasEnded() bool + GetScore() (int, int) + OutputForConsole() string +} + +type game struct { + complete bool + attempts int + answer string + grid Grid +} + +func (g *game) Play(word string) (bool, error) { + // TODO check the word length here and error if too long/short + + // Create the row for the grid + parts := strings.Split(word, "") + answerParts := strings.Split(g.answer, "") + row := make([]GridCell, len(parts)) + numCorrect := 0 + for i, chr := range parts { + var status CellStatus + if chr == answerParts[i] { + status = STATUS_CORRECT + numCorrect++ + } else if stringInSlice(chr, answerParts) { + status = STATUS_INCORRECT + } else { + status = STATUS_WRONG + } + + row[i] = GridCell{chr, status} + } + + // Update the game + g.grid[g.attempts] = row + g.attempts++ + + return word == g.answer, nil +} + +func (g *game) HasEnded() bool { + return g.complete || g.attempts == len(g.grid) +} + +func (g *game) GetScore() (int, int) { + return g.attempts, len(g.grid) +} + +func (g *game) OutputForConsole() string { + str := "\n" + strings.Repeat("-", len(g.answer)+2) + "\n" + for _, row := range g.grid { + if len(row) == 0 { + break + } + + str += "|" + for _, cell := range row { + switch cell.Status { + case STATUS_CORRECT: + str += COLOUR_GREEN + case STATUS_INCORRECT: + str += COLOUR_YELLOW + } + str += cell.Letter + COLOUR_RESET + } + str += "|\n" + } + str += strings.Repeat("-", len(g.answer)+2) + "\n" + + return str +} + +// TODO include valid entries +func CreateGame(answer string, tries int) Game { + grid := make([][]GridCell, tries) + + return &game{false, 0, answer, grid} +} diff --git a/helpers.go b/helpers.go new file mode 100644 index 0000000..48918f9 --- /dev/null +++ b/helpers.go @@ -0,0 +1,10 @@ +package main + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/main.go b/main.go index 6f692c3..9f6d8ec 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "flag" "fmt" "os" "sort" @@ -34,6 +35,35 @@ var answersIncorrectAll []string var board []string func main() { + wordPtr := flag.String("word", "tapir", "The game's answer") + playPtr := flag.Bool("play", false, "Whether to play the game") + flag.Parse() + + reader := bufio.NewReader(os.Stdin) + + if *playPtr { + g := CreateGame(*wordPtr, NUM_ATTEMPTS) + + for { + fmt.Print("Enter your guess: ") + input, _ := reader.ReadString('\n') + word := strings.TrimSpace(input) + + success, _ := g.Play(word) + + fmt.Println(g.OutputForConsole()) + + if success { + score, of := g.GetScore() + fmt.Printf("Great work! %d/%d\n", score, of) + return + } else if g.HasEnded() { + fmt.Printf("Better luck next time! X/%d\n", NUM_ATTEMPTS) + return + } + } + } + // Read the valid words fmt.Println("Reading words...") err := readValidWords() @@ -42,7 +72,6 @@ func main() { answersCorrect = make([]string, NUM_LETTERS) answersIncorrect = make([][]string, NUM_LETTERS) - reader := bufio.NewReader(os.Stdin) for { // Generate histogram fmt.Println("Building histogram...") diff --git a/wordle b/wordle index e6b16de..eae32c7 100755 Binary files a/wordle and b/wordle differ