package main import ( "flag" "fmt" "log" "math" "math/rand" "sync" "time" ) func main() { numPlayers := flag.Int("n", 2, "Number of players") sides := flag.Int("sides", 6, "How many sides the die should have") flag.Parse() if *numPlayers < 2 { log.Fatalf("we need at least 2 players") } if *sides < 2 { log.Fatalf("die needs at least two sides") } fmt.Println("Welcome to the game") fmt.Printf("There are %d players, each with a %d-sided die\n", *numPlayers, *sides) game(*numPlayers, *sides) } type Player struct { id int score int } // The player with the lowest score wins. func game(numPlayers, faces int) { // Get the game's winning number by throwing the die once. winningNumber := throwDie(faces) fmt.Printf("Winning number is %d\n", winningNumber) // The finishedPlayers channel communicates the number of turns a // player took to hit the winning number. finishedPlayers := make(chan Player) var wg sync.WaitGroup for i := range numPlayers { id := i + 1 // Spawn a player. wg.Go(func() { var score int // Start rolling the dice! for { score++ outcome := throwDie(faces) if outcome == winningNumber { fmt.Printf("Player %d threw a %d: the winning number! Their score is %d\n", id, winningNumber, score) finishedPlayers <- Player{id: id, score: score} return } fmt.Printf("Player %d threw a %d\n", id, outcome) time.Sleep(1 * time.Second) } }) } go func() { wg.Wait() close(finishedPlayers) }() minPlayer := Player{score: math.MaxInt} for player := range finishedPlayers { if player.score < minPlayer.score { minPlayer = player } } fmt.Printf("Player %d won with a score of %d\n", minPlayer.id, minPlayer.score) fmt.Println("Thanks for playing!") } func throwDie(faces int) int { return rand.Intn(faces) + 1 }