Python实现2048
发布日期:2021-06-29 16:00:20 浏览次数:2 分类:技术文章

本文共 7511 字,大约阅读时间需要 25 分钟。

Tkinter是 Python 的标准 GUI 库。Python 使用 Tkinter 可以快速的创建 GUI 应用程序。

由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。

首先先我们先定义几个按键和颜色、背景框大小等信息

KEY_UP = "'w'"KEY_DOWN = "'s'"KEY_LEFT = "'a'"KEY_RIGHT = "'d'"BACKGROUND_COLOR_GAME = "#92877d"BACKGROUND_COLOR_CELL_EMPTY = "#9e948a"BACKGROUND_COLOR_DICT = {
2:"#eee4da", 4:"#ede0c8", 8:"#f2b179", 16:"#f59563", \ 32:"#f67c5f", 64:"#f65e3b", 128:"#edcf72", 256:"#edcc61", \ 512:"#edc850", 1024:"#edc53f", 2048:"#edc22e" }CELL_COLOR_DICT = {
2:"#776e65", 4:"#776e65", 8:"#f9f6f2", 16:"#f9f6f2", \ 32:"#f9f6f2", 64:"#f9f6f2", 128:"#f9f6f2", 256:"#f9f6f2", \ 512:"#f9f6f2", 1024:"#f9f6f2", 2048:"#f9f6f2" }FONT = ("Verdana", 40, "bold")SIZE = 500GRID_LEN = 4GRID_PADDING = 10

接着我们来写一个GameGrid类,这个类继承自TkinterFrame

class GameGrid(Frame):    def __init__(self):        Frame.__init__(self)        self.commands = {
KEY_UP: up, KEY_DOWN: down, KEY_LEFT: left, KEY_RIGHT: right} def init_grid(self): pass def gen(self): pass def init_matrix(self): pass def update_grid_cells(self): pass def key_down(self, event): pass def generate_next(self): pass

定好框架后,我们来写各个函数,先来写一个矩阵处理函数reverse,这个函数主要将矩阵

'''1 2 3     3 2 14 5 6 ==> 6 5 47 8 9     9 8 7'''def reverse(mat):    new=[]    x=y=len(mat)    for i in range(x):        new.append([])        for j in range(y):            new[i].append(mat[i][y-j-1])    return new

接着定义函数transpose,计算矩阵转置

'''1 2 3     1 4 74 5 6 ==> 2 5 87 8 9     3 6 9'''def transpose(mat):    new=[]    x=y=len(mat)    for i in range(y):        new.append([])        for j in range(x):            new[i].append(mat[j][i])    return new

定义函数cover_up

''' 0  0  2  1       2  1  0  0 6  6  5  4  ==>  6  6  5  4 0  9  8  7       9  8  7  010 11 12 13      10 11 12 13'''def cover_up(mat):    x=y=len(mat)    new=[x*[0] for i in range(y)]    done=False    for i in range(x):        count=0        for j in range(y):            if mat[i][j]!=0:                new[i][count]=mat[i][j]                if j!=count:                    done=True                count+=1    return (new,done)

定义函数merge,也就是一个合并函数

''' 0  0  2  1       2  1  0  0 6  6  5  4  ==> 12  0  5  4 0  9  8  7       9  8  7  010 11 12 13      10 11 12 13'''def merge(mat):    done=False    x=y=len(mat)    for i in range(x):         for j in range(y-1):             if mat[i][j]==mat[i][j+1] and mat[i][j]!=0:                 mat[i][j]*=2                 mat[i][j+1]=0                 done=True    return (mat,done)

接着我们处理updownrightleft函数

''' 0  0  2  1       6  6  2  1 6  6  5  4  ==> 10  9  5  4 0  9  8  7       0 11  8  710 11 12 13       0  0 12 13'''def up(game):        game=transpose(game)        game,done=cover_up(game)        temp=merge(game)        game=temp[0]        done=done or temp[1]        game=cover_up(game)[0]        game=transpose(game)        return (game,done)''' 0  0  2  1       0  0  2  1 6  6  5  4  ==>  0  6  5  4 0  9  8  7       6  9  8  710 11 12 13      10 11 12 13'''def down(game):        game=reverse(transpose(game))        game,done=cover_up(game)        temp=merge(game)        game=temp[0]        done=done or temp[1]        game=cover_up(game)[0]        game=transpose(reverse(game))        return (game,done)''' 0  0  2  1       2  1  0  0 6  6  5  4  ==> 12  5  4  0 0  9  8  7       9  8  7  010 11 12 13      10 11 12 13'''def left(game):        game,done=cover_up(game)        temp=merge(game)        game=temp[0]        done=done or temp[1]        game=cover_up(game)[0]        return (game,done)''' 0  0  2  1       0  0  2  1 6  6  5  4  ==>  0 12  5  4 0  9  8  7       0  9  8  010 11 12 13      10 11 12 13'''def right(game):        game=reverse(game)        game,done=cover_up(game)        temp=merge(game)        game=temp[0]        done=done or temp[1]        game=cover_up(game)[0]        game=reverse(game)        return (game,done)

接着定义init_grid这个图像初始化函数

def init_grid(self):    #定义背景颜色和大小    background = Frame(self, bg=BACKGROUND_COLOR_GAME, width=SIZE, height=SIZE)    #绘制背景    background.grid()    for i in range(GRID_LEN):        grid_row = []        for j in range(GRID_LEN):            #定义每个背景小方格的颜色和大小            cell = Frame(background, bg=BACKGROUND_COLOR_CELL_EMPTY, width=SIZE/GRID_LEN, height=SIZE/GRID_LEN)            #填充小方格的分割线            cell.grid(row=i, column=j, padx=GRID_PADDING, pady=GRID_PADDING)            #将label加入到frame中            t = Label(master=cell, text="", bg=BACKGROUND_COLOR_CELL_EMPTY, justify=CENTER, font=FONT, width=4, height=2)            t.grid()            grid_row.append(t)            self.grid_cells.append(grid_row)

接着我们定义一个产生随机数的函数gen

def gen():    #产生[0, GRID_LEN-1]之间的随机数    return randint(0, GRID_LEN - 1)

接着我们开始定义游戏逻辑函数,首先定义new_game函数,这个函数用来初始化n*n矩阵为0

def new_game(n):    matrix = [[0]*n for i in range(n)]    return matrix

接着我们定义坐标产生函数generate_next

def generate_next(self):    #产生随机坐标xy    index = (self.gen(), self.gen())    #如果坐标xy格子对应的数字不是0的话,重新产生坐标    while self.matrix[index[0]][index[1]] != 0:        index = (self.gen(), self.gen())    self.matrix[index[0]][index[1]] = 2

接着我们定义矩阵初始化函数init_matrix(逻辑上)

def init_matrix(self):    #初始化矩阵    self.matrix = new_game(4)    #随机初始化两个格子    self.generate_next()    self.generate_next()

接着我们定义格子初始化函数update_grid_cells(图形上)

def update_grid_cells(self):    for i in range(GRID_LEN):        for j in range(GRID_LEN):            #获取每个格子的数值            new_number = self.matrix[i][j]            #如果格子的数值为0,设置对应的格子背景颜色            if new_number == 0:                self.grid_cells[i][j].configure(text="", bg=BACKGROUND_COLOR_CELL_EMPTY)            else:#如果格子的数值不为0,设置对应的格子背景颜色,不同数字对应不同背景                self.grid_cells[i][j].configure(text=str(new_number), bg=BACKGROUND_COLOR_DICT[new_number], fg=CELL_COLOR_DICT[new_number])    #更新所有的操作    self.update_idletasks()

我们定义游戏状态函数game_state

def game_state(mat):    x=y=len(mat)    for i in range(x):        for j in range(y):            #如果矩阵有数是2048,那么就赢了            if mat[i][j]==2048:                return 'win'    for i in range(x-1):         for j in range(y-1):             if mat[i][j]==mat[i+1][j] or mat[i][j+1]==mat[i][j]:                return 'not over'    for i in range(x):         for j in range(len(y):            if mat[i][j]==0:                return 'not over'    for k in range(x-1):         if mat[x-1][k]==mat[x-1][k+1]:            return 'not over'    for j in range(x-1):         if mat[j][x-1]==mat[j+1][x-1]:            return 'not over'    return 'lose'

接着我们定义按键处理函数key_down

def key_down(self, event):    #得到输入的按键    key = repr(event.char)    if key in self.commands:        self.matrix,done = self.commands[key](self.matrix)        if done:            #产生新的坐标            self.generate_next()            #图形上更新小方格            self.update_grid_cells()            done=False            #如果游戏状态为赢的话            if game_state(self.matrix)=='win':                self.grid_cells[1][1].configure(text="You",bg=BACKGROUND_COLOR_CELL_EMPTY)                self.grid_cells[1][2].configure(text="Win!",bg=BACKGROUND_COLOR_CELL_EMPTY)            #如果游戏状态为输的话            if game_state(self.matrix)=='lose':                self.grid_cells[1][1].configure(text="You",bg=BACKGROUND_COLOR_CELL_EMPTY)                self.grid_cells[1][2].configure(text="Lose!",bg=BACKGROUND_COLOR_CELL_EMPTY)

回顾上面的所有细节,我们发现最困难的地方就在于矩阵的处理上面

项目地址,give me a star O(∩_∩)O!

转载地址:https://coordinate.blog.csdn.net/article/details/79308531 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:c++中空字符串解释为True的困惑
下一篇:图片转化为字符画

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月26日 07时27分21秒