日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

《C++游戏编程入门 第四版》的例子Blackjack-

發(fā)布時間:2023/12/18 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《C++游戏编程入门 第四版》的例子Blackjack- 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

這是《C++游戲編程入門 第四版》的最后一個例子,還挺復(fù)雜的。要完成這個制作,先要弄明白Blackjack的游戲規(guī)則。

簡化版Blackjack(21點)
規(guī)則:

游戲由2到6個人玩,使用除大小王之外的52張牌,游戲者的目標(biāo)是使手中的牌的點數(shù)之和不超過21點且盡量大。一個莊家Houser,多個玩家Player

  • 2至10牌,按其原點數(shù)計算;
  • K、Q、J和10牌都算作10點(一般記作T,即ten之意);
  • A 牌(ace)既可算作1點也可算作11點,由玩家自己決定(當(dāng)玩家停牌時,點數(shù)一律視為最大而盡量不爆,如A+9為20,A+4+8為13,A+3+A視為15)。
  • 玩法:

    開局先發(fā)兩張牌,莊家一明(面朝上)一暗(面朝下),玩家兩張明牌。
    接下來,每個玩家只要愿意,每次都有機(jī)會添加一張牌,超過21就Bust。
    當(dāng)所有的玩家選擇好了后,莊家亮出暗牌。如果莊家的點總數(shù)低于17,則莊家必須添加新牌。如果超過21就Bust(不管玩家點數(shù)多少,玩家都贏了)。如果暗牌已經(jīng)大于等于17了,莊家直接勝利。
    如果某個玩家點數(shù)比莊家點數(shù)大(小/等于),則…\dots

    類的設(shè)計


    Blackjack游戲Blackjack游戲Blackjack

    類描述
    CardBlackjack的游戲牌
    Hand玩家和莊家所持的牌,Card對象的集合
    GenericPlayer一般的玩家,是具體玩家類的過度,包含Player和Houser的共有元素
    Player玩家
    Houser莊家
    Deck牌堆,Hand的增強(qiáng)類(具有Hand類不具備的額外功能,如洗牌和發(fā)牌
    Game游戲外部接口,執(zhí)行游戲流程

    為了讓事情變得簡單再簡單,幾乎所有成員函數(shù)都是公用的,所有數(shù)據(jù)成員都是受保護(hù)的。繼承只使用公有繼承。

    Card類Card類Card

    成員描述
    rank m_rank牌的大小。rank是表示13個等級的枚舉類型
    suit m_suit牌的花色。suit是4種花色的枚舉類型
    bool m_faceUp是否是明牌(牌面向上)。這個影響牌的點數(shù)和顯示
    int Get()返回牌的點值

    Hand類Hand類Hand

    成員描述
    vector<Card*> m_cards撲克牌的集合,存儲著若干Card對象指針
    void Add(Card* pCard)向所持的牌中添加一張。在向量m_cards添加一個Card指針
    void Clear()清空所以所持的牌。移除m_cards所有的指針,刪除堆里相關(guān)Card對象
    int GetTotal()const返回所持牌的點數(shù)總和

    是Hand基類的實現(xiàn)類,是Player、Houser的抽象類。

    GenericPlayer類GenericPlayer類GenericPlayer

    成員描述
    string m_name玩家名
    virtual bool AreHitting()const =0指示玩家是否跟牌
    bool AreBusted()const指示玩家是否炸了
    void Bust()const玩家炸了后執(zhí)行的函數(shù)

    Player類Player類Player

    成員描述
    bool AreHitting()const指示玩家是否跟牌
    void Win()const玩家贏了后執(zhí)行的函數(shù)
    void Lose()const玩家輸了后執(zhí)行的函數(shù)
    void Push()const平局后執(zhí)行的函數(shù)

    Houser類Houser類Houser

    成員描述
    bool AreHitting()const指示莊家是否跟牌
    void FlipFirstCard()翻轉(zhuǎn)第一張牌,決定暗牌明牌

    Deck類就是發(fā)牌類,對Hand類進(jìn)行組合,與Player、Houser類的基類GenericPlayer互動。

    Deck類Deck類Deck

    成員描述
    void Populate()生成包含52張牌的標(biāo)準(zhǔn)牌堆
    void Shuffle()洗牌
    void Deal(Hand& aHand)發(fā)牌
    void AdditionalCards(GenericPlayer& aGenericPlayer)只要玩家跟牌,就向玩家額外發(fā)牌

    游戲引擎類,將其他類抽象出來的接口使用起來。并且對客戶端提供簡單的使用接口。

    Game類Game類Game

    成員描述
    Deck m_deck牌堆
    Houser m_houser莊家
    vector m_players許多的玩家
    void Play()進(jìn)行一輪游戲
    非成員函數(shù)描述
    vector Game_Interface()將輸入玩家個數(shù)和名字的部分隱藏起來

    游戲的實現(xiàn)

    Card.h

    #ifndef _CARD_H_ #define _CARD_H_#include<iostream> #include<string> #include<vector> #include<algorithm> #include<iomanip>//setw() using namespace std;//撲克牌 class Card { public:enum rank { ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };enum suit { CLUBS, DIAMONDS, HEARTS, SPADES };public:friend ostream& operator<<(ostream& os, const Card& aCard);Card(rank r = ACE, suit s = SPADES, bool faceUp = true);~Card() = default;int Get()const;void Flip();private:rank m_rank;suit m_suit;bool m_faceUp;};#endif

    Card.cpp

    #include "Card.h"ostream& operator<<(ostream& os, const Card& aCard) {const string THE_RANKS[] = { "0","A","2","3","4","5","6","7","8","9","10","J","Q","K" };const string THE_SUITS[] = { "c","d","h","s" };if (aCard.m_faceUp)os << THE_RANKS[aCard.m_rank] << THE_SUITS[aCard.m_suit];elseos << "XX";return os;} Card::Card(rank r , suit s , bool faceUp ) : m_rank(r),m_suit(s),m_faceUp(faceUp){}int Card::Get()const {int val = 0;if (m_faceUp) {val = m_rank;if (val > 10)val = 10;}return val; } void Card::Flip() {m_faceUp = !m_faceUp; }

    Hand.h

    #ifndef _HAND_H_ #define _HAND_H_#include"Card.h"//撲克牌的集合 class Hand { public:Hand();virtual ~Hand();void Add(Card* pCard);//拿一張牌到手上void Clear();//丟掉手上所有牌int GetTotal()const;//返回牌的全部價值 protected:vector<Card*> m_cards; };#endif

    Hand.cpp

    #include "Hand.h"Hand::Hand() {m_cards.reserve(7); } Hand::~Hand() {Clear(); }void Hand::Add(Card* pCard) {m_cards.push_back(pCard); } void Hand::Clear() {//刪除堆內(nèi)所有內(nèi)存for (Card* it : m_cards) {delete it;it = NULL;}//清空容器內(nèi)的指針m_cards.clear(); }int Hand::GetTotal()const {//撲克牌為空 或者 牌面朝下if (m_cards.empty() || m_cards[0]->Get() == 0)return 0;int total = 0;//獲取全部牌值for (Card* it : m_cards) total += it->Get();//看看是否牌里有尖bool contains_ace = false;for (Card* it : m_cards) {if (it->Get() == Card::ACE)contains_ace = true;}if (contains_ace &&total <= 11)total += 10;return total; }

    GenericPlayer.h

    #ifndef _GENERIC_PLAYER_H_ #define _GENERIC_PLAYER_H_#include"Hand.h"//這個類并不代表一個完整的玩家,只是表示玩家和機(jī)器玩家共有的元素 class GenericPlayer : public Hand {friend ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer); public:GenericPlayer(const string& name="");virtual ~GenericPlayer() = default;//寫虛析構(gòu)是為了下面派生的類的析構(gòu)能執(zhí)行到//indicates whether or not generic player wants to keep hittingvirtual bool AreHitting()const = 0;//returns whether generic player has busted - has a total greater than 21bool AreBusted()const; //是否要炸//announces that the generic player bustsvoid Bust()const; //炸了 protected:string m_name; };#endif

    GenericPlayer.cpp

    #include "GenericPlayer.h"ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer) {os << aGenericPlayer.m_name << ">>\t";if (!aGenericPlayer.m_cards.empty()) {for (Card* it : aGenericPlayer.m_cards) {os << *it << "\t";}if (aGenericPlayer.GetTotal() != 0)cout << "(" << aGenericPlayer.GetTotal() << ")";}elseos << setw(5)<<"\t<empty>";return os;}GenericPlayer::GenericPlayer(const string& name): m_name(name) {}bool GenericPlayer::AreBusted()const {return GetTotal() > 21; }void GenericPlayer::Bust()const {cout << m_name << " busts.\n==============================\n"; }

    Player.h

    #ifndef _PLAYER_H_ #define _PLAYER_H_#include"GenericPlayer.h"//人類玩家類 由GenericPlayer類派生而來 class Player : public GenericPlayer { public:Player(const string& name="");~Player() = default;bool AreHitting()const; //是否拿牌void Win()const; //贏了void Lose()const; //輸了void Push()const; //繼續(xù)游戲 };#endif

    Player.cpp

    #include "Player.h"Player::Player(const string& name ) : GenericPlayer(name){}bool Player::AreHitting()const {cout << m_name << ",do you want to hit? Y/N >>";char response;cin >> response;if (response == 'y' || response == 'Y')return true;cout << "---------------------------------------------------" << endl;return false;} void Player::Win()const {cout << m_name << " wins\n"; } void Player::Lose()const {cout << m_name << " loses\n"; } void Player::Push()const {cout << m_name << " pushes\n"; }

    Houser.h

    #ifndef _HOUSER_H_ #define _HOUSER_H_#include"GenericPlayer.h"//莊家 class Houser : public GenericPlayer { public:Houser(const string& name="Houser");~Houser() = default;bool AreHitting()const;void FlipFirstCard(); };#endif

    Houser.cpp

    #include "Houser.h"Houser::Houser(const string& name ): GenericPlayer(name){}//返回的點數(shù)小于17,表示莊家繼續(xù)跟牌 /* 如果莊家的暗牌已經(jīng)大于等于17了,則不管玩家多少,莊家直接贏。 */ bool Houser::AreHitting()const {return (GetTotal() < 17); }//翻開第一張莊家的牌 void Houser::FlipFirstCard() {if (!m_cards.empty())m_cards[0]->Flip();elsecout << "no card to flip!\n";}

    Deck.h

    #ifndef _DECK_H_ #define _DECK_H_#include"Hand.h" #include"GenericPlayer.h"class Deck : public Hand { public:Deck();~Deck() = default;void Populate();void Shuffle();void Deal( Hand& aHand);void AdditionalCards(GenericPlayer& aGenericPlayer);};#endif

    Deck.cpp

    #include "Deck.h"Deck::Deck() {m_cards.reserve(52);//turn the capacity to 52 Populate(); }void Deck::Populate() {Clear();//create a standard deckfor (int s = Card::CLUBS; s<= Card::SPADES; s++) {for (int r = Card::ACE; r <= Card::KING; r++) {Card* pNew = new Card(static_cast<Card::rank>(r),static_cast<Card::suit>(s));Add(pNew);//讓牌堆里保存一副52張的牌}}} void Deck::Shuffle() {//打亂元素的順序random_shuffle(m_cards.begin(), m_cards.end()); }void Deck::Deal( Hand& aHand) {if ( !m_cards.empty()) {aHand.Add(m_cards.back());//返回一張牌給玩家或莊家m_cards.pop_back();//彈出最后一個}elsecout << "out of cards. unable to deal"; }void Deck::AdditionalCards(GenericPlayer& aGenericPlayer){cout << endl;//如果玩家或莊家沒有爆而且選擇拿牌,直到不想繼續(xù)拿牌或者已經(jīng)爆了while (aGenericPlayer.AreBusted() == false && aGenericPlayer.AreHitting() == true) {Deal(aGenericPlayer);//aGenericPlayer傳遞,拿張牌出來cout << aGenericPlayer << endl;if (aGenericPlayer.AreBusted())aGenericPlayer.Bust();}}

    Game.h

    #ifndef _GAME_H_ #define _GAME_H_#include"Card.h" #include"Hand.h" #include"GenericPlayer.h" #include"Player.h" #include"Houser.h" #include"Deck.h"//這個類表示Blackjack這個游戲 class Game {Deck m_deck;Houser m_houser;vector<Player> m_players; public:Game() = default;Game(const vector<string>& names);Game(const Game& b) = default;Game operator=(const Game& b) = delete;~Game() = default;void Play();};vector<string> Game_Interface();#endif

    Game.cpp

    #include "Game.h"Game::Game(const vector<string>& names) {//seed the random number generatorsrand(static_cast<unsigned int>(time(0)));//create a vector of players from a vector of namesfor (auto hao : names)m_players.emplace_back(Player(hao));}/* 這個運行函數(shù)只游戲一遍*/void Game::Play() {/*------------------------------------------------------------------初始化和顯示-----------------------------------------------------------------------------*/m_deck.Populate();//生成52張牌的容器m_deck.Shuffle();//打亂容器元素//deal initial 2 cards to everyonefor (int i : {0,1}) {for (Player it : m_players) //把玩家都放進(jìn)Deck,拿出兩張牌m_deck.Deal( it);m_deck.Deal(m_houser); //把莊家也放進(jìn)Deck,拿出兩張牌}//HIde houser's first cardm_houser.FlipFirstCard();//display everyone's handfor (Player it : m_players)cout << it << endl;cout << m_houser << endl;/*由于重載了GenericPlayer和Card類的<<所以,可以對實例對象用<<直接輸出*//*---------------------------------------------------------------------------繼續(xù)加牌和判斷---------------------------------------------------------------------------------*///deal additional cards to playersfor (Player it : m_players)m_deck.AdditionalCards(it);//reveal houser's first cardm_houser.FlipFirstCard();cout << endl << m_houser;//把暗牌翻出來//deal additional cards to houserm_deck.AdditionalCards(m_houser);if (m_houser.AreBusted()) { //莊家輸了//everyone still playing winsfor (Player it : m_players) {if (it.AreBusted() == false) //某個玩家或某些玩家贏了it.Win();}}else {//莊家沒輸//compare each player still playing to houserfor (Player it : m_players) {if (it.AreBusted() == false) {if (it.GetTotal() > m_houser.GetTotal())//沒炸反而值還比莊家大it.Win();else if (it.GetTotal() < m_houser.GetTotal())//雖然沒炸,但是比莊家小it.Lose();else if (it.GetTotal() == m_houser.GetTotal())it.Push();//繼續(xù)游戲}}}/*---------------------------------------------------------------清空容器-------------------------------------------------------------------------------*///remove everyone's cardsfor (Player it : m_players)it.Clear();m_houser.Clear();m_deck.Clear();cout << "===================GAME END====================" << endl; }vector<string> Game_Interface() {cout << "===================Game Start====================" << endl;cout << "\t\tWelcome to Blackjack!\n\n";int numPlayers = 0;while (numPlayers < 1 || numPlayers>7) {cout << "How many players? (1~7) >>";cin >> numPlayers;}vector<string> names;string name;for (int i = 0; i < numPlayers; i++) {cout << "enter player name>>";cin >> name;names.push_back(name);}return names;}

    main.cpp

    #include"Game.h"void main(void) {vector<string> s = Game_Interface();Game* aGame = new Game(s);char again_flag = 'y';while (again_flag != 'n'&&again_flag != 'N') {aGame->Play();cout << "\nDo you want to play again?(Y/N)>>";cin >> again_flag;}system("pause");}

    最后的顯示結(jié)果

    括號前的幾個是牌,第一個數(shù)字是牌數(shù),第二個是符號。括號里的是總的點數(shù)。
    還剩下一個BUG,
    一開始應(yīng)該給每個玩家兩張牌,而我那段代碼并沒有被執(zhí)行…\dots
    反正能玩就是了。從沒想過,這么個小程序竟然也這么復(fù)雜。代碼量多而且類之間的調(diào)用關(guān)系真是臥槽!

    參考:《C++游戲編程入門 第四版》

    總結(jié)

    以上是生活随笔為你收集整理的《C++游戏编程入门 第四版》的例子Blackjack-的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。