01_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)# 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])field[firstIndex][secondIndex] = valuebreakdef game():random_create()random_create()print(field)for row in field:draw_sep()draw_one_row(row)draw_sep()if __name__ == '__main__':game()

02_判断棋盘是否可以向左、右移动

# 判断棋盘是否可以向左移动?
#  1). 只要棋盘的任意一行可以向左移动, 就返回True;
#          目标: 如何判断棋盘的一行是否可以向左移动?
#  2). 只要这一行的任意两个元素可以向左移动, 则返回True;
#           目标: 如何两个元素可以向左移动?
#           #  - 如果第一个数值为0, 第二个数值不为0, 则说明可以向左移动;
#           #  - 如果第一个数值不为0, 第二个数值与第一个元素相等, 则说明可以向左移动;
判断是否能向左移动:
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("测试用例完成.....")

判断是否能向右移动:
def invert(field):"""矩阵的反转"""return  [row[::-1] for row in field]def is_move_right(field):# 对棋盘的每一行元素进行反转;invertField = invert(field)return  is_move_left(invertField)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, "棋盘向右移动失败"except AssertionError as e:print(e)else:print("测试用例完成.....")

03_判断棋盘是否可以向上、下移动

判断是否能向上移动:
def transpose(field):"""实现矩阵的转置"""# zip: 实现# *field对列表进行解包;return  [move_row_left(row) for row in field]def is_move_up(field):# 对棋盘的每一行元素进行转置;transposeField = transpose(field)return  is_move_left( transposeField)if __name__ == "__main__":try:assert is_move_up([[0, 2, 0, 0],[0, 2, 0, 0],[0, 4, 0, 0],[0, 4, 0, 0]]) == True, "棋盘向上移动失败"except AssertionError as e:print(e)else:print("测试用例完成.....")

判断是否能向下移动:
def is_move_down(field):# 判断能否向下移动, 也就是对于元素进行转置, 判断转置后的棋盘能否向右移动;# 对棋盘的每一行元素进行反转;transposeField = transpose(field)return is_move_right(transposeField)if __name__ == "__main__":try:assert is_move_down([[0, 2, 0, 0],[0, 2, 0, 0],[0, 4, 0, 0],[0, 4, 0, 0]]) == True, "棋盘向下移动失败"except AssertionError as e:print(e)else:print("测试用例完成.....")

04_实现上下左右移动

# 棋盘向左移动?
#  1). 只要棋盘的每一行可以向左移动, e;
#          目标: 如何让棋盘的每一行向左移动?
#           [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# 1). 先把这一行的非0 数字向前放, 0向后放;   ==== [2, 2, 2, 2]
def tight(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(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# 向左移动
def move_row_left(row):return tight(merge(tight(row)))
def move_left(field):return  [move_row_left(row) for row in field]# 向右移动
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(move_right([[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [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_up([[0, 0, 2, 2], [0, 2, 4, 4], [0, 2, 0, 0], [2, 2, 0, 4]]))print(move_down([[0, 0, 2, 2], [0, 2, 4, 4], [0, 2, 0, 0], [2, 2, 0, 4]]))

05_游戏结束条件

# 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):"""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  Falsereturn  max(chain(*field)) >= 2048
print(is_win(field))

# 2. 何时game over?(当用户在任何方向都不能移动时, 则代表游戏结束, 用户失败)
# 只要有任意一个方向可以移动, 那就没有结束
def is_over(field):return  not any([is_move_left(field),is_move_right(field),is_move_up(field),is_move_down(field) ])field = [[2, 4, 2, 4], [4, 2, 4, 2], [2, 4, 2, 4], [4, 2, 4, 2]]
print(is_over(field))

06_2048完整代码

import curses
import random
from itertools import chainclass GameField(object):def __init__(self, width=4, height=4, win_score=2048):self.width = widthself.height = heightself.score = 0  # 当前得分self.highscore = 0  # 最高分self.win_score = win_score# 存储判断各个方向是否可移动的函数?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(self.height)] for i in range(self.width)]self.random_create()self.random_create()# 开始游戏时, 棋盘数据会随机生成2或者4,def random_create(self):# field[0][2] = 2while True:firstIndex = random.choice(range(self.height))secondIndex = random.choice(range(self.width))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("+-----" * self.width + '+' + '\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()stdstr.addstr(''.center(42, "*")+'\n')stdstr.addstr('2048游戏'.center(40, '*')+'\n')stdstr.addstr(''.center(42, '*')+'\n')# 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")def is_win(self):# return max(chain(*self.field)) >= 2048return max(chain(*self.field)) >= self.win_scoredef 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)])def is_row_left(self, 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(self.width-1)])def invert(self, field):"""矩阵的反转"""return [row[::-1] for row in field]def transpose(self, field):"""实现矩阵的转置"""# zip: 实现# *field对列表进行解包;return [ list(row) for row in zip(*field)]def is_move_left(self, field):# 只要棋盘的任意一行可以向左移动, 就返回True;return any([self.is_row_left(row) for row in field])def is_move_right(self, field):# 对棋盘的每一行元素进行反转;invertField = self.invert(field)return  self.is_move_left(invertField)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)# 1). 先把这一行的非0 数字向前放, 0向后放;   ==== [2, 2, 2, 2]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(self.width-1):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):# 1). 判断这个方向是否可以移动?# 2). 执行移动的操作# 3). 再随机生成一个2或者4# 确保是上下左右的按键if direction in self.moves:# 1).判断这个方向是否可以移动?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()if action == curses.KEY_UP:return 'Up'if action == curses.KEY_DOWN:return 'Down'if action == curses.KEY_LEFT:# stdstr.addstr("left")return 'Left'if action == curses.KEY_RIGHT:# stdstr.addstr("right")return 'Right'# 获取字母r的ASCII码if action == ord('r'):# stdstr.addstr("重新开始")return 'Restart'if action == ord('e'):# stdstr.addstr("退  出")return 'Exit'def main(stdstr):game_field = GameField(width=4, height=4, win_score=8)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 game_field.move(action):# move函数if game_field.is_win():return 'Win'if game_field.is_gameover():return 'Gameover'return 'Game'def not_game():action = get_user_action(stdstr)if action == 'Restart':return 'Init'if action == 'Exit':return 'Exit'state = 'Init'state_dict = {'Init': init,'Game': game,'Win':not_game,'Gameover':not_game,'Exit': exit}while True:state = state_dict[state]()# if state == 'Init':#     # 通过初始化函数, 进入游戏状态;#     state = init()# if state == 'Game':#     # 执行game函数, 判断用户的操作;#     # 1). 继续游戏; (upo, down, left, right)#     # 2). 重新开始;(R)#     # 3). 退出;(Q)##     state = game()## if state == 'Win':#     # 没有进行游戏, 只有两种状态;#     # 1). 重新开始;(R)#     # 2). 退出;(Q)#     state = not_game()# if state == 'Gameover':#     state = not_game()# if state == 'Exit':#     exit()curses.wrapper(main)
# 注意:pycharm不能接收键盘输入,必须要用脚本运行

python(2048)相关推荐

  1. python 2048源码_一个python的2048简单实现

    一个python的2048简单实现 2018-11-28 # -*- coding: utf8 -*- import random data = [[0, 0, 0, 0], [0, 0, 0, 0] ...

  2. python 2048游戏的设计_Python练习:100行代码实现一个简易的2048游戏

    一.任务目标 1.一个在命令行下的2048游戏 2.主要实现功能:判断游戏是否结束:在随机空白位置生成新的数字:上下左右四个方向上进行平移数字并将能合并的数字进行合并:接收键盘输入:将数字阵列显示到命 ...

  3. python - 2048小游戏

    我们先玩一下2048游戏,看都有哪些特点需要完成 完成效果图: 现在开始编写游戏2048: 1.首先,画出棋盘 import random def draw_sep():print("+-- ...

  4. python—2048小游戏

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

  5. python 2048源码,python3+pygame实现的2048,非常完整的代码

    前几天写了一个2048程序,是基于python3+pygame实现的,对于初学python的同学来说应该是很好的练手项目,现在将源码分享给大家,添加了清晰的注释,相信大家能看的很明白 运行效果如下: ...

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

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

  7. 20行python代码的入门级小游戏-200行Python代码实现的2048小游戏

    2048这个小游戏大家都不陌生,应该都玩过,之前已经在网上见过各个版本的2048实现了,有JAVA.HTML5等,今天我就给大家来一个我自己在 实验楼 学到的python版2048.所有代码加起来才2 ...

  8. Python 《Python 实现 2048 游戏》实验报告

    74340da14d79fae0a21de03d44699f80b6c624f3.jpg 2048 游戏 wiki:<2048>是一款单人在线和移动端游戏,由19岁的意大利人 Gabrie ...

  9. python200行代码_200行Python代码实现2048

    200行Python代码实现2048 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面 ...

最新文章

  1. Cmake 实例学习 一
  2. 刻意练习:Python基础 -- Task06. 字典与集合
  3. Linux机器建立密钥信任
  4. 友盟统计-页面访问路径
  5. 阿里重磅发布大规模图神经网络平台AliGraph,架构算法解读
  6. php语言难点,PHP知识难点TOP3,挑战一下你
  7. [渝粤教育] 西北工业大学 博弈论基础 参考 资料
  8. 2021年的电商,要怎么做,才能赚钱呢?
  9. mysql事务高级_mysql高级 标量 与事务
  10. JAVA之列表集合ArrayList
  11. 通过银行卡的Bin号来获取银行名称
  12. jdbc跨库查询 mysql_JDBC如何实现跨数据库的查询
  13. 无线网卡 VS 无线上网卡
  14. 收集N个超实用的 JS 片段( ES6+ 编写),你和大神只差这个宝典
  15. 人到底是为了什么活着?
  16. QModel-BIM-Revit模型轻量化产品介绍
  17. 上海联通第一家冰激凌无限店正式开业,拥抱新零售时代!
  18. 创建文件夹 java_java文件操作 之 创建文件夹路径和新文件
  19. 微信小程序、苹果手机(ios)时间格式显示NAN.....(已解决)
  20. Kanzi: kanzi 学习:kanzi触发器参考

热门文章

  1. 【Gem5】有关gem5模拟器的资料导航
  2. APK Image Extractor(安卓APK图像提取) v2.0
  3. Turtle图形绘制(绘制奥运五环)
  4. python数学圆周率_Python编程超简单方法算圆周率
  5. 宽带换了新的账号怎么连接服务器地址,宽带换了路由器设置步骤图解
  6. 程序员的开发工具:Java语言开发人员常用软件
  7. 快速可靠网络传输协议 KCP
  8. Lambda表达式-常见的函数式接口
  9. iSlide(PPT插件)
  10. winform高效导出Excel带格式设置