Go Fish/Go: Difference between revisions

From Rosetta Code
Content added Content deleted
(Less idiosyncratic and gofmt'ed.)
(Improved quality.)
Line 54: Line 54:
card := gm.deck[0]
card := gm.deck[0]
gm.deck = gm.deck[1:]
gm.deck = gm.deck[1:]
if gm.turn == 0 {
if gm.isPlayerTurn() {
fmt.Printf("You drew a %s.\n", card)
fmt.Printf("You drew a %s.\n", card)
}
}
Line 60: Line 60:
//Check for books
//Check for books
gm.checkForBooks()
gm.checkForBooks()
}
}

// endPly ends the current person's turn.
// It then either calls the next person's
// turn or prints a game over message.
func (gm *GoFishGame) endPly() {
gameOver := gm.isGameOver()
if gameOver {
gm.printGameOverMessage()
} else if gm.turn == 1 {
gm.playerTurn(getPickComputer)
} else {
gm.playerTurn(getPickUser)
}
}
}
}
Line 114: Line 100:
func (gm *GoFishGame) isGameOver() bool {
func (gm *GoFishGame) isGameOver() bool {
return gm.scores[0]+gm.scores[1] == 13
return gm.scores[0]+gm.scores[1] == 13
}

// isPlayerTurn returns if its the player's turn to move.
func (gm *GoFishGame) isPlayerTurn() bool {
return gm.turn == 0
}
}


Line 167: Line 158:
}
}
}
}
gm.endPly()
}
}


Line 192: Line 182:
func (gm *GoFishGame) stealCards(purge string, side int) int {
func (gm *GoFishGame) stealCards(purge string, side int) int {
count := 0
count := 0
tList := gm.hands[side]
var filtered []string
var filtered []string
for _, card := range tList {
for _, card := range gm.hands[side] {
if purge == card {
if purge == card {
count++
count++
Line 218: Line 207:
scores[1] = 0
scores[1] = 0
game := GoFishGame{hands, deck, 0, scores}
game := GoFishGame{hands, deck, 0, scores}
for {
game.playerTurn(getPickUser)
if game.isPlayerTurn() {
game.playerTurn(getPickUser)
} else {
game.playerTurn(getPickComputer)
}
if game.isGameOver() {
break
}
}
game.printGameOverMessage()

}
}

</lang>
</lang>

Revision as of 05:19, 12 September 2015

The AI selects cards randomly from its hand.


<lang go> package main

import ( "fmt" "math/rand" "sort" "time" )

var cards = [13]string{"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}

//GoFishGame Stores the game state. type GoFishGame struct { hands [][]string deck []string turn int scores []int }

// checkForBooks looks for fours of a kind // and scores them if we have them. // If we run out of cards, we draw more. func (gm *GoFishGame) checkForBooks() { sort.Strings(gm.hands[gm.turn]) prev := "" count := 1 for _, card := range gm.hands[gm.turn] { if card == prev { count++ if count == 4 { fmt.Printf("Book of %s.\n", card) gm.stealCards(card, gm.turn) gm.scores[gm.turn]++ if gm.isHandEmpty() { gm.drawCard() } } } else { count = 1 } prev = card } }

// drawCard takes a card from the deck // adding it to the current player's hand. func (gm *GoFishGame) drawCard() { if !gm.isDeckEmpty() { card := gm.deck[0] gm.deck = gm.deck[1:] if gm.isPlayerTurn() { fmt.Printf("You drew a %s.\n", card) } gm.hands[gm.turn] = append(gm.hands[gm.turn], card) //Check for books gm.checkForBooks() } }

// getPickComputer handles the computer's card choices. // We do the moderately smart thing of pick a random // card from our hand func getPickComputer(gm *GoFishGame) string { hand := gm.hands[1] choice := "A" if len(hand) > 0 { choice = hand[rand.Intn(len(hand))] } fmt.Printf("Computer picks %s.\n", choice) return choice }

// getPickUser gets the user's move. // If it's not valid, then the user just wastes // their turn. func getPickUser(gm *GoFishGame) string { fmt.Println("What card do you want?") var card string fmt.Scanf("%s\n", &card) return card }

// isDeckEmpty returns if the deck is empty. func (gm *GoFishGame) isDeckEmpty() bool { return len(gm.deck) == 0 }

// isHandEmpty returns if the current player's hand is empty. func (gm *GoFishGame) isHandEmpty() bool { return len(gm.hands[gm.turn]) == 0 }

// isGameOver returns if the game is over. // This happens when all 13 pips have been made into sets. func (gm *GoFishGame) isGameOver() bool { return gm.scores[0]+gm.scores[1] == 13 }

// isPlayerTurn returns if its the player's turn to move. func (gm *GoFishGame) isPlayerTurn() bool { return gm.turn == 0 }

// makeDeck makes a deck. // The deck is 52 cards with 4 of each pip. func makeDeck() []string { rand.Seed(time.Now().UTC().UnixNano()) deck := make([]string, 52) perm := rand.Perm(52) for indx := range perm { tVal := perm[indx] card := cards[tVal/4] deck[indx] = card } return deck }

// opponentHas returns if the opponent's hand has a card. func (gm *GoFishGame) opponentHas(find string) bool { for _, card := range gm.hands[(gm.turn+1)%2] { if card == find { return true } } return false }

// playerTurn handles the major game logic. // It's used for both the player's and computer's turns, // with the different behavior handled by the getPick param. func (gm *GoFishGame) playerTurn(getPick func(*GoFishGame) string) { opponent := (gm.turn + 1) % 2 gm.checkForBooks() if opponent == 1 { gm.printHand() } if gm.isHandEmpty() { gm.drawCard() } gameOver := gm.isGameOver() if !gameOver { card := getPick(gm) if gm.opponentHas(card) { count := gm.stealCards(card, opponent) for indx := 0; indx < count; indx++ { gm.hands[gm.turn] = append(gm.hands[gm.turn], card) } gm.checkForBooks() } else { fmt.Println("GO FISH!") gm.drawCard() gm.turn = opponent } } }

// printGameOverMessage prints the appropriate end message. func (gm *GoFishGame) printGameOverMessage() { fmt.Printf("Final score is %d to %d.\n", gm.scores[0], gm.scores[1]) if gm.scores[0] > gm.scores[1] { fmt.Println("Player wins!") } else if gm.scores[0] == gm.scores[1] { fmt.Println("It's a tie.") } else { fmt.Println("Computer wins!") } }

// printHand print's the player's hand and current score. func (gm *GoFishGame) printHand() { sort.Strings(gm.hands[0]) fmt.Printf("You have: %s.\n", gm.hands[0]) fmt.Printf("Score is %d to %d.\n", gm.scores[0], gm.scores[1]) }

// stealCards removes all instances of a card from side's hand. func (gm *GoFishGame) stealCards(purge string, side int) int { count := 0 var filtered []string for _, card := range gm.hands[side] { if purge == card { count++ } else { filtered = append(filtered, card) } } gm.hands[side] = filtered return count }

// main creates the deck and initial hands. func main() { deck := makeDeck() playerHand := deck[0:9] compHand := deck[9:18] deck = deck[18:] hands := make([][]string, 2, 2) hands[0] = playerHand hands[1] = compHand scores := make([]int, 2, 2) scores[0] = 0 scores[1] = 0 game := GoFishGame{hands, deck, 0, scores} for { if game.isPlayerTurn() { game.playerTurn(getPickUser) } else { game.playerTurn(getPickComputer) } if game.isGameOver() { break } } game.printGameOverMessage()

}

</lang>