Python實現(xiàn)帶圖形界面的炸金花游戲
炸金花

題目很簡單:就是自己寫一個程序,實現(xiàn)詐金花游戲的發(fā)牌、判斷輸贏。
規(guī)則:
一付撲克牌,去掉大小王,每個玩家發(fā)3張牌,最后比大小,看誰贏。
牌型:
豹子:三張一樣的牌,如3張6.
順金:又稱同花順,即3張同樣花色的順子, 如紅桃 5、6、7
順子:又稱拖拉機,花色不同,但是順子,如紅桃5、方片6、黑桃7,組成的順子
對子:2張牌一樣
單張:單張最大的是A
版型大小順序: 豹子>順金>順子>對子>單張
從網(wǎng)上百科到的詐金花各種牌型的出現(xiàn)概率,一起放進代碼中增加一點趣味小知識。你可能不知道豹子出現(xiàn)的概率比同花順大,實際打牌時同花順反而比豹子?。豁樧映霈F(xiàn)的概率比金花小,實際打牌時順子反而比金花小;最大牌為5、6、7的單張牌型出現(xiàn)的概率都要比金花和順子小,所以有的地方額外規(guī)定同一局中拿到“235”三張牌要比同局的豹子大。
回到正題,直接上代碼,主要2個函數(shù):一個計分、一個比大小
from random import shuffle as DealCards
Players = 5 #人數(shù)
pkPacks = 1 #撲克副數(shù)
W = "單張","對子","順子","金花","順金","豹子"
X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24 #出現(xiàn)概率
Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #單張概率
V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
F = '?', '?', '?', '?'
P = [f+v for f in F for v in V]*pkPacks
def Scores(pokers):
f,p = [],[]
for poker in pokers:
f.append(F.index(poker[0])+1)
p.append(V.index(poker[1])+2)
t = sorted(p)
if len(set(t))==1:
return 500_0000+t[0] #豹子
elif len(set(t))==2: #對子
if t[0]==t[1]: #對子一樣大比較剩下的單張
return (100+t[1])*10000+t[2]
else:
return (100+t[1])*10000+t[0]
else:
if t[0]+1==t[1]==t[2]-1:
if len(set(f))==1:
return 400_0000+t[2] #順金(同花順)
else:
return 200_0000+t[2] #順子
else:
if len(set(f))==1:
return ((300+t[2])*100+t[1])*100+t[0] #金花
else:
return (t[2]*100+t[1])*100+t[0] #單張
def WhoWins(P):
Pokers,Winner = [],[]
for i in range(0,3*Players,3):
Pokers.append(P[i:i+3])
for i,p in enumerate(Pokers,1):
win = Scores(p)
idx = win//100_0000
print(f"Player{i}: {*p,} - {W[idx]}")
Winner.append(win)
win = max(Winner) #沒有判斷“一樣大”,如是則誰在前誰為大
idx = Winner.index(win)
big = win//10000
win = big//100
per = X[win] if win else Y[big-5]
pok = W[win] if win else '單'+V[big-2]
print(f"【Player{idx+1} win!】--> {*Pokers[idx],} {pok}({per}%)\n")
return P[3*Players:] #去掉每一局已發(fā)的牌
if __name__ == '__main__':
DealCards(P) #以隨機洗牌來模擬發(fā)牌
#Players = int(input('請輸入?yún)⒓拥娜藬?shù)?'))
PlayersMax = 52*pkPacks//3+1
if not 0<Players<PlayersMax:
print(f'請注意:參與人數(shù)的范圍 0 < Players < {PlayersMax} !')
else:
count = 1
while len(P)>=3*Players: #所有牌(52*PokerPairs)發(fā)不夠一局為止
print(f'第{count}局:')
count += 1
P = WhoWins(P)運行結(jié)果:
第1局:
Player1: ('♥Q', '♣2', '♣8') - 單張
Player2: ('♦T', '♥7', '♠6') - 單張
Player3: ('♣4', '♠4', '♦2') - 對子
Player4: ('♠5', '♠9', '♥6') - 單張
Player5: ('♠7', '♠3', '♣5') - 單張
【Player3 win!】--> ('♣4', '♠4', '♦2') 對子(16.94%)
第2局:
Player1: ('♥2', '♥8', '♦4') - 單張
Player2: ('♦9', '♦3', '♥A') - 單張
Player3: ('♠J', '♣A', '♦K') - 單張
Player4: ('♠8', '♥9', '♥T') - 順子
Player5: ('♣7', '♣9', '♣T') - 金花
【Player5 win!】--> ('♣7', '♣9', '♣T') 金花(4.96%)
第3局:
Player1: ('♦7', '♦J', '♠2') - 單張
Player2: ('♥J', '♦A', '♥K') - 單張
Player3: ('♥4', '♥5', '♦6') - 順子
Player4: ('♣Q', '♣J', '♠T') - 順子
Player5: ('♣K', '♦8', '♦5') - 單張
【Player4 win!】--> ('♣Q', '♣J', '♠T') 順子(3.26%)
擴展
學(xué)習(xí)要舉一反三,做完題目想到把這個程序的界面圖形化。無非就是把牌型對應(yīng)列表下標(biāo)從下圖中索引取出相應(yīng)的圖片來對應(yīng)到Image控件上;想要輸出的文字對應(yīng)到text控件上;再整2個button控件綁定對應(yīng)的事件動作。(代碼中有第3個button是我測試用的)
牌型圖: Pokers.png

初始界面:

發(fā)牌界面:

開牌界面:

PokersV1.py 完整源代碼:
import tkinter as tk
from PIL import Image,ImageTk
from time import sleep
from random import shuffle as DealCards
Players = 4 #人數(shù)
pkPacks = 1 #撲克副數(shù)
isReady = True
W = "單張","對子","順子","金花","順金","豹子"
X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24 #出現(xiàn)概率
Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #單張概率
V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
F = '?', '?', '?', '?'
def loadCards():
infile = Image.open("pokers.png")
Images = []
for j in range(4):
image = []
for i in range(15):
box = infile.crop((i*100,j*150,i*100+100,j*150+150))
img = ImageTk.PhotoImage(image=box)
image.append(img)
Images.append(image)
infile.close()
return Images
def dealCards():
global cv,cards,isReady,P,Pokers
if not isReady:
return
cv.itemconfig(txt1, text="")
cv.itemconfig(txt2, text="")
if len(Pokers):
for j in range(3):
for i in range(4):
cv.itemconfig(cards[i][j], image=Cards[0][0])
cv.update()
sleep(0.5)
for j in range(3):
for i in range(4):
cv.itemconfig(cards[i][j], image=Cards[1][0])
cv.update()
sleep(0.3)
if len(P)==0 or len(P)<12:
P = [f+v for f in F for v in V]*pkPacks
DealCards(P)
isReady = False
def playCards():
global cv,isReady,P,Pokers,cards,Cards
if isReady:
return
P = WhoWins(P)
for i,pok in enumerate(Pokers):
for j,p in enumerate(pok):
x = F.index(p[0])
y = V.index(p[1])
#print(x,y,'-',i,j)
cv.itemconfig(cards[i][j], image=Cards[x][y+2])
cv.update()
isReady = True
def Scores(pokers):
f,p = [],[]
for poker in pokers:
f.append(F.index(poker[0])+1)
p.append(V.index(poker[1])+2)
t = sorted(p)
if len(set(t))==1:
return 500_0000+t[0] #豹子
elif len(set(t))==2: #對子
if t[0]==t[1]: #對子一樣大比較剩下的單張
return (100+t[1])*10000+t[2]
else:
return (100+t[1])*10000+t[0]
else:
if t[0]+1==t[1]==t[2]-1:
if len(set(f))==1:
return 400_0000+t[2] #順金(同花順)
else:
return 200_0000+t[2] #順子
else:
if len(set(f))==1:
return ((300+t[2])*100+t[1])*100+t[0] #金花
else:
return (t[2]*100+t[1])*100+t[0] #單張
def WhoWins(P):
global cv,txt1,txt2,Pokers
Pokers,Winner = [],[]
for i in range(0,3*Players,3):
Pokers.append(P[i:i+3])
for i,p in enumerate(Pokers,1):
win = Scores(p)
idx = win//100_0000
print(f"Player{i}: {*p,} - {W[idx]}")
Winner.append(win)
win = max(Winner) #沒有判斷“一樣大”,如是則誰在前誰為大
idx = Winner.index(win)
big = win//10000
win = big//100
per = X[win] if win else Y[big-5]
pok = W[win] if win else '單'+V[big-2]
text1 = f"【Player{idx+1} win!】"
text2 = f"{pok}{*Pokers[idx],} {per}%\n"
print(text1,'--> ',text2)
cv.itemconfig(txt1, text=text1)
cv.itemconfig(txt2, text=text2)
return P[3*Players:] #去掉每一局已發(fā)的牌
def test():
global Pokers
print("測試:",Pokers)
if __name__ == '__main__':
root = tk.Tk()
root.geometry('1024x768')
root.title('詐金花')
cv = tk.Canvas(root, width=1024, height=680, bg='darkgreen')
cv.pack()
Pokers = []
Cards = loadCards()
cards = [[None]*3 for _ in range(4)]
P = [f+v for f in F for v in V]*pkPacks
DealCards(P)
x1, x2, x3 = 400, 80, 730
y1, y2, y3 = 100, 550, 320
dx1,dx2,dy = 105, 105, 0
imgxy = [[(x1,y1),(x1+dx1,y1),(x1+2*dx1,y1)],[(x3,y3),(x3+dx2,y3+dy),(x3+2*dx2,y3+dy*2)],
[(x1,y2),(x1+dx1,y2),(x1+2*dx1,y2)],[(x2,y3),(x2+dx2,y3+dy),(x2+2*dx2,y3+dy*2)]]
for x,lst in enumerate(imgxy):
for y,coord in enumerate(lst):
cards[x][y] = cv.create_image(coord, image=Cards[0][0])
cv.create_rectangle(coord[0]-50,coord[1]-75,coord[0]+50,coord[1]+75)
tx,ty = coord[0]-100,coord[1]+92
cv.create_text(tx,ty, text=f'Player{x+1}', fill='white')
btn = [None]*3
btn[0] = tk.Button(root,text='發(fā)牌',command=dealCards,width=10)
btn[1] = tk.Button(root,text='開牌',command=playCards,width=10)
btn[2] = tk.Button(root,text='測試',command=test,width=10)
for i in range(3):
btn[i].place(y=710, x=350+i*110)
txt1 = cv.create_text(510,300, fill='red', font=("宋體", 16))
txt2 = cv.create_text(510,360, fill='red', font=("宋體", 10))
root.mainloop()【編譯程序】
Windows的Cmd窗口中執(zhí)行如下命令,Mac系統(tǒng)自行百度:
pyinstaller -F exam.py --noconsole
注意:記得把上面的牌型圖保存為Pokers.png和代碼放一起運行。
到此這篇關(guān)于Python實現(xiàn)帶圖形界面的炸金花游戲的文章就介紹到這了,更多相關(guān)Python炸金花游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家
相關(guān)文章
python dict.get()和dict[''key'']的區(qū)別詳解
下面小編就為大家?guī)硪黄猵ython dict.get()和dict['key']的區(qū)別詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06
Python Zipfile模塊進行ZIP文件的創(chuàng)建解壓信息獲取和加密等操作
這篇文章主要為大家介紹了Python Zipfile模塊進行ZIP文件的創(chuàng)建解壓信息獲取和加密等操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01
pymongo給mongodb創(chuàng)建索引的簡單實現(xiàn)方法
這篇文章主要介紹了pymongo給mongodb創(chuàng)建索引的簡單實現(xiàn)方法,涉及Python使用pymongo模塊操作mongodb的技巧,需要的朋友可以參考下2015-05-05
對python-3-print重定向輸出的幾種方法總結(jié)
今天小編就為大家分享一篇對python-3-print重定向輸出的幾種方法總結(jié),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05
python與mysql數(shù)據(jù)庫交互的實現(xiàn)
這篇文章主要介紹了python與mysql數(shù)據(jù)庫交互的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01

