Python?Pygame實(shí)戰(zhàn)之紅心大戰(zhàn)游戲的實(shí)現(xiàn)
導(dǎo)語(yǔ)
還記得那些年,我們玩過(guò)的Windows小游戲嗎?

說(shuō)起Windows自帶的游戲,相信許多80、90后的朋友都不陌生。
在很早的那個(gè)游戲貧瘠的年代,《紙牌》、《掃雷》等游戲幫助我們?cè)谖C(jī)課上帶來(lái)了許多歡樂(lè)的時(shí)光。但在這些游戲中,有一款游戲似乎玩懂的人,甚至知道玩法的人并不多。這款游戲就是《紅心大戰(zhàn)》。
最近小編心血來(lái)潮仔細(xì)鉆研了一下之后,發(fā)現(xiàn)這款游戲玩起來(lái)卻比其他的幾款游戲更帶感一些。因?yàn)檫@款游戲的玩法簡(jiǎn)單概括就是兩個(gè)字:“坑人”,而且是明著坑的那種。
那大家猜到了哈——今天跟著木木子一起開(kāi)啟《紅心大戰(zhàn)》紙牌小游戲吧!

一、 紅心大戰(zhàn)用戶手冊(cè)
1.打開(kāi)游戲:雙擊hongxindazhan.py 主程序運(yùn)行即可!
2.開(kāi)始游戲:鍵入玩家姓名,創(chuàng)建新ID,點(diǎn)確認(rèn)進(jìn)入游戲。
3.游戲流程:
1)換牌:選擇三張手牌,點(diǎn)擊上方按鈕完成交換;
2)出牌:輪到玩家出牌時(shí),選擇手牌單擊便可打出。(具體出牌規(guī)則詳見(jiàn)附錄)注:當(dāng)此時(shí)機(jī)不能打出此牌時(shí),下方提示欄會(huì)顯示無(wú)法打出原因。
4.統(tǒng)分階段:一輪游戲過(guò)后,會(huì)彈出得分表,顯示玩家和三名電腦每輪積分和總積分,并顯示玩家當(dāng)前名次。
5.菜單欄:
1)游戲欄:新游戲(F2):?jiǎn)螕糸_(kāi)啟新游戲。得分(F4):?jiǎn)螕麸@示得分表。背景音樂(lè):?jiǎn)螕羟袚Q音樂(lè)開(kāi)關(guān)。選項(xiàng)(F5):?jiǎn)螕粜薷碾娔X出牌速度。退出:?jiǎn)螕敉顺鲇螒颉?/p>
2)幫助欄:規(guī)則介紹(F1):?jiǎn)螕麸@示簡(jiǎn)要規(guī)則和獲勝條件。名言:?jiǎn)螕魪棾鲆粍t名言。
6.背景音樂(lè):更換:可用自己的wav格式音樂(lè)重命名為‘m1.wav’替換程序目錄下的同名文件。
二、紅心大戰(zhàn)游戲規(guī)則
1、在玩游戲前,需要決定莊家。在電腦中,莊家坐南。
2、拿到一手牌(共計(jì)13張)后,莊家首先須選出三張牌傳給其他對(duì)手。第一局把牌傳給左手邊的玩家;第二局把牌傳給右手邊的玩家;第三局把牌傳給坐在對(duì)面的玩家;第四局不傳牌,依此類推。接到莊家的傳牌后,也需要任意傳回給莊家三張牌。在電腦中,如要選牌,單擊相應(yīng)牌張即可。如要取消選定的牌,請(qǐng)?jiān)俅螁螕簟?/p>
3、抓有梅花2 的玩家必須首先出梅花2,謂首攻。
4、然后按順時(shí)針?lè)较虺雠?。每位玩家依次必須跟同花色牌。如果已?jīng)沒(méi)有與發(fā)牌花色相同的牌,則可以出任何一張牌。唯一例外是不能在第一圈牌中出紅桃或黑桃Q(通常稱為“豬”)。注意:出的同一花色牌中最大的牌會(huì)贏取這一圈,贏牌的玩家在下一圈中先出牌。只有前面出過(guò)紅桃以后,才可以拿紅桃領(lǐng)出(除非手中只剩下紅桃一種花色的牌張)。
5、每一輪游戲結(jié)束時(shí),每張紅心計(jì)1 分,“黑桃皇后(豬)”計(jì)13 分。游戲?qū)⒊掷m(xù)到有人得100 分或更多分或者莊家退出游戲時(shí)結(jié)束。如果在一輪牌中贏得了所有的紅心和“黑桃皇后”(稱之為“全收”),則“全收”者得零分,其余玩家每人得26 分。該游戲的得分越低越好。
三、準(zhǔn)備中
1)環(huán)境安裝
環(huán)境安裝 本文用到的運(yùn)行環(huán)境:Python3.7、Pycharm社區(qū)版2020、tkinter模塊、部分自帶模塊直接導(dǎo)入不需要安裝。
模塊安裝:
pip install -i pypi.douban.com/simple/ +模塊名
2)背景選擇最原始的綠色背景。(僅展示背景,其余圖片比較多不展示)

四、代碼演示
?僅展示主程序源碼。每行代碼都有注釋所以直接展示!
from Tkinter import *
from tkFont import *
import winsound
from tkMessageBox import *
from inner import *
from dialog import *
#游戲主界面創(chuàng)建
class GameFrame:
def __init__(self,game,bgimg):#game,Game類對(duì)象;bgimg,背景圖片
self.master = game.root
#創(chuàng)建畫布,繪制背景
self.c = Canvas(self.master,width = 1024,height = 640)
self.c.create_image(514,322,image=bgimg)
self.c.pack()
#創(chuàng)建狀態(tài)條
self.status = Label(self.master,text=" 歡迎參加紅心大戰(zhàn)!",
bd=1,relief=SUNKEN,anchor=W)
self.status.pack(fill = X)
#打開(kāi)開(kāi)始對(duì)話框
startdialog = StartDialog(self.master,"紅心大戰(zhàn)")
if startdialog.isCancel:
game.cancel()
else:
self.gamemodetext = ['向左傳','向右傳','交叉換牌']
self.name = [startdialog.name,'西','北','東']
self.handXY = [[346.5,490,1,0],[20,135,0,1],
[586.5,20,-1,0],[913,375,0,-1]]
self.nameXY = [[-20,130,SE],[0,-20,SW],[91+20,0,NW],[91,130+20,NE]]
self.middleXY = [[466.5,330],[411,255],[466.5,180],[522,255]]
self.img = 53 * ['']
for i in range(52):
self.img[i] = PhotoImage(file = 'card\\%s.pgm' % (i))
self.img[52] = PhotoImage(file = 'back.pgm')
self.scorelist = []
self.cards = []
self.gamemode = 0
self.speed = 100
self.wait = self.speed
self.isChanging = False
self.iswait = False
#繪制名字
for i in range(4):
self.c.create_text(self.handXY[i][0]+self.nameXY[i][0],
self.handXY[i][1]+self.nameXY[i][1],
fill = 'white',text = self.name[i],
anchor = self.nameXY[i][2],
font = Font(size=15,weight="bold"))
#創(chuàng)建手牌
self.l = 52 * ['']
for i in range(52):
self.l[i] = Label(self.master,image=self.img[52],bd = -1)
for i in range(13):
self.l[i]['text'] = str(i)
self.l[i].bind("<Button-1>",self.cardEvent)
#創(chuàng)建中央牌
self.ml = 4 * ['']
for i in range(4):
self.ml[i] = Label(self.master,image=self.img[52],bd = -1)
self.b = Button(self.master,width=15,command=self.buttonEvent)
#一輪游戲開(kāi)始
self.oneGameStart()
def oneGameStart(self):
#創(chuàng)建Onegame對(duì)象,用來(lái)獲取出牌信息
self.onegame = OneGame()
#獲取玩家手牌,顯示
hand = self.onegame.getPlayerHand(0)
for i in range(13):
self.l[i]['image'] = self.img[hand[i].id]
for i in range(4):
for j in range(13):
self.moveCard(i,j,0)
#游戲模式為0,1,2時(shí)進(jìn)入換牌階段
if self.gamemode != 3:
self.changeHands()
else:
self.onegame.changeCards([],3)
self.isChanging = False
self.leftCards = 13
#進(jìn)入出牌階段,玩家前的電腦出牌
self.playpreCards()
def changeHands(self):
#換牌階段相應(yīng)初始化
self.select = []#所選的牌
self.isChanging = True
self.isOK = False
s = [1,3,2]
self.status['text'] = ' 請(qǐng)選三張牌傳給'+self.name[s[self.gamemode]]+'。'
#提示按鈕顯示
self.b['text'] = self.gamemodetext[self.gamemode]
self.b.place(x = 460,y = 400)
self.b['state'] = DISABLED
def cardEvent(self,event):
#牌的事件
#獲取牌的位置
i = int(event.widget['text'])
if not self.isChanging:
#出牌階段的牌事件
#等待中不出牌
if self.iswait:
return
#出不了的牌不出
if not self.onegame.available(i):
self.status['text'] = self.onegame.errorString
return
self.onegame.playCard(i)
#所出牌顯示到中央
event.widget.place_forget()
self.ml[self.turn]['image'] = event.widget['image']
self.ml[self.turn].place(x = self.middleXY[0][0],y = self.middleXY[0][1])
self.turn += 1
self.leftCards -= 1
#玩家后的電腦出牌
self.iswait = True
self.playlaterCards()
self.status['text'] = ' 正在等候……'
self.wait += 500 + 5 * self.speed
#等待一段時(shí)間后,中央牌清空,玩家前的電腦出牌
self.master.after(self.wait,self.playpreCards)
self.wait = self.speed
else:
#換牌階段的牌事件,彈起的落下,落下的彈起
if not self.isOK:
if i in self.select:
self.select.remove(i)
self.moveCard(0,i,0)
self.b['state'] = DISABLED
else:
if len(self.select) < 3:
self.select.append(i)
self.moveCard(0,i,1)
if len(self.select) == 3:
self.b['state'] = NORMAL
def buttonEvent(self):
#提示按鈕事件
if not self.isOK:
#換牌前獲取電腦換的牌進(jìn)行交換
self.select = self.onegame.changeCards(self.select,self.gamemode)
hand = self.onegame.getPlayerHand(0)
for i in range(13):
self.l[i]['image'] = self.img[hand[i].id]
self.moveCard(0,i,0)
for i in self.select:
self.moveCard(0,i,1)
self.status['text'] = ' 請(qǐng)按"確定"接受傳來(lái)的牌。'
self.b['text'] = '確定'
self.isOK = True
else:
#換牌后進(jìn)行確認(rèn),進(jìn)入出牌階段,玩家前的電腦出牌
for i in self.select:
self.moveCard(0,i,0)
self.b.place_forget()
self.isChanging = False
self.leftCards = 13
self.playpreCards()
def playpreCards(self):
if self.leftCards == 0:
#牌出完了進(jìn)行統(tǒng)分,顯示得分對(duì)話框
for i in range(4):
hand = self.onegame.p[i].scoreHand
for j in range(len(hand)):
self.l[i*13+j]['image'] = self.img[hand[j].id]
self.moveCard(i,j,0)
score = self.onegame.getScore()
self.scorelist.append(score)
if len(self.scorelist) != 1:
for i in range(4):
self.scorelist[-1][i] += self.scorelist[-2][i]
self.status['text'] = ' 得分'
scoredialog = self.showScoreDialog()
#得分確認(rèn)后初始化,開(kāi)始新一輪游戲
if scoredialog.isover:
self.scorelist = []
self.gamemode = 0
else:
self.gamemode = (self.gamemode + 1) % 4
for i in range(52):
self.l[i].place_forget()
self.l[i]['image'] = self.img[52]
for i in range(4):
self.ml[i].place_forget()
self.oneGameStart()
else:
#獲取玩家之前的電腦出牌,進(jìn)行顯示
for i in range(4):
self.ml[i].place_forget()
self.turn = 0
preCards = self.onegame.preCard
if len(preCards) == 0:
self.end()
else:
for i in range(len(preCards)):
p,j = preCards[i][0],preCards[i][1]
self.cards.append([self.turn,p,j])
self.master.after(self.wait,self.showMiddleCard)
if p == 3:
self.master.after(self.wait,self.end)
self.wait = self.speed
else:
self.wait += self.speed
self.turn += 1
def playlaterCards(self):
#獲取玩家之后的電腦出牌,進(jìn)行顯示
laterCards = self.onegame.laterCard
for i in range(len(laterCards)):
p,j = laterCards[i][0],laterCards[i][1]
self.cards.append([self.turn,p,j])
self.master.after(self.wait,self.showMiddleCard)
self.wait += self.speed
self.turn += 1
def moveCard(self,i,j,state):#i,玩家;j,第幾張牌;state,彈起還是放下
#牌的移動(dòng)
self.l[i*13+j].place_forget()
x0 = self.handXY[i][0] + self.handXY[i][2]*j*20
y0 = self.handXY[i][1] + self.handXY[i][3]*j*20
self.l[i*13+j].place(x = x0,y = y0 - state * 20)
def newGame(self):
#新游戲
self.scorelist = []
self.gamemode = 0
for i in range(52):
self.l[i].place_forget()
self.l[i]['image'] = self.img[52]
for i in range(4):
self.ml[i].place_forget()
self.oneGameStart()
def showScoreDialog(self):
#顯示分?jǐn)?shù)對(duì)話框
scoredialog = ScoreDialog(self.master,self.scorelist,self.name)
return scoredialog
def showMiddleCard(self):
#中央牌顯示
i = self.cards[0][0]
p = self.cards[0][1]
j = self.cards[0][2]
del self.cards[0]
self.l[p*13+j].place_forget()
hand = self.onegame.getPlayerHand(p)
self.ml[i]['image'] = self.img[hand[j].id]
self.ml[i].place(x = self.middleXY[p][0],
y = self.middleXY[p][1])
def end(self):
#電腦出完牌至玩家出牌的切換
self.iswait = False
self.status['text'] = ' 請(qǐng)出一張牌。'
#游戲窗口創(chuàng)建,并建立游戲菜單項(xiàng)
class Game:
def __init__(self):
#建立根窗口,設(shè)置
self.root = Tk()
self.root.title("紅心大戰(zhàn)")
self.root.geometry('+150+10')
self.root.resizable(False, False)
#播放背景音樂(lè)
self.s = winsound.PlaySound('m1.wav',
winsound.SND_ASYNC+winsound.SND_LOOP)
#建立菜單
m = Menu(self.root)
self.root['menu'] = m
gamemenu = Menu(m)
helpmenu = Menu(m)
m.add_cascade(label = '游戲',menu = gamemenu)
m.add_cascade(label = '幫助',menu = helpmenu)
gamemenu.add_command(label="新游戲 F2",command = self.gameEvent1)
gamemenu.add_separator()
gamemenu.add_command(label="得分... F4",command = self.gameEvent2)
gamemenu.add_command(label="選項(xiàng)... F5",command = self.gameEvent4)
self.v = IntVar()
self.v.set(1)
gamemenu.add_checkbutton(label="背景音樂(lè)",variable = self.v,
command = self.gameEvent3)
gamemenu.add_separator()
gamemenu.add_command(label="退出",command = self.cancel)
helpmenu.add_command(label="規(guī)則介紹... F1",command = self.helpEvent1)
helpmenu.add_command(label="名言...",command = self.helpEvent2)
self.root.bind('<F2>',self.gameEvent1)
self.root.bind('<F4>',self.gameEvent2)
self.root.bind('<F5>',self.gameEvent4)
self.root.bind('<F1>',self.helpEvent1)
self.root.protocol("WM_DELETE_WINDOW",self.cancel)
#導(dǎo)入背景圖片
bgimg = PhotoImage(file = 'bg.gif')
#創(chuàng)建主界面
self.frame = GameFrame(self,bgimg)
#主循環(huán)
self.root.mainloop()
def gameEvent1(self,event=None):
#游戲菜單項(xiàng)”新游戲“
flag = askokcancel('新游戲','你確定要放棄當(dāng)前游戲開(kāi)始新游戲么?')
if flag:
self.frame.newGame()
def gameEvent2(self,event=None):
#游戲菜單項(xiàng)”得分“
self.frame.showScoreDialog()
def gameEvent3(self):
#游戲菜單項(xiàng)”背景音樂(lè)“
if self.v.get() == 0:
winsound.PlaySound(self.s,winsound.SND_PURGE)
else:
self.s = winsound.PlaySound('m1.wav',
winsound.SND_ASYNC+winsound.SND_LOOP)
def gameEvent4(self,event=None):
#游戲菜單項(xiàng)”選項(xiàng)“
optionDialog = OptionDialog(self.root,self.frame.speed / 100 - 1)
if not optionDialog.isCancel:
self.frame.speed = 100 + optionDialog.v.get() * 100
def helpEvent1(self,event=None):
#幫助菜單項(xiàng)”規(guī)則介紹“
HelpDialog(self.root)
def helpEvent2(self):
#幫助菜單項(xiàng)”名言“
SayDialog(self.root)
def cancel(self):
#關(guān)閉音樂(lè),退出游戲
winsound.PlaySound(self.s,winsound.SND_PURGE)
self.root.destroy()
def main():
Game()
if __name__ == '__main__':
main()五、效果展示
1)游戲開(kāi)始

2)游戲界面

?3)左上角幫助菜單

4)游戲結(jié)束排名

到此這篇關(guān)于Python Pygame實(shí)戰(zhàn)之紅心大戰(zhàn)游戲的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python Pygame 紅心大戰(zhàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python基礎(chǔ)globlal nonlocal和閉包函數(shù)裝飾器語(yǔ)法糖
這篇文章主要為大家介紹了Python基礎(chǔ)globlal nonlocal和閉包函數(shù)裝飾器語(yǔ)法糖示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Python實(shí)現(xiàn)Windows上氣泡提醒效果的方法
python隨機(jī)數(shù)分布random測(cè)試
Python基于DFA算法實(shí)現(xiàn)內(nèi)容敏感詞過(guò)濾

