作为python初学者,再学完基本语法后,看到网上多种版本的2048游戏,想起曾痴迷于此,必须实现一波。
该游戏主要可分为以下几个模块(基本思路来源于实验楼2048教程)。
#获取用户操作
get_user_action()
#重置棋盘
reset()
#判断操作是否可行
is_move_possible()
#移动数字
move()
#画棋盘
draw()
#是否结束
is_over()
#是否胜利
is_win()
#随机加数
spawn()
在每次移动时,实验楼采取了一种相当高效的方式。首先,定义一个矩阵逆转函数和一个矩阵转置函数。
#矩阵转置,field 为棋盘(矩阵)
def transpose(field):
return list(map(list,zip(*field)))
#矩阵逆转,每一行反序
def invert(field):
return [row[::-1] for row in field]</span>
这样,在写好是否可以进行向左移动的操作后,其他方向的操作就可以通过 tanspose 或invert 或组合进行实现。
def move_is_possible(self,direction):
def row_is_left_movable(row):
def change(i):
if row[i] == 0 and row[i + 1] != 0: # 可以移动
return True
if row[i] != 0 and row[i + 1] == row[i]: # 可以合并
return True
return False
return any(change(i) for i in range(len(row) - 1)) #存在一个 即返回true
check = {}
check['Left'] = lambda field: any(row_is_left_movable(row) for row in field) #只要有一行可以向左移动,则返回True
check['Right'] = lambda field: check['Left'](invert(field))
check['Up'] = lambda field: check['Left'](transpose(field))
check['Down'] = lambda field: check['Right'](transpose(field))
if direction in check:
return check[direction](self.field)
else:
return False
而在实际的移动操作中,对矩阵各元素有改动,则需要对转置(逆转)的矩阵再次转置(逆转),以保证操作的正确性。比如,
moves = {}
moves['Left'] = lambda field: [move_row_left(row) for row in field]
moves['Right'] = lambda field: invert(moves['Left'](invert(field)))
moves['Up'] = lambda field: transpose(moves['Left'](transpose(field)))
moves['Down'] = lambda field: transpose(moves['Right'](transpose(field))
在最后整合过程,用一个while循环进行。
game_field = GameField()
while True:
game_field.draw()
action = get_user_action()
if action == 'Restart':
game_field.reset()
if action == 'Exit':
break
flag = game_field.is_over()
game_field.move(action)
结果如图: