最近公司在做棋牌类游戏项目,看到炸金花的玩法后,就自己先写出炸金花的基本功能实现,给那些python爱好者参考一下。
炸金花是民间非常流行的一种扑克牌玩法,它具有独特的比牌规则,玩家按照规则以手中的三张牌来比输赢。游戏过程中需要考验玩家的胆略和智慧,由于玩法简单,易于上手,炸金花是被公认的最受欢迎的纸牌游戏之一。炸金花游戏参与人数 2- 6 人,使用一副去掉到大小王的扑克牌,共 52 张牌。
在本游戏demo中,用户输入游戏人数,系统给每位玩家发三张牌,然后进行比牌排序,最后挑选出牌最大的玩家。
排序判断:可以赋予牌型固定值,比如同花顺60,同花50,顺子40…牌型相同的,再进行细节比较。
文件目录如下:
初始化牌堆:game_config.py
#coding=utf-8
import random
# 花色 红黑方梅
SUITS = ['H', 'S', 'D', 'C']
# 初始基本牌
INIT_LIST = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q','K','A']
MAPPING_LIST_NUM = '23456789TJQKA'
MAPPING_LIST_COLOR = 'DCHS' # 方梅红黑
def init_landlords():
lis = []
for card in INIT_LIST: # 数字
for suit in SUITS: # 花色
lis.append('{0}{1}'.format(card, suit))
random.shuffle(lis)
return lis
# print "初始化牌堆:", lis
def exchange_number(cards):
number = []
for r, s in cards:
temp = MAPPING_LIST_NUM.index(r)
number.append(temp)
return number
def exchange_color(cards):
color = []
for r, s in cards:
temp = MAPPING_LIST_COLOR.index(s)
color.append(temp)
return color
if __name__ =='__main__':
init_landlords()
比牌 : compare.py
#coding=utf-8
from game.game_config import *
from collections import Counter
BAOZI = 60 # 三条
COLORSEQ = 50 # 同花顺
COLOR = 40 # 同花
SEQ = 30 # 顺子
PAIR = 20 # 对子
SINGLE = 10 # 单张
# 单张比较
def cmpcard(x, y):
x_num = MAPPING_LIST_NUM.index(x[0])
x_col = MAPPING_LIST_COLOR.index(x[1])
y_num = MAPPING_LIST_NUM.index(y[0])
y_col = MAPPING_LIST_COLOR.index(y[1])
if x_num < y_num:
return -1
elif x_num > y_num:
return 1
else:
if x_col < y_col:
return -1
elif x_col > y_col:
return 1
else:
return 0
def judgetype(cards):
temp = cards[:]
if baozi(cards): # 豹子
print "豹子"
return BAOZI
if color(cards): # 同色
if seq(cards): # 顺子
print "同花顺"
return COLORSEQ # 同花顺
print "同花"
return COLOR # 同花
if seq(cards):
print "顺子"
return SEQ
if pair(cards):
print "对子"
return PAIR
else:
print "单张"
return SINGLE # 单张
# 三条
def baozi(pokers):
count = exchange_number(pokers)
if len(set(count)) == 1:
return True
# 同花,红的返1,黑的返2
def color(pokers):
colorlist = exchange_color(pokers)
ss = set(colorlist) # set集合判断是否同花
if len(ss) == 1:
if list(ss)[0] in [1, 3]: # 1,3对应C,S 草黑
return 2
elif list(ss)[0] in [0, 2]: # 0,2 对应 方红
return 1
# 顺子
def seq(pokers):
count = exchange_number(pokers)
sortcount = sorted(count)
if (sortcount[2] == sortcount[1] + 1 and sortcount[1] == sortcount[0] + 1) or (
sortcount[0] == 2 and sortcount[1] == 3 and sortcount[2] == 14): # 判断 A 2 3 情况
return True
# 对子
def pair(pokers):
count = exchange_number(pokers)
if count_card(count, 2):
return True
# 挑出cards中一张数量为n的牌
def count_card(cards, n):
lis = Counter(cards) # counter方法:计数
returns = []
for r, num in lis.most_common(): # most_common 找出出现频率最高 的方法 返回的是一个dict
if num == n:
returns.append(r)
return returns
return returns
发牌:deal.py
#coding=utf-8
from game.game_config import *
from game.compare import *
from game.compare import *
from operator import itemgetter
def deal():
lis = init_landlords()
seat = 0
tile_list = []
player_num = int(raw_input("请输入玩家数量(玩家人数建议为2—6人) :"))
if player_num <= 6 and player_num >=2:
while seat < player_num:
tile = []
rounds = 0
while rounds < 3:
tile.append(lis.pop()) # tile中三张
rounds += 1
tile_list.append(tile) # tile_list中 3张*人数
seat += 1
elif player_num < 0:
print "玩家人数错误"
return
elif player_num >= 0 and player_num <= 1:
print "人数不够"
return
else:
print "人数超过"
return
# 牌排序后分发到玩家手中
card_group = []
group_type = []
seat_list = []
for key, value in enumerate(tile_list):
# print player,value
card_group.append(sorted(value, cmp=cmpcard))
seat_list.append(key)
# print "发%d个人的牌:"%player_num,card_group
for key, value in enumerate(card_group):
s = judgetype(value)
group_type.append(s) # 玩家三张牌的牌型
print "玩家%d的牌 :" % key ,value,s
print "______________________________________"
# dic_score[key] = s
# print card_group,group_type
# print "玩家的牌型:",group_type
player_card = zip(seat_list,card_group,group_type)
# print player_card
cmp_data = []
for i in range(len(player_card)):
data_i = player_card[i]
player_seat = data_i[0]
card_list = data_i[1]
card_type = data_i[2]
max_card = max(card_list, key=lambda x: MAPPING_LIST_NUM.index(x[0]))
cmp_data.append([card_type, MAPPING_LIST_NUM.index(max_card[0]), MAPPING_LIST_COLOR.index(max_card[1]), data_i])
# print cmp_data
result = sorted(cmp_data, key=itemgetter(0, 1, 2))
sorted_list = []
# print result
for res in result:
sorted_list.append(res[3])
print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
print "本局牌最大的是 : 玩家{0}".format(sorted_list[-1][0])
if __name__ == '__main__':
deal()
优化:
(1)该游戏demo目前会出现2个bug。第一个是按理来说A23是最小的顺子,A23与其他顺子的比较无法实现,需要再增加一个方法把A23确定为最小顺子即可;第二个是对子的比较,比如玩家1手里有55J,玩家2手里有33A,系统会判定玩家2的牌大,解决方案是增加一个比较方法,当牌型都为对子,即牌型等于20时,先从对子中取一张牌比较(对子大的获胜),如果对子相同就看谁拿到黑桃对。
(2)要做成成型的游戏,就需要创建玩家对象,把牌型,分数这些作为属性传入玩家对象中去。
(3)未完待续…
游戏demo运行结果:
D:\python_works\venv\Scripts\python.exe D:/python_works/game/deal.py
请输入玩家数量(玩家人数建议为2—6人) :4
单张
玩家0的牌 : ['7S', '8D', 'TH'] 10
______________________________________
单张
玩家1的牌 : ['3C', '7H', '8S'] 10
______________________________________
对子
玩家2的牌 : ['6C', 'KD', 'KH'] 20
______________________________________
单张
玩家3的牌 : ['6S', '7D', 'AS'] 10
______________________________________
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
本局牌最大的是 : 玩家2