第三章:抽象数据类型:Go 中的面向对象编程
4. 面向对象应用:简化版的 Blackjack 游戏
在本节中,我们将使用面向对象编程的思想来实现一个简化版的 Blackjack 游戏。通过这个例子,我们将展示如何使用结构体、方法和接口来构建一个可扩展和可维护的应用程序。
定义卡牌和牌组
首先,我们定义 Card 和 Deck 结构体。Card 结构体表示一张扑克牌,Deck 结构体表示一副牌。
示例:定义 Card 结构体
package blackjack
import "fmt"
type Suit string
type Rank string
const (
Spades Suit = "Spades"
Hearts Suit = "Hearts"
Clubs Suit = "Clubs"
Diamonds Suit = "Diamonds"
)
const (
Two Rank = "2"
Three Rank = "3"
Four Rank = "4"
Five Rank = "5"
Six Rank = "6"
Seven Rank = "7"
Eight Rank = "8"
Nine Rank = "9"
Ten Rank = "10"
Jack Rank = "Jack"
Queen Rank = "Queen"
King Rank = "King"
Ace Rank = "Ace"
)
type Card struct {
Suit Suit
Rank Rank
}
func (c Card) String() string {
return fmt.Sprintf("%s of %s", c.Rank, c.Suit)
}
示例:定义 Deck 结构体
package blackjack
import (
"math/rand"
"time"
)
type Deck struct {
Cards []Card
}
func NewDeck() *Deck {
var cards []Card
suits := []Suit{Spades, Hearts, Clubs, Diamonds}
ranks := []Rank{Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}
for _, suit := range suits {
for _, rank := range ranks {
cards = append(cards, Card{Suit: suit, Rank: rank})
}
}
return &Deck{Cards: cards}
}
func (d *Deck) Shuffle() {
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(d.Cards), func(i, j int) {
d.Cards[i], d.Cards[j] = d.Cards[j], d.Cards[i]
})
}
func (d *Deck) Draw() Card {
card := d.Cards[0]
d.Cards = d.Cards[1:]
return card
}
定义玩家和游戏逻辑
接下来,我们定义 Player 结构体和一些游戏逻辑。
示例:定义 Player 结构体
package blackjack
type Player struct {
Name string
Hand []Card
Score int
}
func (p *Player) CalculateScore() {
score := 0
aces := 0
for _, card := range p.Hand {
switch card.Rank {
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten:
score += int(card.Rank[0] - '0')
case Jack, Queen, King:
score += 10
case Ace:
aces++
score += 11
}
}
for score > 21 && aces > 0 {
score -= 10
aces--
}
p.Score = score
}
示例:定义 Blackjack 游戏
package blackjack
import "fmt"
type Game struct {
Deck *Deck
Players []Player
}
func NewGame(playerNames []string) *Game {
deck := NewDeck()
deck.Shuffle()
players := make([]Player, len(playerNames))
for i, name := range playerNames {
players[i] = Player{Name: name}
}
return &Game{
Deck: deck,
Players: players,
}
}
func (g *Game) DealInitialCards() {
for i := 0; i < 2; i++ {
for j := range g.Players {
g.Players[j].Hand = append(g.Players[j].Hand, g.Deck.Draw())
}
}
}
func (g *Game) Play() {
g.DealInitialCards()
for i := range g.Players {
g.Players[i].CalculateScore()
fmt.Printf("%s's hand: %v, Score: %d\n", g.Players[i].Name, g.Players[i].Hand, g.Players[i].Score)
}
}
func (g *Game) Hit(playerIndex int) {
card := g.Deck.Draw()
g.Players[playerIndex].Hand = append(g.Players[playerIndex].Hand, card)
g.Players[playerIndex].CalculateScore()
fmt.Printf("%s drew %s. New score: %d\n", g.Players[playerIndex].Name, card, g.Players[playerIndex].Score)
}
主程序
最后,我们编写主程序来启动游戏。
示例:主程序
package main
import (
"project/blackjack"
)
func main() {
game := blackjack.NewGame([]string{"Player1", "Player2"})
game.Play()
game.Hit(0)
game.Hit(1)
}
在这个示例中,我们创建了一个简化版的 Blackjack 游戏。通过使用结构体和方法,我们能够将游戏的不同部分封装起来,使代码更加模块化和易于维护。我们还使用了接口和多态性来增强代码的灵活性和可扩展性。通过这个例子,我们展示了如何在 Go 中应用面向对象编程的思想来构建复杂的应用程序。