網站首頁 編程語言 正文
導語
昨天看到有留言竟然說我是月更博主,我明明更新地這么勤快(心虛.jpg)??窗桑蛱靹偢逻^,今天又來更新了。
今天還是帶大家寫個小游戲吧,不過老是用pygame也沒啥意思,這次我們換點新花樣,用python自帶的tkinter包寫一個記憶翻牌小游戲唄。
廢話不多說,讓我們愉快地開始吧~
開發工具
Python版本:3.7.4
相關模塊:
pygame模塊;
tkinter模塊;
pillow模塊;
以及一些python自帶的模塊。
環境搭建
安裝Python并添加到環境變量,pip安裝需要的相關模塊即可。
先睹為快
在終端運行如下命令即可:
python Game27.py
效果如下:
視頻鏈接
原理簡介
ok,這里我們還是來簡單介紹一下游戲的實現原理吧。
首先,我們還是借助pygame來播放一首我們喜歡的背景音樂吧:
'''播放背景音樂''' def playbgm(self): pygame.init() pygame.mixer.init() pygame.mixer.music.load(cfg.AUDIOPATHS['bgm']) pygame.mixer.music.play(-1, 0.0)
然后,我們初始化一下tkinter的主界面:
# 主界面句柄 self.root = Tk() self.root.wm_title('Flip Card by Memory —— Charles的皮卡丘')
并在主界面上顯示16張未被翻面的卡片:
# 游戲界面中的卡片字典 self.game_matrix = {} # 背景圖像 self.blank_image = PhotoImage(data=cfg.IMAGEPATHS['blank']) # 卡片背面 self.cards_back_image = PhotoImage(data=cfg.IMAGEPATHS['cards_back']) # 所有卡片的索引 cards_list = list(range(8)) + list(range(8)) random.shuffle(cards_list) # 在界面上顯示所有卡片的背面 for r in range(4): for c in range(4): position = f'{r}_{c}' self.game_matrix[position] = Label(self.root, image=self.cards_back_image) self.game_matrix[position].back_image = self.cards_back_image self.game_matrix[position].file = str(cards_list[r * 4 + c]) self.game_matrix[position].show = False self.game_matrix[position].bind('', self.clickcallback) self.game_matrix[position].grid(row=r, column=c)
這16張卡片共包含8張完全不同的圖像,我們游戲的目標就是在有限的時間內,將16張卡片中包含相同的圖像的卡片兩兩配對。匹配的規則是鼠標連續地點擊兩張卡片,若卡片背面的圖像相同,則匹對成功,否則配對失敗。游戲主要考察玩家的記憶力,因為游戲還規定游戲翻開的卡片數量至多有兩張,否則一開始被點擊而翻開的卡片將再次被蓋上(若該張卡片沒有匹對成功)。
接著,我們來定義一些有用的變量:
# 已經顯示正面的卡片 self.shown_cards = [] # 場上存在的卡片數量 self.num_existing_cards = len(cards_list) # 顯示游戲剩余時間 self.num_seconds = 30 self.time = Label(self.root, text=f'Time Left: {self.num_seconds}') self.time.grid(row=6, column=3, columnspan=2)
并讓界面一開始可以出現在電腦屏幕的居中位置:
# 居中顯示 self.root.withdraw() self.root.update_idletasks() x = (self.root.winfo_screenwidth() - self.root.winfo_reqwidth()) / 2 y = (self.root.winfo_screenheight() - self.root.winfo_reqheight()) / 2 self.root.geometry('+%d+%d' % (x, y)) self.root.deiconify()
由于是在有限的時間內完成所有卡片的匹對,所以我們來寫一個定時函數,并實時等更新顯示當前游戲的剩余時間:
'''計時''' def tick(self): if self.num_existing_cards == 0: return if self.num_seconds != 0: self.num_seconds -= 1 self.time['text'] = f'Time Left: {self.num_seconds}' self.time.after(1000, self.tick) else: is_restart = messagebox.askyesno('Game Over', 'You fail since time up, do you want to play again?') if is_restart: self.restart() else: self.root.destroy()
最后,我們在鼠標左鍵點擊卡片時,用代碼定義一下游戲的響應規則,以實現我們想要的功能:
'''點擊回調函數''' def clickcallback(self, event): card = event.widget if card.show: return # 之前沒有卡片被翻開 if len(self.shown_cards) == 0: self.shown_cards.append(card) image = ImageTk.PhotoImage(Image.open(os.path.join(self.card_dir, card.file+'.png'))) card.configure(image=image) card.show_image = image card.show = True # 之前只有一張卡片被翻開 elif len(self.shown_cards) == 1: # --之前翻開的卡片和現在的卡片一樣 if self.shown_cards[0].file == card.file: def delaycallback(): self.shown_cards[0].configure(image=self.blank_image) self.shown_cards[0].blank_image = self.blank_image card.configure(image=self.blank_image) card.blank_image = self.blank_image self.shown_cards.pop(0) self.score_sound.play() self.num_existing_cards -= 2 image = ImageTk.PhotoImage(Image.open(os.path.join(self.card_dir, card.file+'.png'))) card.configure(image=image) card.show_image = image card.show = True card.after(300, delaycallback) # --之前翻開的卡片和現在的卡片不一樣 else: self.shown_cards.append(card) image = ImageTk.PhotoImage(Image.open(os.path.join(self.card_dir, card.file+'.png'))) card.configure(image=image) card.show_image = image card.show = True # 之前有兩張卡片被翻開 elif len(self.shown_cards) == 2: # --之前翻開的第一張卡片和現在的卡片一樣 if self.shown_cards[0].file == card.file: def delaycallback(): self.shown_cards[0].configure(image=self.blank_image) self.shown_cards[0].blank_image = self.blank_image card.configure(image=self.blank_image) card.blank_image = self.blank_image self.shown_cards.pop(0) self.score_sound.play() self.num_existing_cards -= 2 image = ImageTk.PhotoImage(Image.open(os.path.join(self.card_dir, card.file+'.png'))) card.configure(image=image) card.show_image = image card.show = True card.after(300, delaycallback) # --之前翻開的第二張卡片和現在的卡片一樣 elif self.shown_cards[1].file == card.file: def delaycallback(): self.shown_cards[1].configure(image=self.blank_image) self.shown_cards[1].blank_image = self.blank_image card.configure(image=self.blank_image) card.blank_image = self.blank_image self.shown_cards.pop(1) self.score_sound.play() self.num_existing_cards -= 2 image = ImageTk.PhotoImage(Image.open(os.path.join(self.card_dir, card.file+'.png'))) card.configure(image=image) card.show_image = image card.show = True card.after(300, delaycallback) # --之前翻開的卡片和現在的卡片都不一樣 else: self.shown_cards.append(card) self.shown_cards[0].configure(image=self.cards_back_image) self.shown_cards[0].show = False self.shown_cards.pop(0) image = ImageTk.PhotoImage(Image.open(os.path.join(self.card_dir, card.file+'.png'))) self.shown_cards[-1].configure(image=image) self.shown_cards[-1].show_image = image self.shown_cards[-1].show = True # 判斷游戲是否已經勝利 if self.num_existing_cards == 0: is_restart = messagebox.askyesno('Game Over', 'Congratulations, you win, do you want to play again?') if is_restart: self.restart() else: self.root.destroy()
ok,大功告成。代碼邏輯比較簡單,就不展開講啦,小伙伴們簡單看下,肯定就能看懂啦。
原文鏈接:https://zhuanlan.zhihu.com/p/373217730
相關推薦
- 2022-04-03 在Python中如何優雅地創建表格的實現_python
- 2022-06-22 C語言單值二叉樹真題講解_C 語言
- 2023-12-18 MyBatisSystemException異常產生原因及解決方案
- 2022-04-05 C語言實現自動售貨機_C 語言
- 2022-06-11 SQL常用日期查詢語句及顯示格式設置_MsSql
- 2022-06-01 docker安裝nginx并配置ssl的方法步驟_docker
- 2023-02-15 Nginx如何根據前綴路徑轉發到不同的Flask服務_nginx
- 2023-01-28 Flutter項目手勢運用及單獨指針消歧問題解決方案_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支