【Pygame实战】打扑克牌嘛?赢了输了?这款打牌游戏,竟让我废寝忘食。

导语

我小时候能玩的东西,远没有现在这么丰富,打扑克是其中之一。

什么“三打哈”、“丰收”、“二百四”啊!不知道你们那各种方言玩法都叫啥,我这个是湖南老家的。

我的话不经常打牌,大学的时候有手机之后就直接一个宿舍偶尔联网玩一下。

工作这几年,和朋友一起打牌的次数用一只手也能数过来。

BUT每年回湖南老家过年,少不了和亲戚一起打麻将打牌一起嗨皮一下,这是逃不掉的一个法

则了~(当然打牌的话大家不要沉迷哈,你们都懂的.....)

今天小编就给大家编写一个扑克牌的小游戏叭!希望大家喜欢哈,可以先来拿代码练练手~

所有文章完整的素材+源码都在👇👇

粉丝白嫖源码福利,请移步至CSDN社区或文末公众hao即可免费。

正文

一、项目介绍

1)玩家模块规范标准

用一个长度为2的字符串表示一张牌:(D,C,H,S) + (A,2,3,4,5,6,7,8,9,0,J,Q,K) 用"jk"、"JK"分别

表示小王、大王 游戏顺序是逆时针方向 角色用一个字符串表示。

("banker","banker_opposite","banker_left","banker_right")分别表示庄家、庄家的对家、庄

家的左边、庄家的右边 不考虑甩牌,使用python进行设计 。

 player模块设计:

1.1 设计函数:

de add_card_and_is_snatch(current_card): 表示玩家摸到一张牌curernt_card,并选择是否

抢庄。 current_card表示一张牌(长度为2的字符串) 如果抢庄,返回相应的牌的字符串,否则

返回'' 设计函数: def add_left_cards(left_cards): 只需要庄家才会用到,表示底牌是

left_cards,left_cards是一个长度为2的字符串的list 需要返回玩家准备埋到底牌的牌,返回值

也是一个长度为2的字符串的list 。

1.2  设计函数:

def finish_one_round(current_turn_out_cards): 表示这一轮出牌结束,玩家被告知这一轮的

出牌信息, current_turn_out_cards表示一个三元组(order,role,card)的list, 每一个三元组表

示这一轮你出牌之前的某一个人出的牌的信息, order是一个整数,表示出牌顺序(1,2,3,4)

role是一个字符串,表示角色("banker","banker_opposite","banker_left","banker_right")

card是一张牌。

 1.3 设计函数:

def set_main_value(main_value): 玩家被告知主面值是什么,main_value是一个字符

(A,2,3,4,5,6,7,8,9,0,J,Q,K)表示主面值 。

1.4  设计函数: 

def set_main_color(main_color): 玩家被告知主花色是什么,main_color是一个字符(D,C,H,S)

表示主花色 。

1.5 设计函数:

def player_init(): 表示现在开始一局新的游戏,并初始化相关变量 设计函数: def

set_role(role): 玩家被告知自己的角色是什么,role是一个字符串

("banker","banker_opposite","banker_left","banker_right") 。

1.6  设计函数:

def play_out_cards(turn, current_turn_out_cards): turn表示当前是第几轮出牌,

current_turn_out_cards表示一个三元组(order,role,card)的list, 每一个三元组表示这一轮你

出牌之前的某一个人出的牌的信息, order是一个整数,表示出牌顺序(1,2,3,4) role是一个字

符串,表示角色("banker","banker_opposite","banker_left","banker_right") card是一张牌

函数需要返回决定出的一张牌 。

1.7  设计函数: 

def show_cards(): 需要返回当前玩家的手牌(长度为2的字符串的list) 。

2)UI说明

1.1 import UI 

1.2  在游戏初始化模块添加代码:

# Initialize pygame
pygame.init()
setting = UI.Setting()
SCREEN_WIDTH, SCREEN_HEIGHT = setting.SCREEN_WIDTH, setting.SCREEN_HEIGHT
x, y = 150, 60
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("升级")
background = UI.Background(screen, setting)

1.3  使用接口说明:

a) initial(self): 每轮游戏初始化函数,重置卡组等功能;

b) add_card(self, card, turn): 发牌阶段,turn 为目的发牌玩家的位置 0-3,card 为所发牌

值;

c) add_cards_over(self, inputs, outputs, main_color, master): 发牌阶段结束后调用此

函数;input 为发给庄家的 6 张底牌,output 为庄家压底的 6 张牌;mian_color 为此局的主

色,master 是庄家玩家的位置 0-3;

d) push_cards(self, cards, turn): 打牌阶段,函数意义是 turn 玩家打出 cards,cards 为

card 列表,即所有打出的牌 值;

e) turn_over(self): 一轮牌结束阶段;清空四位玩家打出的所有牌;

f) update_point (self, point, level1, level2): 一轮牌结束阶段,更新当前得分和级数;point

为当前得分,level1 为东西位置玩 家当前的级数,level2 为南北玩家当前的级数 。

1.4  传递变量说明: 

a) card: (D,C,H,S) + (A,2,3,4,5,6,7,8,9,0,J,Q,K) 用"jk"、"JK"分别表示小王、大王 黑桃-

spade 红桃-heart 方快-diamond 草花-club 黑桃 3 : card = ‘s3’

b) turn: 整数 0-3 (0, 1, 2, 3) 等价于 ('East', 'North', 'West', 'South')

二、运行环境

1)小编使用的环境:Python3、Pycharm社区版、Pygame 模块部分自带就不一一

展示啦。

 模块安装:pip install -i https://pypi.douban.com/simple/+模块名 

2)素材(图片等)

背景、扑克牌等(图片过多仅展示部分素材)

三、代码展示

参考demo: judge 为裁判模块,myPlayer 为 AI 玩家,运行 judge.py。

主程序judge.py:

# coding:utf-8

import random
import pygame
import os
import time

import myPlayer as p1
import myPlayer as p2
import myPlayer as p3
import myPlayer as p4

import UI

# H S D C
# Heart Spade Diamond Club
# K - King  0 - small king , 1 - big king 

class Judge():
    def __init__(self):
        self.cards = None
        self.players = []
        self.players.append(p1.Player('East'))
        self.players.append(p2.Player('North'))
        self.players.append(p3.Player('West'))
        self.players.append(p4.Player('South'))
        
        self.level = [2,2]

        self.master = None

        self.false = [0 , 0, 0, 0]     #记录每个人犯错次数

        self.main_color = None
        self.main_num = 2

        self.loser = 0      # 记录先犯错的一方,最后判输

    def covert(self, s):
        if s == 1 or s == 14:
            return 'A'
        elif s < 10:
            return str(s)
        elif s == 10:
            return '0'
        elif s == 11:
            return 'J'
        elif s == 12:
            return 'Q'
        elif s == 13:
            return 'K'
        
    # 新游戏,初始化
    def new_game(self, background):
        self.main_color = None
        self.false = [0 , 0, 0, 0]
        self.loser = -1
        self.bottom = []
        self.point = 0
        self.biggest = [0, 0, 0, 0]
        self.player_cards = [[],[],[],[]]

        

        cards = self.create_card()
        random.shuffle(cards)
        for i in range(4):
            self.players[i].player_init()
        l = ['a', 'b', 'c', 'd']
        for i in range(4):
            self.players[i].set_role(l[i])
        for y in self.players:
            #y.initial_new_game()
            y.set_main_value(self.covert(self.main_num))
        # 发牌
        turn = 0
        for i in range(48):
            x = self.players[turn].add_card_and_is_snatch(cards[i])
            self.player_cards[turn].append(cards[i])
            if x != '' and x[1] == self.covert(self.main_num) and self.main_color == None:
                self.main_color = x[0]
                if self.master == None:

                    self.master = turn
                for y in self.players:
                    y.set_main_color(self.main_color)
            elif x == '':
                None
            else:
                self.false[turn] += 1
                if self.loser == -1:
                    self.loser = turn

            background.add_card(cards[i], turn)

            turn += 1
            turn %= 4
        if self.main_color == None:
            col = ['H', 'C', 'D', 'S']
            self.main_color = random.choice(col)
            for y in self.players:
                y.set_main_color(self.main_color)
        if self.master == None:
            self.master = random.randint(0, 3)
        self.bottom = self.players[self.master].add_left_cards(cards[48:])
        for x in cards[48:]:
            self.player_cards[self.master].append(x)
        
        
        if len(self.bottom) != 6:
            self.false[self.master] += 1
            if self.loser == -1:
                self.loser = self.master
        else:
            for x in self.bottom:
                if x in self.player_cards[self.master]:
                    self.player_cards[self.master].remove(x)
                else:
                    if self.loser == -1:
                        self.loser = self.master
        
        background.add_cards_over(cards[48:], self.bottom, self.main_color, self.master)

    '''生成一副牌'''
    def create_card(self):
        colors = ['H', 'S', 'D', 'C']
        nums = 'A234567890JQK'
        cards = []
        for color in colors:
            for i in range(13):
                c = color + nums[i]
                cards.append(c)
        cards.append('jk')
        cards.append('JK')

        return cards

    # 判断玩家手里是否有该花色的牌,y表示该轮是否要出主牌
    def find_color(self,p_cards, this_color, y):
        for x in p_cards:
            if y == True:
                if x == this_color or x == 'jk' or x=='JK' or x ==self.covert(self.main_num):
                    return True
            else:
                if x == this_color:
                    return True
        return False

    # a先出, 判断b的数字是否大于a
    def is_big(self,b, a):
        num_order = ['A', 'K', 'Q', 'J', '0', '9','8','7','6','5','4','3','2']
        for x in num_order:
            if x == a:
                return False
            if x == b:
                return True

    # 判断a 是否大于b,a先出
    def is_bigger(self,a , b, this_color):
        if a == 'JK':
            return True
        if a == 'jk':
            if b == 'JK':
                return False
            else :
                return True
        if a[1] == self.main_num:
            if b == 'jk' or b=='JK' or b[0]==self.main_color and b[1]==self.covert(self.main_num):
                return False
            else:
                return True
        if a[0] == self.main_color:
            if b =='jk' or b=='JK' or b[1]==self.covert(self.main_num) or b[0]==self.main_color and self.is_big(b[1],a[1]):
                return False
            else:
                return True
        if a[0] == this_color:
            if b =='jk' or b=='JK' or b[1]==self.covert(self.main_num) or b[0]==self.main_color or b[0]==this_color and self.is_big(b[1],a[1]):
                return False
            else:
                return True
        
        if b =='jk' or b=='JK' or b[1]==self.covert(self.main_num) or b[0]==self.main_color or b[0]==this_color or self.is_big(b[1],a[1]):
            return False
        else:
            return True
        

    def add_points(self, cards):
        for x in cards:
            if x[1] == '5':
                self.point += 5
            elif x[1] == '0' or x[1] == 'K':
                self.point += 10
            
    # 判断一轮中最大的牌是谁出的,是否加分
    def get_max_index_and_add_points(self, cards, turn, this_color):
        index = 0
        max_card = cards[0]
        for i in range(1,4):
            if not self.is_bigger(max_card, cards[i], this_color):
                index = i
                max_card = cards[i]
        
        if index % 2 != self.master % 2:
            self.add_points(cards)

        return (turn + index) % 4

    def is_a_card(self, s):
        if s == 'jk' or s == 'JK':
            return True
        if s[0] in ['H', 'S', 'D', 'C'] and s[1] in ['A', 'K', 'Q', 'J', '0', '9','8','7','6','5','4','3','2']:
            return True
        else:
            return False


    # 出牌到结束
    def run_game(self, background):
        turn = self.master
        for i in range(12):
            UI.check_events()
            this_turn_cards = []
            first_card = self.players[turn].play_out_cards(0 , this_turn_cards)
            this_turn_cards.append(first_card)

            if first_card in self.player_cards[turn]:
                self.player_cards[turn].remove(first_card)
            else:
                if self.loser == -1:
                    self.loser = turn
            
            background.push_cards([first_card], turn)

            turn += 1
            turn %= 4

            if not self.is_a_card(first_card):
                print('Please input a card')
                self.false[turn] += 1
            if first_card == 'jk' or first_card == 'JK' or first_card[0]==self.main_color or first_card[1]==self.covert(self.main_num):
                this_color = self.main_color
            else:
                this_color = first_card[0]

            for j in range(1, 4):
                a_cards = self.players[turn].play_out_cards(j, this_turn_cards)
                if a_cards in self.player_cards[turn]:
                    self.player_cards[turn].remove(a_cards)
                else:
                    if self.loser == -1:
                        self.loser = turn
                this_turn_cards.append(a_cards)
                #p_cards = self.players[turn].show_cards()
                p_cards = self.player_cards[turn]
                #print('a_cards = ', a_cards)   ###############
                if a_cards[0] == this_color:
                    None
                elif this_color == self.main_color:
                    if a_cards == 'jk' or a_cards == 'JK' or a_cards[1]==self.covert(self.main_num):
                        None
                    elif not self.find_color(p_cards, this_color, True):
                        None
                    else:
                        self.false[turn] += 1
                        if self.loser == -1:
                            self.loser = turn
                else:
                    if self.find_color(p_cards, this_color, False):
                        self.false[turn] += 1
                        if self.loser == -1:
                            self.loser = turn

                background.push_cards([a_cards], turn)

                turn += 1
                turn %= 4

            # 告诉所有玩家本轮出的牌
            for i in range(4):
                self.players[i].finish_one_round(this_turn_cards, (i + turn ) % 4 )

            max_index = self.get_max_index_and_add_points(this_turn_cards, turn, this_color)
            turn = max_index
            self.biggest[max_index] += 1

            background.update_point(self.point, self.level[0], self.level[1])
            background.turn_over()

        # 底牌是否得分
        if turn % 2 != self.master % 2:
            self.add_points(self.bottom)
        
        
        if self.loser % 2 == self.master:
            self.main_num = self.level[(self.master + 1) % 2]
            self.master = (self.master + 1) % 2
        elif self.loser % 2 != self.master and self.loser != -1:
            self.level[self.master % 2] += 1
            self.main_num = self.level[self.master % 2]
            if self.master == self.master % 2:
                self.master += 2
            else:
                self.master %= 2
        elif self.point < 40:
            self.level[self.master % 2] += 1
            self.main_num = self.level[self.master % 2]
            if self.master == self.master % 2:
                self.master += 2
            else:
                self.master %= 2
        else:
            self.main_num = self.level[(self.master + 1) % 2]
            self.master = (self.master + 1) % 2
        # print(self.biggest)

        
if __name__ == '__main__':
	# Initialize pygame
	pygame.init()
	setting = UI.Setting()

	SCREEN_WIDTH, SCREEN_HEIGHT = setting.SCREEN_WIDTH, setting.SCREEN_HEIGHT
	x, y = 150, 60
	os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
	screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
	pygame.display.set_caption("升级")

	background = UI.Background(screen, setting)
	judge = Judge()
	#judge.level = [12,13]
	while True:
		
		time.sleep(0.5)
		judge.new_game(background)
		judge.run_game(background)
		background.initial()

		if judge.level[0] == 13 or judge.level[1] == 13:
			print(judge.level)
			if judge.level[0] > judge.level[1]:
				print('East and West WIN')
			else:
				print('South and North WIN')
			break

四、效果展示

​运行截图——

总结

好啦好啦!这款简单的小游戏写到这里就结束了,看到这里是谁的DNA动了呢?嘻嘻嘻

小编友情提醒:小赌怡情,大赌伤身伤感情。打牌要尽兴,但切记得失心太重哦!

老规矩的撒素材完整的资料源码等关注我的都知道的啦自己去拿哈👇

🎯完整的免费源码领取处:找我吖!文末公众hao可自行领取,滴滴我也可!

🔨推荐往期文章——

项目1.0  超级玛丽

程序员自制游戏:超级玛丽100%真实版,能把你玩哭了~【附源码】

项目1.1   扫雷

 Pygame实战:据说这是史上最难扫雷游戏,没有之一,你们感受下......

​项目1.4  水果忍者

【Pygame实战】风靡全球的切水果游戏升级版“水果忍者”上线啦,你敢来PK嘛?

项目2.0  联网、人机一体五子棋游戏

Pygame实战:下五子棋吗?信不信我让你几步你也赢不了?

项目2.1   宇宙激战射击游戏

【Pygame实战】飞机射击大作:宇宙激战一触即发...这款超经典的射击游戏也该拿出来重启了~

🎄文章汇总——

项目1.0 Python—2021 |已有文章汇总 | 持续更新,直接看这篇就够了

(更多内容+源码都在文章汇总哦!!欢迎阅读~)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顾木子吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值