package main import ( "fmt" ) func PlayGame(numPlayers int) { currentPlayer := 0 runningScores := make([]int, numPlayers) for round := 3; round < 14; round++ { r := NewRound(round, numPlayers, currentPlayer) roundScores := r.Play() currentPlayer = r.currentPlayer for p := 0; p < numPlayers; p++ { runningScores[p] += roundScores[p] } fmt.Printf("The round has ended\n") fmt.Printf("Running total scores: %v\n", runningScores) } fmt.Printf("The game has ended\n") } type Round struct { d []Card discard []Card round int numPlayers int currentPlayer int hands [][]Card } func NewRound(round, numPlayers, currentPlayer int) *Round { r := Round{ round: round, numPlayers: numPlayers, currentPlayer: currentPlayer, } r.d = Deck() Shuffle(r.d) r.discard = []Card{} fmt.Printf("# Round %d\n\n", r.round) // Deal starting cards r.hands = make([][]Card, numPlayers) for p := 0; p < numPlayers; p++ { r.hands[p] = r.d[0:round] // Deal from the bottom (0) r.d = r.d[round:] fmt.Printf("P%d starting hand: %v\n", p, r.hands[p]) } // Deal one into the discard pile r.discard = append(r.discard, r.d[0]) r.d = r.d[1:] // Done return &r } func FormatHandGroupings(hand []Card, groupings [][]int) string { tmp := forkHand(hand) cgroups := [][]Card{} for _, group := range groupings { cgroup := []Card{} for _, cidx := range group { cgroup = append(cgroup, hand[cidx]) tmp[cidx] = Card(-1) } cgroups = append(cgroups, cgroup) } leftover := []Card{} for _, cv := range tmp { if cv != Card(-1) { leftover = append(leftover, cv) } } return fmt.Sprintf("[ %v leftover %v ]", cgroups, leftover) } func (r *Round) Play() []int { fmt.Printf("Discard stack: %v\n", r.discard) fmt.Printf("Deck has %d cards remaining\n", len(r.d)) roundEndsWhenPlayerIs := -1 for { if roundEndsWhenPlayerIs == r.currentPlayer { break } // Play the strategy for the current player r.PlayDefaultStrategy() // Check, one more time, if we have a winning hand currentBestGrouping, currentScore := FindBestGrouping(r.hands[r.currentPlayer], r.round) if currentScore == 0 { // Declare victory fmt.Printf("P%d declares victory\n- Hand: %v\n- Groupings: %v\n", r.currentPlayer, r.hands[r.currentPlayer], currentBestGrouping) if roundEndsWhenPlayerIs == -1 { roundEndsWhenPlayerIs = r.currentPlayer } // Otherwise, the round is already ending anyway } // Move to the next player r.currentPlayer = (r.currentPlayer + 1) % r.numPlayers } // The round has ended // Figure out what each player scored roundScores := make([]int, r.numPlayers) for p := 0; p < r.numPlayers; p++ { gr, score := FindBestGrouping(r.hands[p], r.round) fmt.Printf("P%d has %v (score: %d)\n", p, FormatHandGroupings(r.hands[p], gr) /*r.hands[p], gr,*/, score) roundScores[p] = score } // Check stack alignment if len(r.discard)+len(r.d)+(r.numPlayers*len(r.hands[0])) != DeckSize { panic("Cards on the floor") } // Done return roundScores }