数据结构和算法-Go泛型实现:第三章抽象数据类型:Go 中的面向对象编程- 4. 面向对象应用:简化版的 Blackjack 游戏

84 阅读2分钟

第三章:抽象数据类型:Go 中的面向对象编程

4. 面向对象应用:简化版的 Blackjack 游戏

在本节中,我们将使用面向对象编程的思想来实现一个简化版的 Blackjack 游戏。通过这个例子,我们将展示如何使用结构体、方法和接口来构建一个可扩展和可维护的应用程序。

定义卡牌和牌组

首先,我们定义 CardDeck 结构体。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 中应用面向对象编程的思想来构建复杂的应用程序。