76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Player interface {
|
|
Mark() string
|
|
MakeMove(b *Board) bool
|
|
}
|
|
|
|
type Human struct {
|
|
mark string
|
|
}
|
|
|
|
func NewHuman(m string) *Human {
|
|
return &Human{mark: m}
|
|
}
|
|
|
|
func (h *Human) Mark() string { return h.mark }
|
|
|
|
// MakeMove marks the board
|
|
// returns false if the player wants to stop
|
|
func (h *Human) MakeMove(b *Board) bool {
|
|
for {
|
|
sq, stop, err := AskInput()
|
|
if err != nil {
|
|
fmt.Printf("That didn't work: %v\n", err)
|
|
fmt.Println("Try again, or press ctrl-c to abort.")
|
|
continue
|
|
}
|
|
if stop {
|
|
return false
|
|
}
|
|
|
|
if ok := b.Mark(sq, h.mark); !ok {
|
|
fmt.Println("That square was already taken. Sorry.")
|
|
|
|
av := make([]string, 0)
|
|
for _, a := range b.Available() {
|
|
av = append(av, fmt.Sprintf("%d", a))
|
|
}
|
|
fmt.Printf("Open squares are: %s\n", strings.Join(av, ", "))
|
|
continue
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
// AskInput waits for user input.
|
|
// returns the square, a request to stop, or an error
|
|
func AskInput() (int, bool, error) {
|
|
fmt.Println("Enter 0-8 to mark a square, or q to quit:")
|
|
|
|
var input string
|
|
count, err := fmt.Scan(&input)
|
|
if err != nil {
|
|
return 0, false, err
|
|
}
|
|
if count != 1 {
|
|
return 0, false, fmt.Errorf("one can only mark a single square per turn")
|
|
}
|
|
if input == "q" {
|
|
return 0, true, nil
|
|
}
|
|
sq, err := strconv.Atoi(input)
|
|
if err != nil || sq < 0 || sq > 8 {
|
|
return 0, false, fmt.Errorf("squares are indicated by the numbers 0 to 8")
|
|
}
|
|
|
|
return sq, false, nil
|
|
}
|