使用 Python3 實現翻牌遊戲(記憶遊戲)
歡迎閱讀這篇博文,我們將討論一個名為 Flip! 的趣味遊戲的實現,該遊戲使用 Python 開發。Flip! 是一款在 4x4 網格上翻轉瓦片以顯示其顏色的遊戲。遊戲的目標是在儘可能少的步數內翻轉所有瓦片。在這篇文章中,我們將逐步介紹使用 Python 實現該遊戲的過程,並解釋程式碼的不同組成部分。
語法
以下軟體包用於此程式碼:
itertools - 該軟體包提供函式,以更簡單的方式迭代集合。
tkinter - 該軟體包為遊戲提供圖形使用者介面 (GUI)。
random - 該軟體包提供函式來生成隨機數。
ctypes - 該軟體包提供對低階 Windows 函式的訪問。
由於這些軟體包都是 Python 預設庫的一部分,因此無需額外安裝。
演算法
按下按鈕時,按鈕的顏色會顯示出來,並將其與之前按下的按鈕的顏色進行比較。
如果兩種顏色匹配,則按鈕保持翻轉狀態,並更新玩家的分數。如果兩種顏色不匹配,則按鈕翻轉回來,並且玩家的分數不會改變。
遊戲持續進行,直到所有按鈕都被翻轉過來,程式將玩家的最高分儲存在名為 maxscore.txt 的文字檔案中。
在遊戲結束時,將玩家的分數與其最高分進行比較,如果玩家的分數更高,則更改檔案中的最高分。
按下按鈕會導致按鈕的白色背景發生變化,以顯示下面的顏色。
當連續按下相同顏色的兩個按鈕時,它們會保持翻轉狀態。連續按下兩個不同顏色的按鈕,它們會翻轉回來。
所有按鈕都翻轉後,遊戲結束並顯示玩家的分數。
玩家翻轉按鈕的次數決定了他們的分數。
import itertools import tkinter as tk import random import ctypes ctypes.windll.shcore.SetProcessDpiAwareness(1) pressed = -1 tile_flipped = 16 count_move = 0 maxscore = 0 def is_winner(): global maxscore, count_move if tile_flipped == 0: if count_move <= maxscore or maxscore == -1: maxscore = count_move with open('maxscore.txt', 'w') as f: f.write(str(maxscore)) win_lbl['text'] = f'CLICKS: {str(count_move)}, BEST: {str(maxscore)}' def print_count_move(): win_lbl['text'] = f'CLICKS: {str(count_move)}' def new_game(): global pressed, tile_flipped, btns, colours, count_move, win_lbl, maxscore pressed = -1 tile_flipped = 16 count_move = 0 btns = {} win_lbl['text'] = '' # make the file if it doesn't exist try: with open('maxscore.txt', 'r') as f: pass except FileNotFoundError: with open('maxscore.txt', 'w') as f: f.write('-1') with open('maxscore.txt', 'r') as f: maxscore = int(f.readline().strip()) random.shuffle(colours) k=0 for _, _ in itertools.product(range(4), range(4)): btn = Button(k) btns[k] = btn if k!= len(colours)-1: k+=1 k=0 for i, j in itertools.product(range(4), range(4)): btns[k].bttn.grid(row=i, column=j, sticky='nsew') if k!= len(colours)-1: k+=1 class Button: def __init__(self, k): self.index = k self.bttn = tk.Button(frm,width=6, height=2,borderwidth=6, bg='white', activebackground = colours[self.index],command=self.btn_press) def btn_press(self): global pressed, count_move self.bttn.configure(bg=colours[self.index]) count_move += 1 print_count_move() if pressed == -1: pressed = self.index else: self.compare_pressed_btns() def compare_pressed_btns(self): global pressed global tile_flipped if colours[self.index] != colours[pressed]: self.bttn.configure(bg='white') btns[pressed].bttn.configure(bg='white') elif self.index != pressed: self.bttn['state'] = tk.DISABLED btns[pressed].bttn['state']= tk.DISABLED tile_flipped -= 2 is_winner() else: self.bttn.configure(bg='white') pressed = -1 window = tk.Tk() window.title('Flip!') window.config(bg = 'black') window.rowconfigure([0,1],weight=1,pad=2) window.columnconfigure(0,weight =1, pad=2) frm = tk.Frame(window, bg='Gray') frm.grid(row = 0, column=0, sticky='nsew') frm.rowconfigure(list(range(4)), minsize=50, pad=2) frm.columnconfigure(list(range(4)), minsize=50, pad=2) btns = {} colours=['YellowGreen', 'Violet', 'Tomato', 'SlateBlue', 'DarkCyan', 'Orange','DodgerBlue', 'ForestGreen']*2 random.shuffle(colours) frm2 = tk.Frame(window, bg='Khaki') win_lbl = tk.Label(frm2,width=19, height=1,bg='PowderBlue',relief=tk.GROOVE,borderwidth=2) win_lbl.grid(row=0, column=0, padx=5, pady=5, sticky='nsew') new_game_btn = tk.Button(text='NEW GAME', master=frm2, width=10, height=1, borderwidth=3, bg='Plum', command=new_game) new_game_btn.grid(row=0, column=1, padx=5, pady=5, sticky = 'nsew') frm2.grid(row=1, column=0, sticky='nsew') new_game() window.mainloop()
輸出
解釋
在這個流行的記憶遊戲 Flip 的簡化版本中,玩家會看到一個按鈕網格,每個按鈕最初顯示為白色,並且 4x4 網格中的每個按鈕都隱藏了一個顏色。使用者需要在翻轉按鈕時匹配兩個按鈕的顏色,直到沒有兩個按鈕剩餘為止,遊戲結束。
首先匯入必要的庫,包括用於圖形使用者介面的 random、itertools、tkinter 和用於 Windows 特定功能的 ctypes。Random 模組用於重新排列按鈕的顏色。設定不同的全域性變數來跟蹤遊戲的進度。"pressed" 用於跟蹤最近一次按鈕按下事件的索引,"tile flipped" 顯示匹配了多少個按鈕,"count move" 顯示進行了多少次移動,而 "maxscore" 顯示遊戲中的最高分。
is_winner 函式負責檢查遊戲是否獲勝。它檢查所有瓦片是否都已翻轉,即 tile_flipped 是否等於零,如果是,則檢查當前移動次數 count_move 是否小於或等於之前的最高分 maxscore。如果是,則將 maxscore 更新為新的 count_move 並將其寫入名為 maxscore.txt 的檔案中。最後,它更新 win_lbl 標籤的文字以顯示當前分數和最高分。
print_count_move 函式更新 win_lbl 標籤以顯示當前移動次數。
new_game 函式負責重置遊戲。它將變數初始化為預設值,清除 win_lbl 標籤,並從 maxscore.txt 檔案中讀取之前的最高分。然後,它對顏色列表進行洗牌,並使用 Button 類建立按鈕網格。它還在螢幕上設定按鈕的網格佈局。
Button 類定義了遊戲中每個瓦片的屬性和行為。每個按鈕都有一個索引值,對應於它在顏色洗牌列表中的位置。它建立一個 tk.Button 物件,其背景顏色為白色,活動背景顏色與其分配的顏色匹配。當按鈕被點選時,其背景顏色會更改為其分配的顏色,並且 count_move 會遞增。如果按鈕是第一個被點選的按鈕,則它會將索引值儲存在 pressed 變數中。如果是第二個被點選的按鈕,則透過呼叫 compare_pressed_btns 方法將其顏色與第一個按鈕的顏色進行比較。如果顏色匹配,則停用按鈕,並且 tile_flipped 計數遞減。如果顏色不匹配,則將按鈕的背景顏色改回白色。
最後,程式碼的主體初始化 GUI 視窗,設定其標題和背景顏色,並建立 frm 和 frm2 框架,分別用於容納遊戲板和分數標籤以及新遊戲按鈕。它還建立了 win_lbl 標籤和 new_game_btn 按鈕並設定其屬性。然後,它呼叫 new_game 函式以開始遊戲。最後,它使用 window.mainloop() 進入主事件迴圈。
應用
這個專案可以展示圖形使用者介面 (GUI)、按鈕和函式的概念;同樣,它也作為評估和提高記憶能力的絕佳方式,使用清晰的圖形連線點。可以進一步修改遊戲以包含各種形狀、顏色和影像,使其成為初學者學習如何使用 Python 程式設計圖形使用者介面的絕佳專案。
結論
使用 Tkinter 工具包和 Python 3 開發的翻牌遊戲既有趣又引人入勝,它是學習 Python GUI 開發的絕佳專案。按鈕和函式的使用演示瞭如何使用程式語言和 GUI 框架建立互動式圖形介面,因此可以根據自己的喜好調整此益智遊戲,並且是初學者開始學習 Python 程式語言的圖形使用者介面的好起點。