java ----实现简单的21点纸牌游戏_利用python制作“21点纸牌游戏”

本项目利用Python的Tkinter模块创建了一个21点纸牌游戏的可视化界面。游戏中,玩家与电脑对战,每人起始两张牌,目标是接近但不超过21点。玩家可以选择是否要牌,如果超过21点则输掉比赛。电脑的策略是直到点数超过玩家。游戏结束后,玩家可以选择继续下一局。
摘要由CSDN通过智能技术生成

7c80fec9509b2a3828488e8924b92a4a.png

本项目是利用python中的Tkinter模块来制作一个可视化的“21点纸牌游戏”

1.基本游戏规则

  1. 游戏共有两个玩家:电脑和人类,电脑坐庄。
  2. 游戏开始时,先给人类和电脑分别发两种牌作为底牌,其中庄家仅露出一张牌。
  3. 判断双方是否直接为21点,如果其中一方为21点,则直接判该方胜利,在该方总分上加一分。如果双方都是21点,则为平局,双方都不得分。
  4. 当初始牌面都没有21点时,人类玩家根据自己牌面决定是否继续要牌。若要牌,则在牌堆中抽出一张,然后再次判断胜负。如果人类牌面的总数超过21点,则直接判输。
  5. 如果人类玩家停止要牌,并且在人类没有因为超过21点而被判输的情况下,电脑开始要牌。电脑要牌的规则是:电脑一直要牌,知道比人类玩家大才停止。
  6. 循环4和5的步骤。
  7. 完成一轮游戏后,由人类玩家决定,是否继续玩下一轮

2. 游戏计分规则

  1. 2、3、4、5、6、7、8、9、10分别是正常的分数
  2. J、Q、K都是10点
  3. A的计分比较复杂:首先将A记为1分,若牌面总分小于21分,将A记为11分再算一次,若这个时候仍然小于21,则将A按照11分算;若总分大于了21分,则将A计为1分。

3.代码实现

import os

import tkinter as tk
from PIL import Image,ImageTk
from random import shuffle
import random
import numpy as np
from tkinter import messagebox

win = tk.Tk()
win.title("21点纸牌游戏")

class Poker:
    def __init__(self,height=720,width=1280):
        self.height = height
        self.width = width
        self.people_poker_list = []
        self.computer_poker_list = []
        self.people_hand_poker = []
        self.computer_hand_poker = []
        self.poker_list = []
        self.people_score = 0
        self.computer_score = 0
        self.total_score = np.array([0,0])
        self.game_round = 0

        self.playing_card = self.make_cards("pokerImage")

        self.cv = tk.Canvas(win, height=self.height, width=self.width)
        self.desk = Image.open("desk.png")
        self.background_image = ImageTk.PhotoImage(self.desk)
        self.cv.create_image(0,0,image=self.background_image,anchor=tk.NW)
        self.cv.pack()

        self.every_round()
        self.start()


    def make_cards(self,file_dir):
        # 读取文件夹中的纸牌文件名,并将文件名和分值构建成一个字典
        imgs_name = {}
        for img_name in os.listdir(r"./" + file_dir):
            if img_name.split(".")[1] == 'jpg':
                if int(img_name.split(".")[0][1:3]) < 11:
                    imgs_name[img_name.split(".")[0]] = int(img_name.split(".")[0][1:3])
                else:
                    imgs_name[img_name.split(".")[0]] = 10
        return imgs_name


    def cards_name(self, poker_count=1):
        # 获取纸牌图片的文件名称
        poker_name = list(self.playing_card.keys())
        return poker_name*poker_count


    def random_cards(self):
        # 洗牌,对扑克牌进行随机排列
        shuffle(self.poker_list)


    def start_game_get_two_poker(self):
        # 初始化,给电脑和玩家分别发两张牌
        return [self.poker_list.pop(random.randint(0, len(self.poker_list) - 1)),
                self.poker_list.pop(random.randint(0, len(self.poker_list) - 1))]

    def read_img(self,hand_poker_list):
        # 由于tkinter要求图片格式为gif,因此利用ImageTK模块对手中纸牌图片进行格式转换
        img_list = []
        for i in range(len(hand_poker_list)):
            file_name = "./pokerImage/" + hand_poker_list[i] + ".jpg"
            card_img = Image.open(file_name)
            img_list.append(ImageTk.PhotoImage(card_img))
        return img_list


    def get_one_poker(self):
        # 从随机纸牌序列中抽取一张牌
        return self.poker_list.pop(random.randint(0, len(self.poker_list) - 1))


    def score_count(self,hand_poker):
        # 计算手中的牌的分数
        poker_score = 0
        have_a = False
        for k in hand_poker:
            poker_score += self.playing_card[k]
        for i in hand_poker:
            if i[1:] == '01':
                have_a = True
                break
            else:
                continue
        if have_a == True:
            if poker_score + 10 <= 21:
                poker_score = poker_score + 10
        return poker_score


    def who_win(self,people_score, computer_score):
        # 判断每一局牌的输赢
        if people_score > 21 and computer_score > 21:
            self.disabled_button()
            messagebox.showinfo(title="牌局结果", message="平局了!!!")
            self.total_score = np.add(self.total_score,np.array([0,0]))
            self.score_board()
        elif people_score > 21 and computer_score <= 21:
            self.disabled_button()
            messagebox.showinfo(title="牌局结果", message="对不起,您输了!!!")
            self.total_score = np.add(self.total_score, np.array([0, 1]))
            self.score_board()
        elif people_score <= 21 and computer_score > 21:
            self.disabled_button()
            messagebox.showinfo(title="牌局结果", message="恭喜,您赢了!!!")
            self.total_score = np.add(self.total_score, np.array([1, 0]))
            self.score_board()
        elif people_score <= 21 and computer_score <= 21:
            if people_score < computer_score:
                self.disabled_button()
                messagebox.showinfo(title="牌局结果", message="对不起,您输了!!!")
                self.total_score = np.add(self.total_score, np.array([0, 1]))
                self.score_board()
            elif people_score > computer_score:
                self.disabled_button()
                messagebox.showinfo(title="牌局结果", message="恭喜,您赢了!!!")
                self.total_score = np.add(self.total_score, np.array([1, 0]))
                self.score_board()
            else:
                self.disabled_button()
                messagebox.showinfo(title="牌局结果", message="平局了!!!")
                self.total_score = np.add(self.total_score, np.array([0, 0]))
                self.score_board()

    def disabled_button(self):
        # 将要牌与不要两个按钮转变为灰色
        self.yes_button['state'] = 'disabled'
        self.no_button['state'] = 'disabled'

    def score_board(self):
        # 分数显示牌
        self.round_label = tk.Label(self.cv, text="第 " + str(self.game_round) + " 局", height=1, width=21,
                                    font=("微软雅黑", 20), fg="#00ff00", bg="#cccccc")
        self.round_label.place(relx=0.75, rely=0.04)
        self.score_label = tk.Label(self.cv,
                                    text="目前比分:  玩家" + str(self.total_score[0]) + " : " + str(
                                        self.total_score[1]) + "庄家",
                                    height=1, width=18, font=("兰亭黑-简 中黑", 20), fg="#339900", bg="#cccccc")
        self.score_label.place(relx=0.75, rely=0.08)

    def hit_no(self):
        # 不要牌按钮及其响应事件
        if self.people_score > 21 and self.computer_score <= 21:
            # self.score = self.who_win(self.people_score, self.computer_score)
            return self.who_win(self.people_score, self.computer_score)
        elif self.people_score <= 21 and self.computer_score >= 21:
            # self.score = self.who_win(self.people_score, self.computer_score)
            return self.who_win(self.people_score, self.computer_score)
        elif self.people_score <= 21 and self.computer_score < 21:
            while self.computer_score <= self.people_score:
                self.computer_hand_poker.append(self.get_one_poker())
                self.computer_score = self.score_count(self.computer_hand_poker)
        computer_hand_num = len(self.computer_hand_poker)
        self.computer_poker_list = self.read_img(self.computer_hand_poker)
        for k in range(computer_hand_num):
            self.computer_cv = self.cv.create_image(650 - (105 + 20 * computer_hand_num) / 2 + 20 * k, 215,image=self.computer_poker_list[k], anchor=tk.NW)
            self.cv.update()
        # self.score = self.who_win(self.people_score,self.computer_score)
        return self.who_win(self.people_score, self.computer_score)


    def hit_yes(self):
        # 要牌按钮及其响应事件
        print("poker_list:{}".format(self.poker_list))
        self.people_hand_poker.append(self.get_one_poker())
        people_hand_num = len(self.people_hand_poker)
        self.people_poker_list = self.read_img(self.people_hand_poker)
        for i in range(people_hand_num):
            self.people_cv = self.cv.create_image(650 - (105 + 20 * people_hand_num) / 2 + 20 * i, 485,image=self.people_poker_list[i], anchor=tk.NW)
            self.cv.update()
        self.people_score = self.score_count(self.people_hand_poker)
        if self.people_score > 21:
            messagebox.showinfo(title="⚠️警告",message="您手里的牌已经超过21点!")
            # self.score = self.who_win(self.people_score, self.computer_score)
            return self.who_win(self.people_score, self.computer_score)


    def every_round(self):
        # 每一轮牌
        self.poker_list = self.cards_name()
        self.random_cards()
        print(self.poker_list)

        self.people_hand_poker = []
        self.computer_hand_poker = []
        self.people_poker_list = []
        self.computer_poker_list = []
        self.people_score = 0
        self.computer_score = 0
        # self.score = 0
        self.game_round += 1
        self.score_board()

        self.people_init_poker = self.start_game_get_two_poker()
        self.computer_init_poker = self.start_game_get_two_poker()

        self.people_hand_poker.extend(self.people_init_poker)
        print("people_hand_poker:{}".format(self.people_hand_poker))
        self.people_score = self.score_count(self.people_hand_poker)

        self.computer_hand_poker.extend(self.computer_init_poker)
        print("computer_hand_poker:.{}".format(self.computer_hand_poker))
        self.computer_score = self.score_count(self.computer_hand_poker)

        self.people_poker_list = self.read_img(self.people_hand_poker)
        self.computer_poker_list = self.read_img(self.computer_hand_poker)

        people_hand_num = len(self.people_hand_poker)


        for i in range(people_hand_num):
            print("显示玩家的牌")
            self.people_cv = self.cv.create_image(650 - (105 + 20 * people_hand_num) / 2 + 20 * i, 485,image=self.people_poker_list[i], anchor=tk.NW)

        computer_hand_num = len(self.computer_hand_poker)
        for k in range(computer_hand_num):
            print("显示电脑的牌")
            self.computer_cv = self.cv.create_image(650-(105+20*computer_hand_num)/2+20*k,215,image=self.computer_poker_list[k],anchor=tk.NW)


        if self.people_score == 21 or self.computer_score == 21:
            messagebox.showinfo(title="⚠️警告",message="初始化牌面分数有21点!")
            return self.who_win(self.people_score, self.computer_score)
        else:
            if self.people_score <= 21:
                self.yes_button = tk.Button(self.cv, text="要 牌", bg='grey', fg='red', font=('微软雅黑', 16),
                                            command=self.hit_yes)
                self.yes_button.place(relx=0.45, rely=0.61, height=30, width=50)
                self.no_button = tk.Button(self.cv, text='不 要', bg='grey', fg='red', font=('微软雅黑', 16),
                                           command=self.hit_no)
                self.no_button.place(relx=0.52, rely=0.61, height=30, width=50)


    def restart(self):
        # 点击再来一局后的响应
        self.cv.delete(self.people_cv)
        self.cv.delete(self.computer_cv)
        self.every_round()

    def start(self):
        # 再来一局按钮及其响应事件
        self.start_button = tk.Button(self.cv, text="再玩一次", bg='grey', fg='red',
                                      font=('微软雅黑 Bold', 20),
                                      command=self.restart)
        self.start_button.place(relx=0.85, rely=0.9, height=40, width=100)


poker = Poker()
win.mainloop()

游戏运行结果如下图:

380a62a9c14a6345906d18992b417707.png
游戏运行后的显示效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值