159 lines
3.1 KiB
Go
159 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"math/rand"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/fatih/color"
|
|
)
|
|
|
|
type CharacterStatus byte
|
|
|
|
const (
|
|
RIGHT CharacterStatus = iota
|
|
CONTAINS
|
|
WRONG
|
|
)
|
|
|
|
func main() {
|
|
rightOutput := color.New(color.BgGreen, color.FgBlack)
|
|
containsOutput := color.New(color.BgYellow, color.FgBlack)
|
|
wrongOutput := color.New(color.BgWhite, color.FgBlack)
|
|
|
|
nFlag := flag.Int("n", 5, "Word size")
|
|
fFlag := flag.String("f", "./dictionary/5.txt", "Path to dictionary file with words of length -n. If specified, -n must be specified too (if the latter must not be equal to default value")
|
|
|
|
flag.Parse()
|
|
|
|
fmt.Println("Welcome to Gordle - go implementation of Wordle game")
|
|
|
|
nChar := *nFlag
|
|
filePath := *fFlag
|
|
|
|
file, err := os.Open(filePath)
|
|
|
|
if err != nil {
|
|
log.Fatal("There is no dictionary with such amount of letters")
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
|
|
words := []string{}
|
|
|
|
for scanner.Scan() {
|
|
words = append(words, scanner.Text())
|
|
}
|
|
|
|
if len(words[0]) != nChar {
|
|
log.Fatal("Words in dictionary must be of size", nChar)
|
|
}
|
|
|
|
fmt.Printf("You are going to guess a %d letter word in %d tries from %d dictionary\n", nChar, nChar+1, len(words))
|
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
ind := rand.Intn(len(words))
|
|
|
|
chosen := words[ind]
|
|
|
|
inpScanner := bufio.NewScanner(os.Stdin)
|
|
|
|
var nTries = 1
|
|
|
|
for nTries <= nChar+1 {
|
|
inpScanner.Scan()
|
|
input := inpScanner.Text()
|
|
|
|
moveConsoleCursorUp()
|
|
|
|
if len(input) != nChar {
|
|
fmt.Printf("Wrong number of letters in your input. Remember, you need to input %d character words.\n", nChar)
|
|
continue
|
|
}
|
|
|
|
if input == chosen {
|
|
color.Green(input)
|
|
fmt.Printf("Congratulations, you have found the right word on %d try!\n", nTries)
|
|
os.Exit(0)
|
|
}
|
|
|
|
if !BinSearch(words, input) {
|
|
fmt.Printf("The word you entered: %s is not contained in the dictionary\n", input)
|
|
continue
|
|
}
|
|
|
|
nTries++
|
|
|
|
comparitionResult := CompareStrings(input, chosen)
|
|
|
|
for pos, chr := range input {
|
|
switch comparitionResult[pos] {
|
|
case RIGHT:
|
|
rightOutput.Print(string(chr))
|
|
case CONTAINS:
|
|
containsOutput.Print(string(chr))
|
|
case WRONG:
|
|
wrongOutput.Print(string(chr))
|
|
}
|
|
}
|
|
|
|
fmt.Print("\n")
|
|
}
|
|
|
|
fmt.Println("Unfortunately, you lost. Puzzled word was", chosen)
|
|
}
|
|
|
|
func moveConsoleCursorUp() {
|
|
fmt.Print("\033[1A")
|
|
}
|
|
|
|
func CompareStrings(input, chosen string) []CharacterStatus {
|
|
inputReader := strings.NewReader(input)
|
|
chosenReader := strings.NewReader(chosen)
|
|
|
|
result := make([]CharacterStatus, len(input))
|
|
|
|
for i := 0; ; i++ {
|
|
inputRune, _, err1 := inputReader.ReadRune()
|
|
chosenRune, _, err2 := chosenReader.ReadRune()
|
|
|
|
if err1 != nil || err2 != nil {
|
|
return result
|
|
}
|
|
|
|
if inputRune == chosenRune {
|
|
result[i] = RIGHT
|
|
} else if strings.ContainsRune(chosen, inputRune) {
|
|
result[i] = CONTAINS
|
|
} else {
|
|
result[i] = WRONG
|
|
}
|
|
}
|
|
}
|
|
|
|
func BinSearch(arr []string, el string) bool {
|
|
begin, end := 0, len(arr)-1
|
|
|
|
for begin <= end {
|
|
middle := begin + (end-begin)/2
|
|
|
|
if el > arr[middle] {
|
|
begin = middle + 1
|
|
} else if el < arr[middle] {
|
|
end = middle - 1
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|