最近公司在做棋牌類遊戲項目,看到炸金花的玩法後,就自己先寫出炸金花的基本功能實現,給那些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