基于python做一个2048小游戏
作者:微小冷
2048的逻辑无非是操作4*4的方格,每个方格中有一个数,这些数可以移动,如果两个相同的数字在移动时相撞了,就可以彼此合并,本文将给大家介绍如何基于python做一个2048小游戏,感兴趣的小伙伴跟着小编一起来看看吧
逻辑设计
2048的逻辑无非是操作4 × 4 的方格,每个方格中有一个数,这些数可以移动,如果两个相同的数字在移动时相撞了,就可以彼此合并。
而这个4 × 4的方格,无非是一个矩阵。只需设计好移动逻辑,再用PyGame将这个方格表现出来就算大功告成。
2048只有四个手势动作,即上下左右,这四个动作所引发的结果都可以归结为对单行或者单列的操作,进而归结为对一个列表的操作。
首先,对列表进行操作时,先排除0的影响,在排除0的影响之后,若相邻元素相等,即可合并。例如对于[ 0 , 2 , 2 , 0 ],如果向左合并则输出为[ 4 , 0 , 0 , 0 ]。
def mergeLst(lst): lst = [x for x in lst if x] # 删除lst中的0 newLst = [] N, i = len(lst), 0 while i < N: if i<N-1 and lst[i] == lst[i+1]: newLst.append(lst[i]*2) i += 2 else: newLst.append(lst[i]) i += 1 return newLst + (4-len(newLst))*[0]
测试如下
mergeLst([0,2,2,0]) # [4, 0, 0, 0] mergeLst([2,2,2,2]) # [4, 4, 0, 0] mergeLst([2,2,8,4]) # [4, 8, 4, 0]
相应地,对一个矩阵进行合并,只需针对每一行进行操作即可
[mergeLst(x) for x in mat]
对于上下左右不同按键的操作,可以先将矩阵旋转,然后再进行合并操作,合并之后再逆转回来。
def rotate(mat): newMat = [[[] for _ in mat] for b in mat[0]] for i,row in enumerate(mat, 1): for j,r in enumerate(row, 0): newMat[j][-i] = r return newMat
在实际操作中,左、下、右、上分别对应旋转0,1,2,3次,即
KEY_DCT = { pygame.K_LEFT:0, pygame.K_DOWN:1, pygame.K_RIGHT:2, pygame.K_UP:3 }
从而游戏的总挪动逻辑如下
def updateMat(mat, key): N = KEY_DCT[key] for _ in range(N): mat = rotate(mat) mat = [mergeLst(x) for x in mat] for _ in range(4-N): mat = rotate(mat) # 旋转回来 return mat
2048游戏在开始之前,需要初始化一个4x4
的矩阵,然后每次操作之前,需要在矩阵中为0的位置随机生成一个数。随机生成的数的取值范围决定了游戏的难度,所以生成方式也比较灵活,下面给出一种普通的生成方法
from itertools import product from random import sample, randint def addNew(mat): ijs = [] for i,j in product(range(4), range(4)): if mat[i][j] == 0: ijs.appen((i,j)) if len(ijs) == 0: return False i, j = sample(ijs, 1)[0] # 挑选一个不为0的点 x = randint(1,100) x = 7 - np.floor(np.log2(x)) mat[i,j] = int(2**x) return True
绘图逻辑
这个游戏的绘图逻辑比较简单,只需为矩阵中每个元素赋予一个颜色即可。
GRAY = (205, 205, 205) WHITE = (255, 255, 255) GREEN = (0, 255, 0) SIZE = 80 def setColor(N): if N == 0: return (233, 233, 233) n = int(math.log2(N)) delta = int(255/15) return (255-n*delta, n*delta, (128+n*delta)%255) def draw(win, font, mat): for i,j in product(range(4), range(4)): ch = str(mat[i][j]) rect = (j*SIZE, i*SIZE, SIZE, SIZE) c = setColor(mat[i][j]) pygame.draw.rect(win, c, rect) pygame.draw.rect(win, GRAY, rect, 5) txt = font.render(ch, True, GREEN) offset = (0.5 - len(ch)/10)*SIZE xy = (j*SIZE+offset, (i+0.3)*SIZE) win.blit(txt, xy)
主循环
最后,实现游戏的主循环如下
def gui(): pygame.init() win = pygame.display.set_mode( (4 * SIZE, 4 * SIZE)) pygame.display.set_caption("迷宫游戏") font.init() f = font.Font('C:\\WINDOWS\\Fonts\\ARLRDBD.TTF', 32) running = True mat = [[0]*4 for _ in range(4)] addNew(mat) while running: win.fill(WHITE) for evt in pygame.event.get(): if evt.type == pygame.QUIT: return if evt.type == pygame.KEYDOWN and evt.key in KEY_DCT: newMat = updateMat(mat, evt.key) if newMat!=mat: mat = newMat running = addNew(mat) draw(win, f, mat) # 判断玩家是否到达出口 if max([max(x) for x in mat])==2048: print("恭喜通关") running = False if min([min(x) for x in mat])>0: print("游戏失败") running = False pygame.display.update()
游戏效果如下
以上就是基于python做一个2048小游戏的详细内容,更多关于python 2048小游戏的资料请关注脚本之家其它相关文章!