脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Python - Python Pygame实战之红心大战游戏的实现

Python Pygame实战之红心大战游戏的实现

2022-09-16 11:10木木子学python Python

说起Windows自带的游戏,相信许多80、90后的朋友都不陌生。本文就将利用Python中的Pygame模块实现一下windows经典游戏之一的红心大战,需要的可以参考一下

导语

还记得那些年,我们玩过的Windows小游戏吗?

Python Pygame实战之红心大战游戏的实现

说起Windows自带的游戏,相信许多80、90后的朋友都不陌生。

在很早的那个游戏贫瘠的年代,《纸牌》、《扫雷》等游戏帮助我们在微机课上带来了许多欢乐的时光。但在这些游戏中,有一款游戏似乎玩懂的人,甚至知道玩法的人并不多。这款游戏就是《红心大战》。

最近小编心血来潮仔细钻研了一下之后,发现这款游戏玩起来却比其他的几款游戏更带感一些。因为这款游戏的玩法简单概括就是两个字:“坑人”,而且是明着坑的那种。

那大家猜到了哈——今天跟着木木子一起开启《红心大战》纸牌小游戏吧!

Python Pygame实战之红心大战游戏的实现

 

一、 红心大战用户手册

1.打开游戏:双击hongxindazhan.py 主程序运行即可!

2.开始游戏:键入玩家姓名,创建新ID,点确认进入游戏。

3.游戏流程:

1)换牌:选择三张手牌,点击上方按钮完成交换;

2)出牌:轮到玩家出牌时,选择手牌单击便可打出。(具体出牌规则详见附录)注:当此时机不能打出此牌时,下方提示栏会显示无法打出原因。

4.统分阶段:一轮游戏过后,会弹出得分表,显示玩家和三名电脑每轮积分和总积分,并显示玩家当前名次。

5.菜单栏:

1)游戏栏:新游戏(F2):单击开启新游戏。得分(F4):单击显示得分表。背景音乐:单击切换音乐开关。选项(F5):单击修改电脑出牌速度。退出:单击退出游戏。

2)帮助栏:规则介绍(F1):单击显示简要规则和获胜条件。名言:单击弹出一则名言。

6.背景音乐:更换:可用自己的wav格式音乐重命名为‘m1.wav’替换程序目录下的同名文件。

 

二、红心大战游戏规则

1、在玩游戏前,需要决定庄家。在电脑中,庄家坐南。

2、拿到一手牌(共计13张)后,庄家首先须选出三张牌传给其他对手。第一局把牌传给左手边的玩家;第二局把牌传给右手边的玩家;第三局把牌传给坐在对面的玩家;第四局不传牌,依此类推。接到庄家的传牌后,也需要任意传回给庄家三张牌。在电脑中,如要选牌,单击相应牌张即可。如要取消选定的牌,请再次单击。

3、抓有梅花2 的玩家必须首先出梅花2,谓首攻。

4、然后按顺时针方向出牌。每位玩家依次必须跟同花色牌。如果已经没有与发牌花色相同的牌,则可以出任何一张牌。唯一例外是不能在第一圈牌中出红桃或黑桃Q(通常称为“猪”)。注意:出的同一花色牌中最大的牌会赢取这一圈,赢牌的玩家在下一圈中先出牌。只有前面出过红桃以后,才可以拿红桃领出(除非手中只剩下红桃一种花色的牌张)。

5、每一轮游戏结束时,每张红心计1 分,“黑桃皇后(猪)”计13 分。游戏将持续到有人得100 分或更多分或者庄家退出游戏时结束。如果在一轮牌中赢得了所有的红心和“黑桃皇后”(称之为“全收”),则“全收”者得零分,其余玩家每人得26 分。该游戏的得分越低越好。

 

三、准备中

1)环境安装

环境安装 本文用到的运行环境:Python3.7、Pycharm社区版2020、tkinter模块、部分自带模块直接导入不需要安装。

模块安装:

pip install -i pypi.douban.com/simple/ +模块名

2)背景选择最原始的绿色背景。(仅展示背景,其余图片比较多不展示)

Python Pygame实战之红心大战游戏的实现

 

四、代码演示

​仅展示主程序源码。每行代码都有注释所以直接展示!

from Tkinter import *
from tkFont import *
import winsound
from tkMessageBox import *
from inner import *
from dialog import *
#游戏主界面创建
class GameFrame:
  def __init__(self,game,bgimg):#game,Game类对象;bgimg,背景图片
      self.master = game.root
      #创建画布,绘制背景
      self.c = Canvas(self.master,width = 1024,height = 640)
      self.c.create_image(514,322,image=bgimg)
      self.c.pack()
      #创建状态条
      self.status = Label(self.master,text=" 欢迎参加红心大战!",
                          bd=1,relief=SUNKEN,anchor=W)
      self.status.pack(fill = X)
      #打开开始对话框
      startdialog = StartDialog(self.master,"红心大战")
      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"))
          #创建手牌
          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)
          #创建中央牌
          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)
          #一轮游戏开始
          self.oneGameStart()
  def oneGameStart(self):
      #创建Onegame对象,用来获取出牌信息
      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时进入换牌阶段        
      if self.gamemode != 3:
          self.changeHands()
      else:
          self.onegame.changeCards([],3)
          self.isChanging = False
          self.leftCards = 13
          #进入出牌阶段,玩家前的电脑出牌
          self.playpreCards()
  def changeHands(self):
      #换牌阶段相应初始化
      self.select = []#所选的牌
      self.isChanging = True
      self.isOK = False
      s = [1,3,2]
      self.status['text'] = ' 请选三张牌传给'+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
          #等待一段时间后,中央牌清空,玩家前的电脑出牌
          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:
          #换牌前获取电脑换的牌进行交换
          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'] = ' 请按"确定"接受传来的牌。'
          self.b['text'] = '确定'
          self.isOK = True
      else:
          #换牌后进行确认,进入出牌阶段,玩家前的电脑出牌
          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:
          #牌出完了进行统分,显示得分对话框
          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()
          #得分确认后初始化,开始新一轮游戏
          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:
          #获取玩家之前的电脑出牌,进行显示
          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):
      #获取玩家之后的电脑出牌,进行显示
      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,弹起还是放下
      #牌的移动
      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):
      #显示分数对话框
      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'] = ' 请出一张牌。'

#游戏窗口创建,并建立游戏菜单项
class Game:
  def __init__(self):
      #建立根窗口,设置
      self.root = Tk()
      self.root.title("红心大战")
      self.root.geometry('+150+10')
      self.root.resizable(False, False)
      #播放背景音乐
      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="选项...    F5",command = self.gameEvent4)
      self.v = IntVar()
      self.v.set(1)
      gamemenu.add_checkbutton(label="背景音乐",variable = self.v,
                               command = self.gameEvent3)
      gamemenu.add_separator()
      gamemenu.add_command(label="退出",command = self.cancel)
      helpmenu.add_command(label="规则介绍...    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)
      #导入背景图片
      bgimg = PhotoImage(file = 'bg.gif')
      #创建主界面
      self.frame = GameFrame(self,bgimg)
      #主循环
      self.root.mainloop()
  def gameEvent1(self,event=None):
      #游戏菜单项”新游戏“
      flag = askokcancel('新游戏','你确定要放弃当前游戏开始新游戏么?')
      if flag:
          self.frame.newGame()
  def gameEvent2(self,event=None):
      #游戏菜单项”得分“
      self.frame.showScoreDialog()
  def gameEvent3(self):
      #游戏菜单项”背景音乐“
      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):
      #游戏菜单项”选项“
      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):
      #帮助菜单项”规则介绍“
      HelpDialog(self.root)
  def helpEvent2(self):
      #帮助菜单项”名言“
      SayDialog(self.root)
  def cancel(self):
      #关闭音乐,退出游戏
      winsound.PlaySound(self.s,winsound.SND_PURGE)
      self.root.destroy()

     
def main():
  Game()

  
if __name__ == '__main__': 
  main()

 

五、效果展示

1)游戏开始

Python Pygame实战之红心大战游戏的实现

2)游戏界面

Python Pygame实战之红心大战游戏的实现

​3)左上角帮助菜单

Python Pygame实战之红心大战游戏的实现

4)游戏结束排名

Python Pygame实战之红心大战游戏的实现

到此这篇关于Python Pygame实战之红心大战游戏的实现的文章就介绍到这了,更多相关Python Pygame 红心大战内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7062525743464448007

延伸 · 阅读

精彩推荐
  • PythonPython实现自定义函数的5种常见形式分析

    Python实现自定义函数的5种常见形式分析

    这篇文章主要介绍了Python实现自定义函数的5种常见形式,结合实例形式较为详细的分析了Python自定义函数相关的参数、默认值、隐函数等相关操作技巧与注...

    Abvedu9532021-03-05
  • PythonPython基础知识之函数,类,模块

    Python基础知识之函数,类,模块

    今天小编就为大家分享一篇Python函数,类,模块,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    Mrwei_4186472022-02-20
  • Pythonpython直接获取API传递回来的参数方法

    python直接获取API传递回来的参数方法

    今天小编就为大家分享一篇python直接获取API传递回来的参数方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    蜡笔小心丶12282021-04-30
  • PythonPython ftp上传文件

    Python ftp上传文件

    这篇文章主要介绍了Python ftp上传文件的相关资料,需要的朋友可以参考下...

    a62253016162020-08-12
  • Python从DataFrame中提取出Series或DataFrame对象的方法

    从DataFrame中提取出Series或DataFrame对象的方法

    今天小编就为大家分享一篇从DataFrame中提取出Series或DataFrame对象的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    Sev6plus17152021-04-18
  • Python浅谈python中的面向对象和类的基本语法

    浅谈python中的面向对象和类的基本语法

    下面小编就为大家带来一篇浅谈python中的面向对象和类的基本语法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Python教程网2042020-08-26
  • PythonPython 逐行分割大txt文件的方法

    Python 逐行分割大txt文件的方法

    本文通过代码给大家介绍了Python 逐行分割大txt文件的方法,在文中给大家提到了Python从txt文件中逐行读取数据的方法,需要的朋友参考下吧...

    脚本之家11602020-12-11
  • PythonPython Pandas两个表格内容模糊匹配的实现

    Python Pandas两个表格内容模糊匹配的实现

    模糊查询大家应该都不会陌生,下面这篇文章主要给大家介绍了关于Python Pandas两个表格内容模糊匹配的实现方法,文中通过示例代码介绍的非常详细,需要的朋...

    迪迦瓦特曼5552022-02-28