用python實現的21點游戲


游戲規則

該游戲的規則與實際的玩法應該有點差異,因為我沒有去細查21點的確切玩法,只是根據印象中進行了一系列的定義,具體如下:
1.玩家為人類玩家與電腦玩家,共2個玩家。電腦為庄家。
2.先給人類玩家與電腦玩家分別發兩張牌作為底牌。
3.判斷雙方底牌是否為blackjack,如果一方為blackjack則直接判勝利,並在總分中記上一分。如果雙方均為blackjack,則判雙方平局,均不得分
4.如果沒有出現blackjack的情況,人類玩家根據牌面決定是否要牌,若要牌則得到牌堆的一張牌,並再次判斷。如果人類牌面的點數超過21點,則直接判負。
5.如果人類玩家停止要牌,且未因為超過21點而判負,則電腦要牌(電腦的要牌基於一個算法,后期如果更新,這個算法要基於對勝率的估算),電腦停止要牌后,判斷與人類的輸贏情況。贏者加一分。
6.人類玩家決定是否繼續下一輪,如果繼續,則從剩余牌堆中繼續發牌開始上述過程。如果不繼續,則計算總分,判斷誰勝出。
7.如果牌堆的牌已經不夠玩一輪的話,自動判斷游戲結束。人類可以選擇是否重新再玩。



程序功能

要實現上面游戲的規則,程序的功能進行划分如下,不同的功能用不同的函數來實現,以達到代碼的復用。
1.牌堆:在發牌的過程中,牌堆中會去除已經發出的牌
2.發牌:要牌的時候,需要從牌堆隨機抽取一張牌
3.計分:能對手中的牌的分數進行計算,其中需要考慮靠A的特殊性
4.勝負判斷:當結束要牌的時候,能通過分數判斷勝負
5.要牌與否:一個讓你判斷是否繼續要牌的功能
6.游戲結束判斷:讓你決定是否提前結束游戲,如果不提前結束,則在牌堆中牌的數量比較少的時候,自動結束游戲
7.一局游戲的過程

代碼實現:
角色類,實現打印用戶牌面,獲取用戶牌分數
//角色類
class Role:
    def __init__(self):
        """初始化方法"""
        # 定義列表,用來保存當前角色手中的牌,初始牌為空,保存的類型為Card對象
        self.cards = []

    # 向控制台打印手中所有的牌
    def show_card(self, style=0, show=True):
        lastpos = len(self.cards) - 1

        if style == 1:
            msg = '你擁有的牌:'
        else:
            msg = '庄家的牌:'

        cardSow = ''
        for i, card in enumerate(self.cards):
            if show:
                if i < lastpos:
                    cardSow = cardSow + (card.card_tpye + card.card_text) + ','
                else:
                    cardSow = cardSow + (card.card_tpye + card.card_text)
            else:
                if i < lastpos:
                    cardSow = cardSow + (card.card_tpye + card.card_text) + ','
                else:
                    cardSow = cardSow + ' ?\n'

        print(msg + cardSow, sep='', end='')

        # 打印當前角色手中所有牌之后,在進行換行。
        print()

    def get_value(self):
        """獲取當前角色牌的點數(分為最小值和最大值)
        """
        Score = 0
        Have_Ace = False
        for card in self.cards:
            Score += card.card_value

        for i in self.cards:
            if i.card_text == 'A':
                Have_Ace = True
                break
            else:
                continue

        if Have_Ace:
            if Score + 10 <= 21:
                Score = Score + 10
        return Score

    def clear_card(self):
        # 清空牌,重新開始
        self.cards = []
View Code
牌類
//牌類

class Card:
    def __init__(self, card_tpye, card_text, card_value):
        """初始化方法
        Parameters
        ---------
        card_type:str
            牌的類型:(紅桃,黑桃,梅花,方片)
        card_text:str
            牌面顯示的文本(A,K,Q,J)
        card_value:int
            牌面的真實值(例如A為1點或11點,K為10點)
        """
        self.card_tpye = card_tpye
        self.card_text = card_text
        self.card_value = card_value
View Code
牌管理類,實現牌的生成,和牌的發放
//牌管理類

class CardManager:
    """管理一整副撲克牌,並且能夠進行發牌"""

    def __init__(self):
        """初始化方法"""
        # 用來保存一整副52張撲克牌
        self.cards = []
        # 定義所有牌的花色類型
        all_card_type = "♥♠♣♦"
        all_card_text = ["A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3", "2"]
        all_card_value = [11, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2]

        # 對牌面類型、牌面值、牌面文本嵌套循環
        for card_type in all_card_type:
            for index, card_text in enumerate(all_card_text):
                card = Card(card_type, card_text, all_card_value[index])
                self.cards.append(card)

        # 洗牌
        random.shuffle(self.cards)

    def getCard(self):
        return self.cards

    # 發牌
    def send_card(self, role, num=1):
        """給電腦或玩家發牌,
        Parameters
        ------
        role:Role
            電腦或玩家
        num:int
            發牌的數量,默認1張
        """
        for i in range(num):
            card = self.cards.pop()
            role.cards.append(card)
View Code
游戲管理類,實現牌,用戶的生成,用戶輸入以及分數判別等
//游戲管理類
class GameManager:
    def __init__(self):
        # 創建撲克牌管理器類
        self.cards = CardManager()

        # 創建玩家角色
        self.player = Role()
        # 創建電腦角色
        self.computer = Role()

        self.total_score = np.array([0, 0])  # 總分的計分器

    def start_game(self):
        Round = 1
        while len(self.cards.getCard()) > 10:
            self.player.clear_card()
            self.computer.clear_card()

            input('開始, good luck...<<Enter>>\n')
            print(f'第 {Round} 輪:')
            print('.' * 60)

            score = self.one_round()
            self.total_score += score
            print(f'總分數:{self.total_score[0]}:{self.total_score[1]}')
            Round += 1
            self.continue_or_quit()

    def judgement(self, your_score, pc_score):
        # 結束要牌的時候,計算雙方的點數,判斷輸贏
        if your_score > 21 and pc_score > 21:
            print(f'平局,分數: {your_score}:{pc_score}')
            return np.array([0, 0])
        elif your_score > 21 and pc_score <= 21:
            print(f'你輸了,分數: {your_score}:{pc_score}')
            return np.array([0, 1])
        elif your_score <= 21 and pc_score > 21:
            print(f'你贏了,分數: {your_score}:{pc_score}')
            return np.array([1, 0])
        elif your_score <= 21 and pc_score <= 21:
            if your_score < pc_score:
                print(f'你輸了,分數: {your_score}:{pc_score}')
                return np.array([0, 1])
            elif your_score > pc_score:
                print(f'你贏了,分數: {your_score}:{pc_score}')
                return np.array([1, 0])
            else:
                print(f'平局,分數: {your_score}:{pc_score}')
                return np.array([0, 0])

    def one_round(self):
        # 一個回合的游戲
        self.cards.send_card(self.player, 2)
        self.cards.send_card(self.computer, 2)

        self.player.show_card(1)
        self.computer.show_card(0, False)

        score = np.array([self.player.get_value(), self.computer.get_value()])
        if score[0] == 21 or score[1] == 21:
            print('BlackJack 21點直接獲勝')
            return self.judgement(score[0], score[1])
        else:
            while score[0] <= 21:
                Get_New_Poker = self.hit_or_stand()
                # 要了一張牌
                if Get_New_Poker:

                    self.player.show_card(1)
                    self.computer.show_card(0, False)

                    score[0] = self.player.get_value()
                    if score[0] > 21:
                        print('你超過21點')
                        self.computer.show_card(0)

                        print()
                        return self.judgement(score[0], score[1])
                    else:
                        continue
                elif not Get_New_Poker:
                    # npc點數比玩家低,則要牌
                    while score[1] < score[0]:
                        self.cards.send_card(self.computer)

                        score[1] = self.computer.get_value()

                    self.player.show_card(1)
                    self.computer.show_card(0)
                    print()
                    return self.judgement(score[0], score[1])
                else:
                    continue

    def hit_or_stand(self):
        # 玩家需要判斷是否繼續叫牌
        AskPoker = input('是否叫牌? 【Y/N】>>:')
        if AskPoker.upper() == 'Y':
            print()

            self.cards.send_card(self.player)
            return True
        elif AskPoker.upper() == 'N':
            print('你沒加牌.')
            print()
            return False
        else:
            print('輸入錯誤 Y/y or N/n!>>')
            return self.hit_or_stand()

    def continue_or_quit(self):
        # 在每一輪結束后,判斷是否繼續下一輪的游戲。當牌堆里面牌的數目不足的時候,自動停止游戲
        NextRound = input('是否繼續? 【Y/N】>>')
        if NextRound.upper() == 'Y':
            if len(self.cards.getCard()) < 10:
                print('牌不夠了')
                input('Game Over')
                exit(1)
            else:
                return True
        elif NextRound.upper() == 'N':
            input('Game Over')
            exit(1)
        else:
            print('輸入有誤')
            self.continue_or_quit()
View Code
完整代碼
//完整代碼

import random
import numpy as np
from sys import exit


class Role:
    def __init__(self):
        """初始化方法"""
        # 定義列表,用來保存當前角色手中的牌,初始牌為空,保存的類型為Card對象
        self.cards = []

    # 向控制台打印手中所有的牌
    def show_card(self, style=0, show=True):
        lastpos = len(self.cards) - 1

        if style == 1:
            msg = '你擁有的牌:'
        else:
            msg = '庄家的牌:'

        cardSow = ''
        for i, card in enumerate(self.cards):
            if show:
                if i < lastpos:
                    cardSow = cardSow + (card.card_tpye + card.card_text) + ','
                else:
                    cardSow = cardSow + (card.card_tpye + card.card_text)
            else:
                if i < lastpos:
                    cardSow = cardSow + (card.card_tpye + card.card_text) + ','
                else:
                    cardSow = cardSow + ' ?\n'

        print(msg + cardSow, sep='', end='')

        # 打印當前角色手中所有牌之后,在進行換行。
        print()

    def get_value(self):
        """獲取當前角色牌的點數(分為最小值和最大值)
        """
        Score = 0
        Have_Ace = False
        for card in self.cards:
            Score += card.card_value

        for i in self.cards:
            if i.card_text == 'A':
                Have_Ace = True
                break
            else:
                continue

        if Have_Ace:
            if Score + 10 <= 21:
                Score = Score + 10
        return Score

    def clear_card(self):
        # 清空牌,重新開始
        self.cards = []


class Card:
    def __init__(self, card_tpye, card_text, card_value):
        """初始化方法
        Parameters
        ---------
        card_type:str
            牌的類型:(紅桃,黑桃,梅花,方片)
        card_text:str
            牌面顯示的文本(A,K,Q,J)
        card_value:int
            牌面的真實值(例如A為1點或11點,K為10點)
        """
        self.card_tpye = card_tpye
        self.card_text = card_text
        self.card_value = card_value


class CardManager:
    """管理一整副撲克牌,並且能夠進行發牌"""

    def __init__(self):
        """初始化方法"""
        # 用來保存一整副52張撲克牌
        self.cards = []
        # 定義所有牌的花色類型
        all_card_type = "♥♠♣♦"
        all_card_text = ["A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3", "2"]
        all_card_value = [11, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2]

        # 對牌面類型、牌面值、牌面文本嵌套循環
        for card_type in all_card_type:
            for index, card_text in enumerate(all_card_text):
                card = Card(card_type, card_text, all_card_value[index])
                self.cards.append(card)

        # 洗牌
        random.shuffle(self.cards)

    def getCard(self):
        return self.cards

    # 發牌
    def send_card(self, role, num=1):
        """給電腦或玩家發牌,
        Parameters
        ------
        role:Role
            電腦或玩家
        num:int
            發牌的數量,默認1張
        """
        for i in range(num):
            card = self.cards.pop()
            role.cards.append(card)


"""
游戲管理類,檢測用戶輸入,分數判斷等
"""


class GameManager:
    def __init__(self):
        # 創建撲克牌管理器類
        self.cards = CardManager()

        # 創建玩家角色
        self.player = Role()
        # 創建電腦角色
        self.computer = Role()

        self.total_score = np.array([0, 0])  # 總分的計分器

    def start_game(self):
        Round = 1
        while len(self.cards.getCard()) > 10:
            self.player.clear_card()
            self.computer.clear_card()

            input('開始, good luck...<<Enter>>\n')
            print(f'第 {Round} 輪:')
            print('.' * 60)

            score = self.one_round()
            self.total_score += score
            print(f'總分數:{self.total_score[0]}:{self.total_score[1]}')
            Round += 1
            self.continue_or_quit()

    def judgement(self, your_score, pc_score):
        # 結束要牌的時候,計算雙方的點數,判斷輸贏
        if your_score > 21 and pc_score > 21:
            print(f'平局,分數: {your_score}:{pc_score}')
            return np.array([0, 0])
        elif your_score > 21 and pc_score <= 21:
            print(f'你輸了,分數: {your_score}:{pc_score}')
            return np.array([0, 1])
        elif your_score <= 21 and pc_score > 21:
            print(f'你贏了,分數: {your_score}:{pc_score}')
            return np.array([1, 0])
        elif your_score <= 21 and pc_score <= 21:
            if your_score < pc_score:
                print(f'你輸了,分數: {your_score}:{pc_score}')
                return np.array([0, 1])
            elif your_score > pc_score:
                print(f'你贏了,分數: {your_score}:{pc_score}')
                return np.array([1, 0])
            else:
                print(f'平局,分數: {your_score}:{pc_score}')
                return np.array([0, 0])

    def one_round(self):
        # 一個回合的游戲
        self.cards.send_card(self.player, 2)
        self.cards.send_card(self.computer, 2)

        self.player.show_card(1)
        self.computer.show_card(0, False)

        score = np.array([self.player.get_value(), self.computer.get_value()])
        if score[0] == 21 or score[1] == 21:
            print('BlackJack 21點直接獲勝')
            return self.judgement(score[0], score[1])
        else:
            while score[0] <= 21:
                Get_New_Poker = self.hit_or_stand()
                # 要了一張牌
                if Get_New_Poker:

                    self.player.show_card(1)
                    self.computer.show_card(0, False)

                    score[0] = self.player.get_value()
                    if score[0] > 21:
                        print('你超過21點')
                        self.computer.show_card(0)

                        print()
                        return self.judgement(score[0], score[1])
                    else:
                        continue
                elif not Get_New_Poker:
                    # npc點數比玩家低,則要牌
                    while score[1] < score[0]:
                        self.cards.send_card(self.computer)

                        score[1] = self.computer.get_value()

                    self.player.show_card(1)
                    self.computer.show_card(0)
                    print()
                    return self.judgement(score[0], score[1])
                else:
                    continue

    def hit_or_stand(self):
        # 玩家需要判斷是否繼續叫牌
        AskPoker = input('是否叫牌? 【Y/N】>>:')
        if AskPoker.upper() == 'Y':
            print()

            self.cards.send_card(self.player)
            return True
        elif AskPoker.upper() == 'N':
            print('你沒加牌.')
            print()
            return False
        else:
            print('輸入錯誤 Y/y or N/n!>>')
            return self.hit_or_stand()

    def continue_or_quit(self):
        # 在每一輪結束后,判斷是否繼續下一輪的游戲。當牌堆里面牌的數目不足的時候,自動停止游戲
        NextRound = input('是否繼續? 【Y/N】>>')
        if NextRound.upper() == 'Y':
            if len(self.cards.getCard()) < 10:
                print('牌不夠了')
                input('Game Over')
                exit(1)
            else:
                return True
        elif NextRound.upper() == 'N':
            input('Game Over')
            exit(1)
        else:
            print('輸入有誤')
            self.continue_or_quit()


if __name__ == '__main__':
    startGame = GameManager()
    startGame.start_game()
View Code

 

效果:

 

 

 

查看文檔:https://www.jianshu.com/p/35c3a67ff241


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM