Skip to content

Instantly share code, notes, and snippets.

@iporsut
Last active September 23, 2018 08:17
Show Gist options
  • Save iporsut/ac18ee59f95ec7c19da4ad76c5f5f8e2 to your computer and use it in GitHub Desktop.
Save iporsut/ac18ee59f95ec7c19da4ad76c5f5f8e2 to your computer and use it in GitHub Desktop.
Hangman The Series
package main
import (
"fmt"
)
func hangman(secretWord string, letters []rune) bool {
secrets := []rune(secretWord)
for _, s := range secrets {
var found bool
for _, l := range letters {
if s == l {
found = true
break
}
}
if !found {
return false
}
}
return true
}
func main() {
fmt.Println(hangman("bigbears", []rune{'a','e','i','o','u','c','d','p','r','k','l','j','h'}))
fmt.Println(hangman("bigbears", []rune{'a','e','i','b','r','g','s'}))
}
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type Status int
const (
InProcess Status = iota
Win
Lose
)
func (s Status) String() string {
switch s {
case InProcess:
return "in-process"
case Win:
return "win"
case Lose:
return "lose"
default:
return ""
}
}
type Result struct {
status Status
selectedLetters []rune
liftLeft int
secretWordLength int
knownSecretWord string
}
func (r *Result) Display() {
fmt.Println("Status:", r.status)
fmt.Println("Life:", r.liftLeft)
fmt.Println("knownSecretWord:", r.knownSecretWord)
}
func hangman(secretWord string, letterCh chan rune) chan Result {
resultCh := make(chan Result)
go func() {
secrets := []rune(secretWord)
// Current Result
cr := Result{
status: InProcess,
selectedLetters: []rune{},
liftLeft: 7,
secretWordLength: len(secretWord),
knownSecretWord: strings.Repeat("_", len(secretWord)),
}
resultCh <- cr
for l := range letterCh {
cr.selectedLetters = append(cr.selectedLetters, l)
var foundIndex []int
for i, s := range secrets {
if l == s {
foundIndex = append(foundIndex, i)
}
}
if len(foundIndex) == 0 {
cr.liftLeft--
} else {
ksw := []rune(cr.knownSecretWord)
for _, i := range foundIndex {
ksw[i] = l
}
cr.knownSecretWord = string(ksw)
}
if cr.liftLeft == 0 {
cr.status = Lose
resultCh <- cr
break
}
if secretWord == cr.knownSecretWord {
cr.status = Win
resultCh <- cr
break
}
resultCh <- cr
}
close(resultCh)
}()
return resultCh
}
func main() {
letterCh := make(chan rune)
resultCh := hangman("bigbear", letterCh)
result := <-resultCh
result.Display()
scanner := bufio.NewScanner(os.Stdin)
for {
fmt.Print("Enter Letter: ")
fmt.Scanf("")
if scanner.Scan() {
ls := []rune(scanner.Text())
letterCh <- ls[0]
} else {
close(letterCh)
return
}
result := <-resultCh
result.Display()
if result.status != InProcess {
close(letterCh)
return
}
}
}
package main
import (
"testing"
)
func TestHangmanNewGame(t *testing.T) {
letterCh := make(chan rune)
resultCh := hangman("bigbear", letterCh)
defer func() {
close(letterCh)
}()
result := <-resultCh
if result.status != InProcess {
t.Fatal("status shound be in-process")
}
if result.liftLeft != 7 {
t.Fatal("lift left should be 7")
}
if string(result.selectedLetters) != "" {
t.Fatal("selectedLetters should be empty")
}
if result.knownSecretWord != "_______" {
t.Fatal("knownSecretWord should be _______")
}
}
func TestHangmanWin(t *testing.T) {
letterCh := make(chan rune)
resultCh := hangman("bigbear", letterCh)
defer func() {
close(letterCh)
}()
go func() {
for _, l := range []rune{'b', 'o', 'i', 'g', 'a', 'e', 'y', 'r'} {
letterCh <- l
}
}()
var result Result
for result = range resultCh {
// fetch result until win
if result.status == Win {
break
}
if result.status != InProcess {
t.Fatal("status shound be in-process")
}
}
if result.status != Win {
t.Fatal("status shound be win")
}
if result.liftLeft != 5 {
t.Fatal("lift left should be 5")
}
if string(result.selectedLetters) != "boigaeyr" {
t.Fatal("selectedLetters should be boigaeyr")
}
if result.knownSecretWord != "bigbear" {
t.Fatal("knownSecretWord should be bigbear")
}
}
func TestHangmanLose(t *testing.T) {
letterCh := make(chan rune)
resultCh := hangman("bigbear", letterCh)
defer func() {
close(letterCh)
}()
go func() {
for _, l := range []rune{'b', 'o', 'a', 'e', 'n', 'u', 't', 'z', 'x', 'v'} {
letterCh <- l
}
}()
var result Result
for result = range resultCh {
// fetch result until lose
if result.status == Lose {
break
}
if result.status != InProcess {
t.Fatal("status shound be in-process")
}
}
if result.status != Lose {
t.Fatal("status shound be lose")
}
if result.liftLeft != 0 {
t.Fatal("lift left should be 0")
}
if string(result.selectedLetters) != "boaenutzxv" {
t.Fatal("selectedLetters should be boaenutzxv")
}
if result.knownSecretWord != "b__bea_" {
t.Fatal("knownSecretWord should be b__bea_")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment