利用 Python_tkinter 完成 2048 遊戲

成品展現 

具有基本的數據合併以及分數統計,不一樣數字的色塊不一樣python

產生隨機數, 數據沒法合併斷定以及從新開始選項算法

 同時能夠斷定遊戲失敗條件數據結構

 

需求分析

  • 完成基本數據合併算法
  • 遊戲結束條件
  • 界面展現
  • 重置按鈕
  • 分數統計

代碼邏輯

頁面建立

展現數據

建立一個基本的數據結構地圖數據來保存各位置的數值app

_map_data = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
]

 

展現圖形

利用 tkinter 經過遍歷地圖數據來循環建立標籤dom

建立時利用 tkinter 設置樣式以及顏色函數

一樣維護一個列表來填入每行的標籤oop

    map_labels = [] 
    for r in range(4):
        row = []
        for c in range(len(_map_data[0])):
            value = _map_data[r][c]
            text = str(value) if value else ''
            label = Label(frame, text=text, width=4, height=2,
                          font=("黑體", 30, "bold"))
            label.grid(row=r, column=c, padx=5, pady=5, sticky=N + E + W + S)
            row.append(label)
        map_labels.append(row)

 

色塊設置

不一樣數值的色塊以不一樣的顏色標識佈局

    # 設置遊戲中每一個數據對應色塊的顏色
    mapcolor = {
        0: ("#cdc1b4", "#776e65"),
        2: ("#eee4da", "#776e65"),
        4: ("#ede0c8", "#f9f6f2"),
        8: ("#f2b179", "#f9f6f2"),
        16: ("#f59563", "#f9f6f2"),
        32: ("#f67c5f", "#f9f6f2"),
        64: ("#f65e3b", "#f9f6f2"),
        128: ("#edcf72", "#f9f6f2"),
        256: ("#edcc61", "#f9f6f2"),
        512: ("#e4c02a", "#f9f6f2"),
        1024: ("#e2ba13", "#f9f6f2"),
        2048: ("#ecc400", "#f9f6f2"),
        4096: ("#ae84a8", "#f9f6f2"),
        8192: ("#b06ca8", "#f9f6f2"),
        # ----其它顏色都與8192相同---------
        2 ** 14: ("#b06ca8", "#f9f6f2"),
        2 ** 15: ("#b06ca8", "#f9f6f2"),
        2 ** 16: ("#b06ca8", "#f9f6f2"),
        2 ** 17: ("#b06ca8", "#f9f6f2"),
        2 ** 18: ("#b06ca8", "#f9f6f2"),
        2 ** 19: ("#b06ca8", "#f9f6f2"),
        2 ** 20: ("#b06ca8", "#f9f6f2"),
    }

 

分數顯示

建立兩個標籤分別標識分數 , 以及數字ui

label = Label(frame, text='分數', font=("黑體", 30, "bold"),
                  bg="#bbada0", fg="#eee4da")
label.grid(row=4, column=0, padx=5, pady=5)
label_score = Label(frame, text='0', font=("黑體", 30, "bold"),
                        bg="#bbada0", fg="#ffffff")
label_score.grid(row=4, columnspan=2, column=1, padx=5, pady=5)

 

重置按鈕

重置按鈕須要作到將遊戲重置spa

即地圖數據還原以及分數重置

此部分須要設計相關 函數來負責重置以及刷新界面

def reset():
    '''從新設置遊戲數據,將地圖恢復爲初始狀態,並加入兩個數據 2 做用初始狀態'''
    _map_data[:] = []  # _map_data.clear()
    _map_data.append([0, 0, 0, 0])
    _map_data.append([0, 0, 0, 0])
    _map_data.append([0, 0, 0, 0])
    _map_data.append([0, 0, 0, 0])
    # 在空白地圖上填充兩個2
    fill2()
    fill2()

 

    def reset_game():
        reset()
        update_ui()

    restart_button = Button(frame, text='從新開始', font=("黑體", 16, "bold"),
                            bg="#8f7a66", fg="#f9f6f2", command=reset_game)
    restart_button.grid(row=4, column=3, padx=5, pady=5)

 

計算邏輯

移動邏輯

移動的邏輯分爲兩步

移動數字和合並數字

可是合併數字後又會發現存在空格, 所以須要第三步

def _left_move_number(line):
    '''左移一行數字,若是有數據移動則返回True,不然返回False:
    如: line = [0, 2, 0, 8] 即表達以下一行:
        +---+---+---+---+
        | 0 | 2 | 0 | 8 |      <----向左移動
        +---+---+---+---+
    此行數據須要左移三次:
      第一次左移結果:
        +---+---+---+---+
        | 2 | 0 | 8 | 0 |
        +---+---+---+---+
      第二次左移結果:
        +---+---+---+---+
        | 2 | 8 | 0 | 0 |
        +---+---+---+---+
      第三次左移結果:
        +---+---+---+---+
        | 2 | 8 | 0 | 0 |  # 由於最左則爲2,因此8不動
        +---+---+---+---+
     最終結果: line = [4, 8, 0, 0]
    '''
    moveflag = False  # 是否移動的標識,先假設沒有移動
    for _ in range(3):  # 重複執行下面算法三次
        for i in range(3):  # i爲索引
            if 0 == line[i]:  # 此處有空位,右側相鄰數字向左側移動,右側填空白
                moveflag = True
                line[i] = line[i + 1]
                line[i + 1] = 0
    return moveflag


def _left_marge_number(line):
    '''向左側進行相同單元格合併,合併結果放在左側,右側補零
    如: line = [2, 2, 4, 4] 即表達以下一行:
        +---+---+---+---+
        | 2 | 2 | 4 | 4 |
        +---+---+---+---+
    全並後的結果爲:
        +---+---+---+---+
        | 4 | 0 | 8 | 0 |
        +---+---+---+---+
    最終結果: line = [4, 8, 8, 0]
    '''
    for i in range(3):
        if line[i] == line[i + 1]:
            moveflag = True
            line[i] *= 2  # 左側翻倍
            line[i + 1] = 0  # 右側歸零


def _left_move_aline(line):
    '''左移一行數據,若是有數據移動則返回True,不然返回False:
    如: line = [2, 0, 2, 8] 即表達以下一行:
        +---+---+---+---+
        | 2 |   | 2 | 8 |      <----向左移動
        +---+---+---+---+
    左移算法分爲三步:
        1. 將全部數字向左移動來填補左側空格,即:
            +---+---+---+---+
            | 2 | 2 | 8 |   |
            +---+---+---+---+
        2. 判斷是否發生碰幢,若是兩個相臨且相等的數值則說明有碰撞須要合併,
           合併結果靠左,右則填充空格 
            +---+---+---+---+
            | 4 |   | 8 |   |
            +---+---+---+---+
        3. 再重複第一步,將全部數字向左移動來填補左側空格,即:
            +---+---+---+---+
            | 4 | 8 |   |   |
            +---+---+---+---+
        最終結果: line = [4, 8, 0, 0]
    '''
    moveflag = False
    if _left_move_number(line):
        moveflag = True
    if _left_marge_number(line):
        moveflag = True
    if _left_move_number(line):
        moveflag = True
    return moveflag

上下左右移動實現

基本實現了一個就能夠所有實現了

本質自己就是列表 , 翻轉方向的就翻轉列表便可. 可是記得要再轉回來

上下的列表就是4個列表的同索引位置從新拼接列表. 

一樣翻轉後在翻轉

def left():
    """遊戲左鍵按下時或向左滑動屏幕時的算法"""
    moveflag = False  # moveflag 是否成功移動數字標誌位,若是有移動則爲真值,原地圖不變則爲假值

    # 將第一行都向左移動.若是有移動就返回True
    for line in _map_data:
        if _left_move_aline(line):
            moveflag = True
    return moveflag


def right():
    """遊戲右鍵按下時或向右滑動屏幕時的算法
    選將屏幕進行左右對調,對調後,原來的向右滑動即爲如今的向左滑動
    滑動完畢後,再次左右對調回來
    """
    # 左右對調
    for r in _map_data:
        r.reverse()
    moveflag = left()  # 向左滑動
    # 再次左右對調
    for r in _map_data:
        r.reverse()
    return moveflag


def up():
    """遊戲上鍵按下時或向上滑動屏幕時的算法
    先把每一列都自上而下放入一個列表中line中,而後執行向滑動,
    滑動完成後再將新位置擺回到原來的一列中
    """
    moveflag = False
    line = [0, 0, 0, 0]  # 先初始化一行,準備放入數據
    for col in range(4):  # 先取出每一列
        # 把一列中的每一行數入放入到line中
        for row in range(4):
            line[row] = _map_data[row][col]
        # 將當前列進行上移,即line 左移
        if (_left_move_aline(line)):
            moveflag = True
        # 把左移後的 line中的數據填充回原來的一列
        for row in range(4):
            _map_data[row][col] = line[row]
    return moveflag


def down():
    """遊戲下鍵按下時或向下滑動屏幕時的算法
    選將屏幕進行上下對調,對調後,原來的向下滑動即爲如今的向上滑動
    滑動完畢後,再次上下對調回來
    """
    _map_data.reverse()
    moveflag = up()  # 上滑
    _map_data.reverse()
    return moveflag

結束斷定

def is_gameover():
    """判斷遊戲是否結束,若是結束返回True,否是返回False
    """
    for r in _map_data:
        # 若是水平方向還有0,則遊戲沒有結束
        if r.count(0):
            return False
        # 水平方向若是有兩個相鄰的元素相同,應當是能夠合併的,則遊戲沒有結束
        for i in range(3):
            if r[i] == r[i + 1]:
                return False
    for c in range(4):
        # 豎直方向若是有兩個相鄰的元素相同,應當能夠合併的,則遊戲沒有結束
        for r in range(3):
            if _map_data[r][c] == _map_data[r + 1][c]:
                return False
    # 以上都沒有,則遊戲結束
    return True

 

分數統計

def get_score():
    '''獲取遊戲的分數,得分規則是每次有兩個數加在一塊兒則生成相應的分數。
    如 2 和 2 合併後得4分, 8 和 8 分並後得 16分.
    根據一個大於2的數字就能夠知道他共合併了多少次,能夠直接算出分數:
    如:
       4 必定由兩個2合併,得4分
       8 必定由兩個4合併,則計:8 + 4 + 4 得32分
       ... 以此類推
    '''
    score = 0
    for r in _map_data:
        for c in r:
            score += 0 if c < 4 else c * int((math.log(c, 2) - 1.0))
    return score  # 導入數學模塊

 

 

隨機數添加

隨機數的添加形式爲 添加一個 2 到任意一個爲 0 的位置

先進行一個 0 位置的數量統計

 

def get_space_count():
    """獲取沒有數字的方格的數量,若是數量爲0則說有沒法填充新數據,遊戲即將結束
    """
    count = 0
    for r in _map_data:
        count += r.count(0)
    return count

 

利用定義偏移量來添加, 隨機 0~0位置統計個數, 而後選一個後循環+1偏移量到被選到數字進行復製爲 2 

def fill2():
    '''填充2到空位置,若是填度成功返回True,若是已滿,則返回False'''
    blank_count = get_space_count()  # 獲得地圖上空白位置的個數
    if 0 == blank_count:
        return False
    # 生成隨機位置, 如,當只有四個空時,則生成0~3的數,表明自左至右,自上而下的空位置
    pos = random.randrange(0, blank_count)
    offset = 0
    for row in _map_data:  # row爲行row
        for col in range(4):  # col 爲列,column
            if 0 == row[col]:
                if offset == pos:
                    # 把2填充到第row行,第col列的位置,返回True
                    row[col] = 2
                    return True
                offset += 1

 

鍵盤映射響應

keymap = {
        'a': left,
        'd': right,
        'w': up,
        's': down,
        'Left': left,
        'Right': right,
        'Up': up,
        'Down': down,
        'q': root.quit,
    }
    def on_key_down(event):
        '鍵盤按下處理函數'
        keysym = event.keysym
        if keysym in keymap:
            if keymap[keysym]():  # 若是有數字移動
                fill2()  # 填充一個新的2
        update_ui()
        if is_gameover():
            mb = messagebox.askyesno(
                title="gameover", message="遊戲結束!\n是否退出遊戲!")
            if mb:
                root.quit()
            else:
                reset()
                update_ui()

 

# 設置焦點能接收按鍵事件
    frame.focus_set()
    frame.bind("<Key>", on_key_down)

 

刷新界面

    def update_ui():
        '''刷新界面函數
        根據計算出的f地圖數據,更新各個Label的設置
        '''
        for r in range(4):
            for c in range(len(_map_data[0])):
                number = _map_data[r][c]  # 設置數字
                label = map_labels[r][c]  # 選中Lable控件
                label['text'] = str(number) if number else ''
                label['bg'] = mapcolor[number][0]
                label['foreground'] = mapcolor[number][1]
        label_score['text'] = str(get_score())  # 重設置分數

 

所有代碼

"""2048遊戲
本模塊已完整實現2048遊戲的算法及分數的計算算法
本遊戲的界面採用python 標準庫 tkinter 來實現
此界面的佈局採用tkinter中的grid佈局
"""

import random
import math
import sys

_map_data = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
]


# -------------------------如下爲2048遊戲的基本算法---------------------------

# 重置
def reset():
    '''從新設置遊戲數據,將地圖恢復爲初始狀態,並加入兩個數據 2 做用初始狀態'''
    _map_data[:] = []  # _map_data.clear()
    _map_data.append([0, 0, 0, 0])
    _map_data.append([0, 0, 0, 0])
    _map_data.append([0, 0, 0, 0])
    _map_data.append([0, 0, 0, 0])
    # 在空白地圖上填充兩個2
    fill2()
    fill2()


# 獲取 0 個數
def get_space_count():
    """獲取沒有數字的方格的數量,若是數量爲0則說有沒法填充新數據,遊戲即將結束
    """
    count = 0
    for r in _map_data:
        count += r.count(0)
    return count


# 計算分數
def get_score():
    '''獲取遊戲的分數,得分規則是每次有兩個數加在一塊兒則生成相應的分數。
    如 2 和 2 合併後得4分, 8 和 8 分並後得 16分.
    根據一個大於2的數字就能夠知道他共合併了多少次,能夠直接算出分數:
    如:
       4 必定由兩個2合併,得4分
       8 必定由兩個4合併,則計:8 + 4 + 4 得32分
       ... 以此類推
    '''
    score = 0
    for r in _map_data:
        for c in r:
            score += 0 if c < 4 else c * int((math.log(c, 2) - 1.0))
    return score  # 導入數學模塊


# 隨機數生成
def fill2():
    '''填充2到空位置,若是填度成功返回True,若是已滿,則返回False'''
    blank_count = get_space_count()  # 獲得地圖上空白位置的個數
    if 0 == blank_count:
        return False
    # 生成隨機位置, 如,當只有四個空時,則生成0~3的數,表明自左至右,自上而下的空位置
    pos = random.randrange(0, blank_count)
    offset = 0
    for row in _map_data:  # row爲行row
        for col in range(4):  # col 爲列,column
            if 0 == row[col]:
                if offset == pos:
                    # 把2填充到第row行,第col列的位置,返回True
                    row[col] = 2
                    return True
                offset += 1


# 結束斷定
def is_gameover():
    """判斷遊戲是否結束,若是結束返回True,否是返回False
    """
    for r in _map_data:
        # 若是水平方向還有0,則遊戲沒有結束
        if r.count(0):
            return False
        # 水平方向若是有兩個相鄰的元素相同,應當是能夠合併的,則遊戲沒有結束
        for i in range(3):
            if r[i] == r[i + 1]:
                return False
    for c in range(4):
        # 豎直方向若是有兩個相鄰的元素相同,應當能夠合併的,則遊戲沒有結束
        for r in range(3):
            if _map_data[r][c] == _map_data[r + 1][c]:
                return False
    # 以上都沒有,則遊戲結束
    return True


# 移動合併分數
def _left_move_number(line):
    '''左移一行數字,若是有數據移動則返回True,不然返回False:
    如: line = [0, 2, 0, 8] 即表達以下一行:
        +---+---+---+---+
        | 0 | 2 | 0 | 8 |      <----向左移動
        +---+---+---+---+
    此行數據須要左移三次:
      第一次左移結果:
        +---+---+---+---+
        | 2 | 0 | 8 | 0 |
        +---+---+---+---+
      第二次左移結果:
        +---+---+---+---+
        | 2 | 8 | 0 | 0 |
        +---+---+---+---+
      第三次左移結果:
        +---+---+---+---+
        | 2 | 8 | 0 | 0 |  # 由於最左則爲2,因此8不動
        +---+---+---+---+
     最終結果: line = [4, 8, 0, 0]
    '''
    moveflag = False  # 是否移動的標識,先假設沒有移動
    for _ in range(3):  # 重複執行下面算法三次
        for i in range(3):  # i爲索引
            if 0 == line[i]:  # 此處有空位,右側相鄰數字向左側移動,右側填空白
                moveflag = True
                line[i] = line[i + 1]
                line[i + 1] = 0
    return moveflag


# 移動位置
def _left_marge_number(line):
    '''向左側進行相同單元格合併,合併結果放在左側,右側補零
    如: line = [2, 2, 4, 4] 即表達以下一行:
        +---+---+---+---+
        | 2 | 2 | 4 | 4 |
        +---+---+---+---+
    全並後的結果爲:
        +---+---+---+---+
        | 4 | 0 | 8 | 0 |
        +---+---+---+---+
    最終結果: line = [4, 8, 8, 0]
    '''
    for i in range(3):
        if line[i] == line[i + 1]:
            moveflag = True
            line[i] *= 2  # 左側翻倍
            line[i + 1] = 0  # 右側歸零


# 移動邏輯
def _left_move_aline(line):
    '''左移一行數據,若是有數據移動則返回True,不然返回False:
    如: line = [2, 0, 2, 8] 即表達以下一行:
        +---+---+---+---+
        | 2 |   | 2 | 8 |      <----向左移動
        +---+---+---+---+
    左移算法分爲三步:
        1. 將全部數字向左移動來填補左側空格,即:
            +---+---+---+---+
            | 2 | 2 | 8 |   |
            +---+---+---+---+
        2. 判斷是否發生碰幢,若是兩個相臨且相等的數值則說明有碰撞須要合併,
           合併結果靠左,右則填充空格 
            +---+---+---+---+
            | 4 |   | 8 |   |
            +---+---+---+---+
        3. 再重複第一步,將全部數字向左移動來填補左側空格,即:
            +---+---+---+---+
            | 4 | 8 |   |   |
            +---+---+---+---+
        最終結果: line = [4, 8, 0, 0]
    '''
    moveflag = False
    if _left_move_number(line):
        moveflag = True
    if _left_marge_number(line):
        moveflag = True
    if _left_move_number(line):
        moveflag = True
    return moveflag


def left():
    """遊戲左鍵按下時或向左滑動屏幕時的算法"""
    moveflag = False  # moveflag 是否成功移動數字標誌位,若是有移動則爲真值,原地圖不變則爲假值

    # 將第一行都向左移動.若是有移動就返回True
    for line in _map_data:
        if _left_move_aline(line):
            moveflag = True
    return moveflag


def right():
    """遊戲右鍵按下時或向右滑動屏幕時的算法
    選將屏幕進行左右對調,對調後,原來的向右滑動即爲如今的向左滑動
    滑動完畢後,再次左右對調回來
    """
    # 左右對調
    for r in _map_data:
        r.reverse()
    moveflag = left()  # 向左滑動
    # 再次左右對調
    for r in _map_data:
        r.reverse()
    return moveflag


def up():
    """遊戲上鍵按下時或向上滑動屏幕時的算法
    先把每一列都自上而下放入一個列表中line中,而後執行向滑動,
    滑動完成後再將新位置擺回到原來的一列中
    """
    moveflag = False
    line = [0, 0, 0, 0]  # 先初始化一行,準備放入數據
    for col in range(4):  # 先取出每一列
        # 把一列中的每一行數入放入到line中
        for row in range(4):
            line[row] = _map_data[row][col]
        # 將當前列進行上移,即line 左移
        if (_left_move_aline(line)):
            moveflag = True
        # 把左移後的 line中的數據填充回原來的一列
        for row in range(4):
            _map_data[row][col] = line[row]
    return moveflag


def down():
    """遊戲下鍵按下時或向下滑動屏幕時的算法
    選將屏幕進行上下對調,對調後,原來的向下滑動即爲如今的向上滑動
    滑動完畢後,再次上下對調回來
    """
    _map_data.reverse()
    moveflag = up()  # 上滑
    _map_data.reverse()
    return moveflag


# -------------------------如下爲2048遊戲的操做界面---------------------------

if (sys.version_info > (3, 0)):
    from tkinter import *
    from tkinter import messagebox
else:
    from Tkinter import *


def main():
    reset()  # 先從新設置遊戲數據

    root = Tk()  # 建立tkinter窗口
    root.title('2048遊戲')  # 設置標題文字
    root.resizable(width=False, height=False)  # 固定寬和高

    # 如下是鍵盤映射
    keymap = {
        'a': left,
        'd': right,
        'w': up,
        's': down,
        'Left': left,
        'Right': right,
        'Up': up,
        'Down': down,
        'q': root.quit,
    }

    game_bg_color = "#bbada0"  # 設置背景顏色

    # 設置遊戲中每一個數據對應色塊的顏色
    mapcolor = {
        0: ("#cdc1b4", "#776e65"),
        2: ("#eee4da", "#776e65"),
        4: ("#ede0c8", "#f9f6f2"),
        8: ("#f2b179", "#f9f6f2"),
        16: ("#f59563", "#f9f6f2"),
        32: ("#f67c5f", "#f9f6f2"),
        64: ("#f65e3b", "#f9f6f2"),
        128: ("#edcf72", "#f9f6f2"),
        256: ("#edcc61", "#f9f6f2"),
        512: ("#e4c02a", "#f9f6f2"),
        1024: ("#e2ba13", "#f9f6f2"),
        2048: ("#ecc400", "#f9f6f2"),
        4096: ("#ae84a8", "#f9f6f2"),
        8192: ("#b06ca8", "#f9f6f2"),
        # ----其它顏色都與8192相同---------
        2 ** 14: ("#b06ca8", "#f9f6f2"),
        2 ** 15: ("#b06ca8", "#f9f6f2"),
        2 ** 16: ("#b06ca8", "#f9f6f2"),
        2 ** 17: ("#b06ca8", "#f9f6f2"),
        2 ** 18: ("#b06ca8", "#f9f6f2"),
        2 ** 19: ("#b06ca8", "#f9f6f2"),
        2 ** 20: ("#b06ca8", "#f9f6f2"),
    }

    def on_key_down(event):
        '鍵盤按下處理函數'
        keysym = event.keysym
        if keysym in keymap:
            if keymap[keysym]():  # 若是有數字移動
                fill2()  # 填充一個新的2
        update_ui()
        if is_gameover():
            mb = messagebox.askyesno(
                title="gameover", message="遊戲結束!\n是否退出遊戲!")
            if mb:
                root.quit()
            else:
                reset()
                update_ui()

    def update_ui():
        '''刷新界面函數
        根據計算出的f地圖數據,更新各個Label的設置
        '''
        for r in range(4):
            for c in range(len(_map_data[0])):
                number = _map_data[r][c]  # 設置數字
                label = map_labels[r][c]  # 選中Lable控件
                label['text'] = str(number) if number else ''
                label['bg'] = mapcolor[number][0]
                label['foreground'] = mapcolor[number][1]
        label_score['text'] = str(get_score())  # 重設置分數

    # 建立一個frame窗口,此建立將容納所有的widget 部件
    frame = Frame(root, bg=game_bg_color)
    frame.grid(sticky=N + E + W + S)
    # 設置焦點能接收按鍵事件
    frame.focus_set()
    frame.bind("<Key>", on_key_down)

    # 初始化圖形界面
    map_labels = []
    for r in range(4):
        row = []
        for c in range(len(_map_data[0])):
            value = _map_data[r][c]
            text = str(value) if value else ''
            label = Label(frame, text=text, width=4, height=2,
                          font=("黑體", 30, "bold"))
            label.grid(row=r, column=c, padx=5, pady=5, sticky=N + E + W + S)
            row.append(label)
        map_labels.append(row)

    # 設置顯示分數的Lable
    label = Label(frame, text='分數', font=("黑體", 30, "bold"),
                  bg="#bbada0", fg="#eee4da")
    label.grid(row=4, column=0, padx=5, pady=5)
    label_score = Label(frame, text='0', font=("黑體", 30, "bold"),
                        bg="#bbada0", fg="#ffffff")
    label_score.grid(row=4, columnspan=2, column=1, padx=5, pady=5)

    # 如下設置從新開始按鈕
    def reset_game():
        reset()
        update_ui()

    restart_button = Button(frame, text='從新開始', font=("黑體", 16, "bold"),
                            bg="#8f7a66", fg="#f9f6f2", command=reset_game)
    restart_button.grid(row=4, column=3, padx=5, pady=5)

    update_ui()  # 更新界面

    root.mainloop()  # 進入tkinter主事件循環


main()  # 啓動遊戲
相關文章
相關標籤/搜索