-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwordle_engine.go
87 lines (78 loc) · 2.22 KB
/
wordle_engine.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package wordle
import (
"crypto/rand"
"math/big"
"os"
"strings"
)
// WordleEngine represents a Wordle game engine and
// the dictionary and settings for running Wordle games.
type WordleEngine struct {
Dictionary []string
DictionaryMap map[string]struct{}
MaxAttempts int
CurrentGame *WordleGame
}
// NewWordleEngine returns a pointer to a [wordle.WordleEngine],
// using the dictionary at the path provided, and a maximum
// number of attempts.
//
// The dictionaryPath parameter should point to a newline
// terminated list of equal-[rune]-length word strings.
func NewWordleEngine(dictionaryPath string, maxAttempts int) (*WordleEngine, error) {
dictionary, err := openDictionary(dictionaryPath)
if err != nil {
return nil, err
}
dictionaryMap := make(map[string]struct{})
for _, word := range dictionary {
dictionaryMap[word] = struct{}{}
}
return &WordleEngine{
Dictionary: dictionary,
DictionaryMap: dictionaryMap,
MaxAttempts: maxAttempts,
}, nil
}
// NewGame starts instantiates a new *WordleGame when there is no
// previous game in [wordle.WordleEngine.CurrentGame], or the
// previous game is over.
func (we *WordleEngine) NewGame() error {
if we.CurrentGame == nil || we.CurrentGame.Status == WordleGameStatusGameOver {
word, err := we.RandomDictionaryWord()
if err != nil {
return err
}
we.CurrentGame = &WordleGame{
Answer: []rune(word),
MaxAttempts: we.MaxAttempts,
Status: WordleGameStatusPlaying,
}
} else {
return &WordleError{
Status: WordleGameStatusPlaying,
}
}
return nil
}
// Fetch a random word from the dictionary in our engine.
//
// Used to start a new game, or can be used to test valid words.
func (we *WordleEngine) RandomDictionaryWord() (string, error) {
i, err := rand.Int(rand.Reader, big.NewInt(int64(len(we.Dictionary))))
if err != nil {
return "", nil
}
return we.Dictionary[i.Int64()], nil
}
// openDictionary reads a newline terminated dictionary file
// containing equal-length words, and returns the words as a
// slice of [string] values.
func openDictionary(path string) ([]string, error) {
file, err := os.ReadFile(path)
if err != nil {
return nil, err
}
dictionary := strings.Split(string(file), "\n")
return dictionary, nil
}