Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
188
Task/Mastermind/Go/mastermind.go
Normal file
188
Task/Mastermind/Go/mastermind.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("mastermind: ")
|
||||
log.SetFlags(0)
|
||||
colours := flag.Int("colours", 6, "number of colours to use (2-20)")
|
||||
flag.IntVar(colours, "colors", 6, "alias for colours")
|
||||
holes := flag.Int("holes", 4, "number of holes (the code length, 4-10)")
|
||||
guesses := flag.Int("guesses", 12, "number of guesses allowed (7-20)")
|
||||
unique := flag.Bool("unique", false, "disallow duplicate colours in the code")
|
||||
flag.Parse()
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
m, err := NewMastermind(*colours, *holes, *guesses, *unique)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = m.Play()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
type mastermind struct {
|
||||
colours int
|
||||
holes int
|
||||
guesses int
|
||||
unique bool
|
||||
|
||||
code string
|
||||
past []string // history of guesses
|
||||
scores []string // history of scores
|
||||
}
|
||||
|
||||
func NewMastermind(colours, holes, guesses int, unique bool) (*mastermind, error) {
|
||||
if colours < 2 || colours > 20 {
|
||||
return nil, errors.New("colours must be between 2 and 20 inclusive")
|
||||
}
|
||||
if holes < 4 || holes > 10 {
|
||||
return nil, errors.New("holes must be between 4 and 10 inclusive")
|
||||
}
|
||||
if guesses < 7 || guesses > 20 {
|
||||
return nil, errors.New("guesses must be between 7 and 20 inclusive")
|
||||
}
|
||||
if unique && holes > colours {
|
||||
return nil, errors.New("holes must be > colours when using unique")
|
||||
}
|
||||
|
||||
return &mastermind{
|
||||
colours: colours,
|
||||
holes: holes,
|
||||
guesses: guesses,
|
||||
unique: unique,
|
||||
past: make([]string, 0, guesses),
|
||||
scores: make([]string, 0, guesses),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mastermind) Play() error {
|
||||
m.generateCode()
|
||||
fmt.Printf("A set of %s has been selected as the code.\n", m.describeCode(m.unique))
|
||||
fmt.Printf("You have %d guesses.\n", m.guesses)
|
||||
for len(m.past) < m.guesses {
|
||||
guess, err := m.inputGuess()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println()
|
||||
m.past = append(m.past, guess)
|
||||
str, won := m.scoreString(m.score(guess))
|
||||
if won {
|
||||
plural := "es"
|
||||
if len(m.past) == 1 {
|
||||
plural = ""
|
||||
}
|
||||
fmt.Printf("You found the code in %d guess%s.\n", len(m.past), plural)
|
||||
return nil
|
||||
}
|
||||
m.scores = append(m.scores, str)
|
||||
m.printHistory()
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Printf("You are out of guesses. The code was %s.\n", m.code)
|
||||
return nil
|
||||
}
|
||||
|
||||
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
const blacks = "XXXXXXXXXX"
|
||||
const whites = "OOOOOOOOOO"
|
||||
const nones = "----------"
|
||||
|
||||
func (m *mastermind) describeCode(unique bool) string {
|
||||
ustr := ""
|
||||
if unique {
|
||||
ustr = " unique"
|
||||
}
|
||||
return fmt.Sprintf("%d%s letters (from 'A' to %q)",
|
||||
m.holes, ustr, charset[m.colours-1],
|
||||
)
|
||||
}
|
||||
|
||||
func (m *mastermind) printHistory() {
|
||||
for i, g := range m.past {
|
||||
fmt.Printf("-----%s---%[1]s--\n", nones[:m.holes])
|
||||
fmt.Printf("%2d: %s : %s\n", i+1, g, m.scores[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mastermind) generateCode() {
|
||||
code := make([]byte, m.holes)
|
||||
if m.unique {
|
||||
p := rand.Perm(m.colours)
|
||||
for i := range code {
|
||||
code[i] = charset[p[i]]
|
||||
}
|
||||
} else {
|
||||
for i := range code {
|
||||
code[i] = charset[rand.Intn(m.colours)]
|
||||
}
|
||||
}
|
||||
m.code = string(code)
|
||||
//log.Printf("code is %q", m.code)
|
||||
}
|
||||
|
||||
func (m *mastermind) inputGuess() (string, error) {
|
||||
var input string
|
||||
for {
|
||||
fmt.Printf("Enter guess #%d: ", len(m.past)+1)
|
||||
if _, err := fmt.Scanln(&input); err != nil {
|
||||
return "", err
|
||||
}
|
||||
input = strings.ToUpper(strings.TrimSpace(input))
|
||||
if m.validGuess(input) {
|
||||
return input, nil
|
||||
}
|
||||
fmt.Printf("A guess must consist of %s.\n", m.describeCode(false))
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mastermind) validGuess(input string) bool {
|
||||
if len(input) != m.holes {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(input); i++ {
|
||||
c := input[i]
|
||||
if c < 'A' || c > charset[m.colours-1] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *mastermind) score(guess string) (black, white int) {
|
||||
scored := make([]bool, m.holes)
|
||||
for i := 0; i < len(guess); i++ {
|
||||
if guess[i] == m.code[i] {
|
||||
black++
|
||||
scored[i] = true
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(guess); i++ {
|
||||
if guess[i] == m.code[i] {
|
||||
continue
|
||||
}
|
||||
for j := 0; j < len(m.code); j++ {
|
||||
if i != j && !scored[j] && guess[i] == m.code[j] {
|
||||
white++
|
||||
scored[j] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *mastermind) scoreString(black, white int) (string, bool) {
|
||||
none := m.holes - black - white
|
||||
return blacks[:black] + whites[:white] + nones[:none], black == m.holes
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue