本文共 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
类,这个类继承自Tkinter
的Frame
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)
接着我们处理up
、down
、right
、left
函数
''' 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!