commit 7b5dfd867d0ee83eecd71b53b390c15578cffcee Author: dm1sh Date: Thu Jul 7 23:59:43 2022 +0300 Added basic implementation diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ce5dd4d --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module dm1sh/gordle + +go 1.18 + +require github.com/fatih/color v1.13.0 + +require ( + github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6ab7ee4 --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/gordle.go b/gordle.go new file mode 100644 index 0000000..8f6f691 --- /dev/null +++ b/gordle.go @@ -0,0 +1,150 @@ +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) + + var nFlag = flag.Int("n", 5, "Word size") + flag.Parse() + nChar := *nFlag + + fmt.Println("Welcome to Gordle - go implementation of Wordle game") + + file, err := os.Open(fmt.Sprintf("./dictionary/%d.txt", nChar+1)) + + 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()) + } + + 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 +}