我们先玩一下2048游戏,看都有哪些特点需要完成

完成效果图:

现在开始编写游戏2048:
1.首先,画出棋盘

import random
def draw_sep():print("+-----" * 4 + '+')# 2. 画每一行的格子
def draw_one_row(row):  # [0, 2, 0, 0]   |    |  2  |    |    |print("".join([ '|  %d  '%(item) if item != 0 else '|     ' for item in row ]) + '|')# draw_one_row([0, 2, 0, 0])# 3. 创建棋盘的数据, 默认情况下时4*4, 数值全为0;
field = [[0 for j in range(4)] for i in range(4)]
# print(field)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]# 4. 开始游戏时, 棋盘数据会随机生成2或者4,
def random_create():# field[0][2] = 2while True:firstIndex = random.choice(range(4))secondIndex = random.choice(range(4))# 随机生成索引值if field[firstIndex][secondIndex] == 0:value = random.choice([2, 4, 2, 2, 2]) # 让一开始游戏生成2的概率大field[firstIndex][secondIndex] = valuebreakdef game():random_create()random_create()# 随机生成两个数字2或4print(field)# 打印棋盘for row in field:draw_sep()draw_one_row(row)draw_sep()if __name__ == '__main__':game()

输出:

第一行列表就是field的内容

2.判断棋盘是否可以向左移动
判断棋盘是否可以向左移动?
1). 只要棋盘的任意一行可以向左移动, 就返回True;
目标: 如何判断棋盘的一行是否可以向左移动?
2). 只要这一行的任意两个元素可以向左移动, 则返回True;
目标: 如何两个元素可以向左移动?
# - 如果第一个数值为0, 第二个数值不为0, 则说明可以向左移动;
# - 如果第一个数值不为0, 第二个数值与第一个元素相等, 则说明可以向左移动;

首先,可以在python console,熟悉or any and all功能:

 True or False or True
输出True
any([True, False, True])
输出True
True and False and True
输出False
all([True, False, True])
输出False

 def is_row_left(row):  # [0, 2,2,0]
# 任意两个元素可以向左移动?
def is_change(index):  # index时索引值, [0,1,2,3]# - 如果第一个数值为0, 第二个数值不为0, 则说明可以向左移动;if row[index] == 0 and row[index + 1] != 0:return True# - 如果第一个数值不为0, 第二个数值与第一个元素相等, 则说明可以向左移动;if row[index] != 0 and row[index + 1] == row[index]:return Truereturn False
# 只要这一行的任意两个元素可以向左移动, 则返回True;
return any([is_change(index) for index in range(3)])def is_move_left(field):# 只要棋盘的任意一行可以向左移动, 就返回True;return any([is_row_left(row) for row in field])

测试这段程序:

if __name__ == "__main__":try:assert is_move_left([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 4]]) == True, "棋盘向左移动失败"assert is_row_left([2, 2, 2, 2]) == True, 'Error'assert is_row_left([2, 4, 2, 4]) == False, 'Error'except AssertionError as e:print(e)else:print("测试用例完成.....")

输出:

测试用例完成.....
  1. 棋盘是否可以向左完成之后,可以延伸到判断棋盘是否可以向右,向下,向上。
    可以画一个矩阵想一下:
    是否向右:翻转以后是否可以向左移动
    是否向上:转置->向左
    是否向下:转置->向右

我们先来实现翻转和转置功能:

def invert(field):"""矩阵反转"""return [row[::-1] for row in field]

测试:

if __name__ == '__main__':print(invert([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 4]]))

def transpose(field):"""实现矩阵的转置"""# zip: 实现转置# *field对列表进行解包;return  list(zip(*field))

测试:

if __name__ == '__main__':print(transpose([[0, 0, 1, 0], [0, 2, 0, 1], [0, 0, 0, 1], [0, 0, 0, 4]]))

输出:

zip的功能,就是实现转置,但是要先把列表解包。zip转置后,需要转换为列表形式输出,否则输出是一个对象。

转置和翻转会了接下来就来完成判断棋盘是否可以向右、向下、向上。

def is_move_right(field):# 对棋盘的每一行元素进行反转;invertField = invert(field)return  is_move_left(invertField)
def is_move_up(field):# 对棋盘的每一行元素进行转置;transposeField = transpose(field)return  is_move_left( transposeField)
def is_move_down(field):# 判断能否向下移动, 也就是对于元素进行转置, 判断转置后的棋盘能否向右移动;# 对棋盘的每一行元素进行反转;transposeField = transpose(field)return is_move_right(transposeField)

测试:

if __name__ == '__main__':try:assert  is_move_right([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 4]]) == True, 'Error'assert is_move_up([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 4]]) == True, 'Error'assert is_move_down([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 4]]) == True, 'Error'except AssertionError as e:print(e)else:print('测试完成')

输出:

测试完成

4.判断能不能移动后,实现棋盘的上下左右移动。

首先,棋盘如何向左移动?
1). 只要棋盘的每一行可以向左移动;
目标: 如何让棋盘的每一行向左移动?
[2, 2, 2, 2] === [4, 4, 0 ,0 ]
讨论:
1). 先把这一行的非0 数字向前放, 0向后放; ==== [2, 2, 2, 2]
2). 依次循环判断两个数是否相等, 如果相等, 第一个*2, 第二个数为0; [4, 0, 4, 0]
3).先把这一行的非0数字向前放, 0向后放;[4, 4, 0 ,0 ]

score = 0 #初始值为0
# 1). 排序。先把这一行的非0 数字向前放, 0向后放;
def tight(row):  return sorted(row, key= lambda x: 1 if x == 0 else 0)# 0记为1,非0记为0,sorted是有小往大排序,所以会把记为0的数往前排# 2). 依次循环判断两个数是否相等, 如果相等, 第一个*2, 第二个数为0;  [4, 0, 4, 0]
def merge(row):for index in range(3):if row[index] == row[index + 1]:row[index] *= 2row[index + 1] = 0# 如果合并完成, 分数增加row[index]global scorescore += row[index]return row
# 每一行向左移动,左滑一次,只合并一次,但是注意合并完顺序需要重新排列一次,非0数在左边    # 一行向左移
def move_row_left(row):return tight(merge(tight(row)))
# 棋盘向左移动(就是每一行向左移动)
def move_left(field):return  [move_row_left(row) for row in field]

测试:

if __name__ == '__main__':print(move_left([[0, 0, 1, 0], [2, 2, 2, 2], [0, 0, 0, 1], [0, 0, 0, 4]]))

输出:

[[1, 0, 0, 0], [4, 4, 0, 0], [1, 0, 0, 0], [4, 0, 0, 0]]

5.实现棋盘的向上向下向右移动
思想和前面判断是否可以向上向下向右移动一致。

def move_right(field):
#向右:翻转后向左移动field = invert(field)    return invert(move_left(field)) # 最后记得翻转回来,恢复矩阵。 def move_up(field):field = transpose(field)return transpose(move_left(field))def move_down(field):field = transpose(field)return transpose(move_right(field))#测试:
if __name__ == '__main__':# print(transpose([[0, 0, 1, 0], [0, 2, 0, 1], [0, 0, 0, 1], [0, 0, 0, 4]]))print(move_left([[0, 0, 1, 0], [2, 2, 2, 2], [0, 0, 0, 1], [0, 0, 0, 4]]))print(move_right([[0, 0, 2, 2], [0, 2, 4, 4], [0, 2, 0, 0], [2, 2, 0, 4]]))print(move_up([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 4]]))print(move_down([[0, 0, 2, 2], [0, 2, 4, 4], [0, 2, 0, 0], [2, 2, 0, 4]]))

输出:

[[1, 0, 0, 0], [4, 4, 0, 0], [1, 0, 0, 0], [4, 0, 0, 0]]
[[0, 0, 0, 4], [0, 0, 2, 8], [0, 0, 0, 2], [0, 0, 4, 4]]
[(0, 2, 0, 4), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)]
[(0, 0, 0, 0), (0, 0, 0, 0), (0, 2, 2, 2), (2, 4, 4, 8)]

6.游戏结束条件

# 1. 何时用户游戏胜利?(当棋盘中出现num=2048时, 则代表用户胜利)
from itertools import  chain
field = [[2048, 0, 0, 0], [0, 0, 0, 0], [0, 0, 4, 0], [0, 0, 0, 4]]def is_win(field):"""chain的用法:list(chain(*[[2048, 0, 0, 0], [0, 0, 0, 0], [0, 0, 4, 0], [0, 0, 0, 4]]))[2048, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 4]:param field::return:"""# 遍历所有的元素, 有一个元素大于等于2048, 即游戏胜利!# for row in field:#     for item in row:#         if item >= 2048:#             return  True# else:#     return  False# 用chain可以简化步骤return  max(chain(*field) >= 2048)# 2. 何时game over?(当用户在任何方向都不能移动时, 则代表游戏结束, 用户失败)
# 只要有任意一个方向可以移动, 那就没有结束
def is_over():return  not any([is_move_left(field),is_move_right(field),is_move_up(field),is_move_down(field) ])

7.游戏雏形
curses使用方法
因为要在终端terminal操作,所以要使用stdstr.

游戏雏形如下,把之前的操作放在 GameField类里。
注意几点:
1这个类有4个初始值。长宽4*4、当前得分和最高得分都为0
2 需要新定义一个reset重置棋盘的函数
3 画棋盘时用stdstr.addstr()

import curses
import random
from itertools import chainclass GameField(object):def __init__(self, width=4, height=4):self.width = widthself.height = heightself.score = 0      # 当前得分self.highscore = 0   # 最高分# 重置棋盘, 重新开始游戏时, 执行的操作;def reset(self):# 2). 是否要更新最高分, 当前分数重置为0;if self.score > self.highscore:self.highscore = self.scoreself.score = 0# 3). 创建棋盘的数据, 默认情况下时4*4, 数值全为0;self.field = [[0 for j in range(4)] for i in range(4)]self.random_create()self.random_create()# 开始游戏时, 棋盘数据会随机生成2或者4,def random_create(self):# field[0][2] = 2while True:firstIndex = random.choice(range(4))secondIndex = random.choice(range(4))if self.field[firstIndex][secondIndex] == 0:value = random.choice([2, 4, 2, 2, 2])self.field[firstIndex][secondIndex] = valuebreak# 画棋盘def draw(self, stdstr):# stdstr是在屏幕上输出需要def draw_sep():# 相当于print("+-----" * 4 + '+')stdstr.addstr("+-----" * 4 + '+' + '\n')# 2. 画每一行的格子def draw_one_row(row):  # [0, 2, 0, 0]   |    |  2  |    |    |stdstr.addstr("".join(['|  %d  ' % (item) if item != 0 else '|     ' for item in row]) + '|\n')# 3. 绘制棋盘for row in self.field:draw_sep()draw_one_row(row)draw_sep()# 2048游戏上始终有记录当前分数,最高分数、按键。胜利会显示胜利,失败会显示游戏结束。stdstr.addstr("\n当前分数: %s" %(self.score))stdstr.addstr("\n当前最高分数: %s" %(self.highscore))stdstr.addstr(" \n游戏帮助: 上下左右键  (R)estart Q(uit) ")if self.is_win():stdstr.addstr("\n游戏胜利\n")if self.is_gameover():stdstr.addstr("游戏失败\n")def is_win(self):return max(chain(*self.field)) >= 2048def is_gameover(self):return not any([self.is_move_left(self.field),self.is_move_right(self.field),self.is_move_up(self.field),self.is_move_down(self.field) ])@staticmethoddef is_row_left(row):  # [0, 2,2,0]# 任意两个元素可以向左移动?def is_change(index):  # index时索引值, [0,1,2,3]# - 如果第一个数值为0, 第二个数值不为0, 则说明可以向左移动;if row[index] == 0 and row[index + 1] != 0:return True# - 如果第一个数值不为0, 第二个数值与第一个元素相等, 则说明可以向左移动;if row[index] != 0 and row[index + 1] == row[index]:return Truereturn False# 只要这一行的任意两个元素可以向左移动, 则返回True;return any([is_change(index) for index in range(3)])def is_move_left(self, field):# 只要棋盘的任意一行可以向左移动, 就返回True;return any([self.is_row_left(row) for row in  field])def invert(self, field):"""矩阵的反转"""return [row[::-1] for row in field]def is_move_right(self, field):# 对棋盘的每一行元素进行反转;invertField = self.invert(field)return self.is_move_left(invertField)def transpose(self, field):"""实现矩阵的转置"""# zip: 实现# *field对列表进行解包;return list(zip(*field))def is_move_up(self, field):# 对棋盘的每一行元素进行转置;transposeField = self.transpose(field)return self.is_move_left(transposeField)def is_move_down(self, field):# 判断能否向下移动, 也就是对于元素进行转置, 判断转置后的棋盘能否向右移动;# 对棋盘的每一行元素进行反转;transposeField = self.transpose(field)return self.is_move_right(transposeField)测试:
def main(stdstr):game_field = GameField()game_field.reset()game_field.draw(stdstr)action = stdstr.getch() #从键盘获取输入curses.wrapper(main) #看连接里有详细解释


在终端运行这个.py文件,可以得到如下的效果,棋盘雏形已经画好了。此时我们按上下左右键没有反应,需要进一步完善。
(curses需要在放在anaconda虚拟环境里运行才有,虚拟环境anaconda我在下次博客中详细写了,这里就不介绍了)

8.2048完整代码

import curses
import random
from itertools import chain# import cursesKey 如果没有安装anaconda,不能用curses,可以自己做一个文件例如curseKeyclass GameField(object):def __init__(self, width=4, height=4):self.width = widthself.height = heightself.score = 0  # 当前得分self.highscore = 0  # 最高分# 存储判断各个方向是否可移动的函数self.moves = {}self.moves['left'] = self.is_move_leftself.moves['right'] = self.is_move_rightself.moves['up'] = self.is_move_upself.moves['down'] = self.is_move_down# 存储移动函数self.movesDict = {}self.movesDict['left'] = self.move_leftself.movesDict['right'] = self.move_rightself.movesDict['up'] = self.move_upself.movesDict['down'] = self.move_down# 重置棋盘, 重新开始游戏时, 执行的操作;def reset(self):# 2). 是否要更新最高分, 当前分数为0;if self.score > self.highscore:self.highscore = self.scoreself.score = 0# 3). 创建棋盘的数据, 默认情况下时4*4, 数值全为0;self.field = [[0 for j in range(4)]for i in range(4)]self.random_create()self.random_create()# 开始游戏时, 棋盘数据会随机生成2或者4,def random_create(self):# field[0][2] = 2while True:firstIndex = random.choice(range(4))secondIndex = random.choice(range(4))with open('hello','w') as f:f.write(str(self.field))if self.field[firstIndex][secondIndex] == 0:value = random.choice([2, 4, 2, 2, 2])self.field[firstIndex][secondIndex] = valuebreak# 画棋盘def draw(self, stdstr):def draw_sep():# print("+-----" * 4 + '+')stdstr.addstr('+-----' * 4 + '+' + '\n')# 2. 画每一行的格子def draw_one_row(row):  # [0, 2, 0, 0]   |    |  2  |    |    |stdstr.addstr("".join(['|  %d  ' % (item) if item != 0 else '|     ' for item in row]) + '|'+'\n')stdstr.clear()# 3. 绘制棋盘for row in self.field:draw_sep()draw_one_row(row)draw_sep()stdstr.addstr('\n当前分数: %s' % (self.score) )stdstr.addstr('\n当前最高分数: %s' % (self.highscore) )stdstr.addstr('\n游戏帮助: 上下左右键  (R)estart E(xit)')if self.is_win():stdstr.addstr('\n游戏胜利\n')if self.is_gameover():stdstr.addstr('\n游戏失败\n')def is_win(self):return max(chain(*self.field)) >= 8def is_gameover(self):return not any([self.is_move_left(self.field),self.is_move_right(self.field),self.is_move_up(self.field),self.is_move_down(self.field)])@staticmethoddef is_row_left(row):  # [0, 2,2,0]# 任意两个元素可以向左移动?def is_change(index):  # index时索引值, [0,1,2,3]# - 如果第一个数值为0, 第二个数值不为0, 则说明可以向左移动;if row[index] == 0 and row[index + 1] != 0:return True# - 如果第一个数值不为0, 第二个数值与第一个元素相等, 则说明可以向左移动;if row[index] != 0 and row[index + 1] == row[index]:return Truereturn False# 只要这一行的任意两个元素可以向左移动, 则返回True;return any([is_change(index) for index in range(3)])def is_move_left(self, field):# 只要棋盘的任意一行可以向左移动, 就返回True;return any([self.is_row_left(row) for row in field])def invert(self, field):"""矩阵的反转"""return [row[::-1] for row in field]def is_move_right(self, field):# 对棋盘的每一行元素进行反转;invertField = self.invert(field)return self.is_move_left(invertField)def transpose(self, field):"""实现矩阵的转置"""# zip: 实现# *field对列表进行解包;return [list(row) for row in zip(*field)]def is_move_up(self, field):# 对棋盘的每一行元素进行转置;transposeField = self.transpose(field)return self.is_move_left(transposeField)def is_move_down(self, field):# 判断能否向下移动, 也就是对于元素进行转置, 判断转置后的棋盘能否向右移动;# 对棋盘的每一行元素进行反转;transposeField = self.transpose(field)return self.is_move_right(transposeField)# 复制的def tight(self, row):  # [2,0,2,0]return sorted(row, key=lambda x: 1 if x == 0 else 0)# 2). 依次循环判断两个数是否相等, 如果相等, 第一个*2, 第二个数为0;  【4, 0, 4, 0】def merge(self, row):for index in range(3):if row[index] == row[index + 1]:row[index] *= 2row[index + 1] = 0# 如果合并完成, 分数增加row[index]self.score += row[index]return rowdef move_row_left(self, row):return self.tight(self.merge(self.tight(row)))def move_left(self, field):return [self.move_row_left(row) for row in field]def move_right(self, field):field = self.invert(field)return self.invert(self.move_left(field))def move_up(self, field):field = self.transpose(field)return self.transpose(self.move_left(field))def move_down(self, field):field = self.transpose(field)return self.transpose(self.move_right(field))def move(self,direction):if direction in self.moves:if self.moves[direction](self.field):self.field = self.movesDict[direction](self.field)self.random_create()else:return Falsedef get_user_action(stdstr):action = stdstr.getch()stdstr.addstr(str(action))if action == curses.KEY_UP:# stdstr.addstr('up')return 'up'if action == curses.KEY_DOWN:# stdstr.addstr('down')return 'down'if action == curses.KEY_LEFT:# stdstr.addstr('left')return 'left'if action == curses.KEY_RIGHT:# stdstr.addstr('right')return 'right'if action == ord('r'):return 'restart'# stdstr.addstr('restart')if action == ord('e'):return 'exit'# stdstr.addstr('quit')def main(stdstr):game_field = GameField()# game_field.reset()# game_field.draw(stdstr)# action = stdstr.getch()# while True:#     get_user_action(stdstr)# curses.wrapper(main)def init():game_field.reset()game_field.draw(stdstr)return 'Game'def game():game_field.draw(stdstr)action = get_user_action(stdstr)if action == 'restart':return 'Init'if action == 'exit':return 'Exit'# if action =='up':#     game_field.move_up()# if action =='down':#     game_field.move_down()# if action =='left':#     game_field.move_left()# if action =='right':#     game_field.move_right()if game_field.move(action):if game_field.move(action):passif game_field.is_win():return 'Win'if game_field.is_gameover():return 'Gameover'return 'Game'return 'Game'def not_game():action = get_user_action(stdstr)if action == 'restart':return 'Init'if action == 'exit':return 'Exit'state = 'Init'# if state =='Init':#     state = init()#     stdstr.addstr(state)# if state =='Game':#     game()# if state =='Win':#     not_game()# if state =='Exit':#     exit()state_dict = {'Init': init,'Game': game,'Win': not_game,'Gameover': not_game,'Exit': exit}while True:state = state_dict[state]()curses.wrapper(main)

进入curses里,文件不完整,没有key值代表的数字等,但是如果你是虚拟环境,curses是完整的

没有curses的,不想新建虚拟环境的,可以新建一个文件cursesKey.py导入,同理你在2048这个代码里调用时也记得要修改上面curses.xxx改为cursesKey.xxx。cursesKey.py内容如下,否则按不了上下左右:

ALL_MOUSE_EVENTS = 134217727A_ALTCHARSET = 4194304
A_ATTRIBUTES = -256
A_BLINK = 524288
A_BOLD = 2097152
A_CHARTEXT = 255
A_COLOR = 65280
A_DIM = 1048576
A_HORIZONTAL = 33554432
A_INVIS = 8388608
A_LEFT = 67108864
A_LOW = 134217728
A_NORMAL = 0
A_PROTECT = 16777216
A_REVERSE = 262144
A_RIGHT = 268435456
A_STANDOUT = 65536
A_TOP = 536870912
A_UNDERLINE = 131072
A_VERTICAL = 1073741824BUTTON1_CLICKED = 4BUTTON1_DOUBLE_CLICKED = 8BUTTON1_PRESSED = 2
BUTTON1_RELEASED = 1BUTTON1_TRIPLE_CLICKED = 16BUTTON2_CLICKED = 256BUTTON2_DOUBLE_CLICKED = 512BUTTON2_PRESSED = 128
BUTTON2_RELEASED = 64BUTTON2_TRIPLE_CLICKED = 1024BUTTON3_CLICKED = 16384BUTTON3_DOUBLE_CLICKED = 32768BUTTON3_PRESSED = 8192
BUTTON3_RELEASED = 4096BUTTON3_TRIPLE_CLICKED = 65536BUTTON4_CLICKED = 1048576BUTTON4_DOUBLE_CLICKED = 2097152BUTTON4_PRESSED = 524288
BUTTON4_RELEASED = 262144BUTTON4_TRIPLE_CLICKED = 4194304BUTTON_ALT = 67108864
BUTTON_CTRL = 16777216
BUTTON_SHIFT = 33554432COLOR_BLACK = 0
COLOR_BLUE = 4
COLOR_CYAN = 6
COLOR_GREEN = 2
COLOR_MAGENTA = 5
COLOR_RED = 1
COLOR_WHITE = 7
COLOR_YELLOW = 3ERR = -1KEY_A1 = 348
KEY_A3 = 349
KEY_B2 = 350
KEY_BACKSPACE = 263
KEY_BEG = 354
KEY_BREAK = 257
KEY_BTAB = 353
KEY_C1 = 351
KEY_C3 = 352
KEY_CANCEL = 355
KEY_CATAB = 342
KEY_CLEAR = 333
KEY_CLOSE = 356
KEY_COMMAND = 357
KEY_COPY = 358
KEY_CREATE = 359
KEY_CTAB = 341
KEY_DC = 330
KEY_DL = 328
KEY_DOWN = 258
KEY_EIC = 332
KEY_END = 360
KEY_ENTER = 343
KEY_EOL = 335
KEY_EOS = 334
KEY_EXIT = 361
KEY_F0 = 264
KEY_F1 = 265
KEY_F10 = 274
KEY_F11 = 275
KEY_F12 = 276
KEY_F13 = 277
KEY_F14 = 278
KEY_F15 = 279
KEY_F16 = 280
KEY_F17 = 281
KEY_F18 = 282
KEY_F19 = 283
KEY_F2 = 266
KEY_F20 = 284
KEY_F21 = 285
KEY_F22 = 286
KEY_F23 = 287
KEY_F24 = 288
KEY_F25 = 289
KEY_F26 = 290
KEY_F27 = 291
KEY_F28 = 292
KEY_F29 = 293
KEY_F3 = 267
KEY_F30 = 294
KEY_F31 = 295
KEY_F32 = 296
KEY_F33 = 297
KEY_F34 = 298
KEY_F35 = 299
KEY_F36 = 300
KEY_F37 = 301
KEY_F38 = 302
KEY_F39 = 303
KEY_F4 = 268
KEY_F40 = 304
KEY_F41 = 305
KEY_F42 = 306
KEY_F43 = 307
KEY_F44 = 308
KEY_F45 = 309
KEY_F46 = 310
KEY_F47 = 311
KEY_F48 = 312
KEY_F49 = 313
KEY_F5 = 269
KEY_F50 = 314
KEY_F51 = 315
KEY_F52 = 316
KEY_F53 = 317
KEY_F54 = 318
KEY_F55 = 319
KEY_F56 = 320
KEY_F57 = 321
KEY_F58 = 322
KEY_F59 = 323
KEY_F6 = 270
KEY_F60 = 324
KEY_F61 = 325
KEY_F62 = 326
KEY_F63 = 327
KEY_F7 = 271
KEY_F8 = 272
KEY_F9 = 273
KEY_FIND = 362
KEY_HELP = 363
KEY_HOME = 262
KEY_IC = 331
KEY_IL = 329
KEY_LEFT = 260
KEY_LL = 347
KEY_MARK = 364
KEY_MAX = 511
KEY_MESSAGE = 365
KEY_MIN = 257
KEY_MOUSE = 409
KEY_MOVE = 366
KEY_NEXT = 367
KEY_NPAGE = 338
KEY_OPEN = 368
KEY_OPTIONS = 369
KEY_PPAGE = 339
KEY_PREVIOUS = 370
KEY_PRINT = 346
KEY_REDO = 371
KEY_REFERENCE = 372
KEY_REFRESH = 373
KEY_REPLACE = 374
KEY_RESET = 345
KEY_RESIZE = 410
KEY_RESTART = 375
KEY_RESUME = 376
KEY_RIGHT = 261
KEY_SAVE = 377
KEY_SBEG = 378
KEY_SCANCEL = 379
KEY_SCOMMAND = 380
KEY_SCOPY = 381
KEY_SCREATE = 382
KEY_SDC = 383
KEY_SDL = 384
KEY_SELECT = 385
KEY_SEND = 386
KEY_SEOL = 387
KEY_SEXIT = 388
KEY_SF = 336
KEY_SFIND = 389
KEY_SHELP = 390
KEY_SHOME = 391
KEY_SIC = 392
KEY_SLEFT = 393
KEY_SMESSAGE = 394
KEY_SMOVE = 395
KEY_SNEXT = 396
KEY_SOPTIONS = 397
KEY_SPREVIOUS = 398
KEY_SPRINT = 399
KEY_SR = 337
KEY_SREDO = 400
KEY_SREPLACE = 401
KEY_SRESET = 344
KEY_SRIGHT = 402
KEY_SRSUME = 403
KEY_SSAVE = 404
KEY_SSUSPEND = 405
KEY_STAB = 340
KEY_SUNDO = 406
KEY_SUSPEND = 407
KEY_UNDO = 408
KEY_UP = 259OK = 0REPORT_MOUSE_POSITION = 134217728version = '2.2'__version__ = '2.2'

python - 2048小游戏相关推荐

  1. python—2048小游戏

    def move_left(lists):"""将列表所有的0元素右移,非0元素左移:param lists: list:return: list_new"&q ...

  2. (Python)2048小游戏核心代码

    算法思想: 1.降维:将二维降为一维列表进行处理 2.去零:相邻相同合并 list_merge = None# 1 def zero_to_end():"""零元素移动到 ...

  3. python游戏代码五子棋_用20行Python代码实现2048小游戏,你会吗?

    前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...

  4. python秒表游戏代码_用20行Python代码实现2048小游戏,你会吗?

    前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...

  5. 我的名片能运行Linux和Python,还能玩2048小游戏,成本只要20元

    晓查 发自 凹非寺  量子位 报道 | 公众号 QbitAI 猜猜它是什么?印着姓名.职位和邮箱,看起来是个名片.可是右下角有芯片,看起来又像是个PCB电路板. 其实它是一台超迷你的ARM计算机,不仅 ...

  6. python里graphics的使用_使用graphics.py实现2048小游戏

    1.过年的时候在手机上下载了2048玩了几天,心血来潮决定用py写一个,刚开始的时候想用QT实现,发现依赖有点大.正好看到graphics.py是基于tkinter做的封装就拿来练手,并借用了CSDN ...

  7. Python学习—2048小游戏等4个小练习

    Python学习-2048小游戏等4个小练习 转载于:https://www.cnblogs.com/ChangAn223/p/10627777.html

  8. python小项目——2048小游戏(详解)

    2048游戏 原版游戏地址 第一部分 导入所需要的库 第二部分 确认游戏键位设置,并和对应的操作关联 第三部分 获取用户输入的值,并直到有效键位 第四部分 对矩阵的应用,减少代码量 第五部分 创建棋盘 ...

  9. Python实现2048小游戏

    2048小游戏也算是一款好玩的益智休闲小游戏,下面本博主用 python 语言将该游戏复现,感兴趣的小伙伴点击 关注 哦! 同时博主还用 java 语言复现了该游戏,可点击以下链接浏览博主的另一篇文章 ...

最新文章

  1. Python设计模式-装饰器模式
  2. 公众号推荐:Python入门、统计学、推荐系统、机器学习、深度学习、数据分析...
  3. 网站服务器被别人绑定域名了怎么办(nginx)?
  4. 12563 - Jin Ge Jin Qu hao
  5. MailMail正式发布!注册码免费发放活动开启!(已结束~~不要再回复咧~)
  6. CCF NOI1098 森林
  7. 欧拉工程第74题:Digit factorial chains
  8. 20届校招-携程笔试题-表达式解析
  9. ss导航java宝典_绅士宝典ss导航
  10. 二阶系统 matlab,线性二阶系统性能的MATLAB仿真.pdf
  11. Java实现在线打开word文档加盖印章/盖章/签名功能
  12. 数据分析-SQL练习
  13. PS制作搞笑印章 - 仿真印章 - 水印滤色
  14. Codeforces::GYM 102896M Miser
  15. linux系统安装windows字体
  16. 全球智慧能源解决方案服务商「雄韬股份」牵手企企通,谱写采购数字化变革之路
  17. php九宫格图片合成,php实现微信中的图片合并-九宫格图片
  18. POI实现 Excel插入图片
  19. 2023年AI十大展望:GPT-4领衔大模型变革,谷歌拉响警报,训练数据告急
  20. 高效深度学习:让模型更小、更快、更好!

热门文章

  1. 2021-06-29 Views and Quality Objectives of Software Construction 软件构造的多维度视图和质量目标
  2. QT QTextEdit 修改默认的行间距
  3. dialog对话框初始化 mfc_「弹出对话框」MFC系列 - 弹出一个模态对话框 - seo实验室...
  4. 推荐一个在线实现音乐可视化的网站
  5. SQL —— 查询最近一小时的数据
  6. 如何通过短视频打造自己的IP形象
  7. HPB普及:BOE完整流程、高性能选举
  8. vue 不同用户登录系统拥有不同查看菜单导航的权限
  9. 独立模式(Standone Mode)启动Spark
  10. bottle中文教程