2048这个小游戏大家都不陌生,应该都玩过,之前已经在网上见过各个版本的2048实现了,有JAVA、HTML5等,今天我就给大家来一个我自己在 实验楼 学到的python版2048。所有代码加起来才200行,不用很麻烦很累就可以写一个 2048 游戏出来。

游戏的具体规则什么的就不多说了,自己亲自去玩一下就清楚了。

导入需要的包

    import cursesfrom random import randrange, choicefrom collections import defaultdict

游戏主逻辑

用户行为

用户在玩游戏的主要输入分为六种,"上,下,左,右,游戏重置,退出"用 actions 表示

actions = ['Up', 'Left', 'Down', 'Right', 'Restart', 'Exit']

分别用 W(上),A(左),S(下),D(右),R(重置),Q(退出),进行输入来操作游戏,这里考虑到大写锁定键锁定的情况:

letter_codes = [ord(ch) for ch in 'WASDRQwasdrq']

将输入与行为进行关联:

actions_dict = dict(zip(letter_codes, actions * 2))

用户输入处理

阻塞+循环,直到获得用户有效输入才返回对应行为:

def get_user_action(keyboard):    char = "N"while char not in actions_dict:    char = keyboard.getch()return actions_dict[char]

矩阵转置与矩阵逆转

这两个操作主要是用户在操作游戏之后对棋盘状态的变化以及修改,拥有这两个函数能够节省不少的代码量。

矩阵转置:

def transpose(field):return [list(row) for row in zip(*field)]

矩阵逆转(不是逆矩阵):

def invert(field):return [row[::-1] for row in field]

创建棋盘

初始化棋盘的参数,可以指定棋盘的高和宽以及游戏胜利条件,默认是最经典的 4x4~2048。

class GameField(object):
def __init__(self, height=4, width=4, win=2048):self.height = height       #高self.width = width         #宽self.win_value = 2048      #过关分数self.score = 0             #当前分数self.highscore = 0         #最高分self.reset()               #棋盘重置

棋盘操作

随机生成一个 2 或者 4

def spawn(self):new_element = 4 if randrange(100) > 89 else 2(i,j) = choice([(i,j) for i in range(self.width) for j in range(self.height) if self.field[i][j] == 0])self.field[i][j] = new_element

重置棋盘

def reset(self):if self.score > self.highscore:self.highscore = self.scoreself.score = 0self.field = [[0 for i in range(self.width)] for j in range(self.height)]self.spawn()self.spawn()

一行向左合并

(注:这一操作是在 move 内定义的,拆出来是为了方便阅读)

def move_row_left(row):def tighten(row): # 把零散的非零单元挤到一块new_row = [i for i in row if i != 0]new_row += [0 for i in range(len(row) - len(new_row))]return new_rowdef merge(row): # 对邻近元素进行合并pair = Falsenew_row = []for i in range(len(row)):if pair:new_row.append(2 * row[i])self.score += 2 * row[i]pair = Falseelse:if i + 1 < len(row) and row[i] == row[i + 1]:pair = Truenew_row.append(0)else:new_row.append(row[i])assert len(new_row) == len(row)return new_row#先挤到一块再合并再挤到一块return tighten(merge(tighten(row)))

棋盘走一步

通过对矩阵进行转置与逆转,可以直接从左移得到其余三个方向的移动操作

def move(self, direction):def move_row_left(row):#一行向左合并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)))if direction in moves:if self.move_is_possible(direction):self.field = moves[direction](self.field)self.spawn()return Trueelse:return False

判断输赢

def is_win(self):return any(any(i >= self.win_value for i in row) for row in self.field)def is_gameover(self):return not any(self.move_is_possible(move) for move in actions)

判断能否移动

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 Trueif row[i] != 0 and row[i + 1] == row[i]: # 可以合并return Truereturn Falsereturn any(change(i) for i in range(len(row) - 1))check = {}check['Left']  = lambda field: any(row_is_left_movable(row) for row in field)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

绘制游戏界面

(注:这一步是在棋盘类内定义的)

def draw(self, screen):help_string1 = '(W)Up (S)Down (A)Left (D)Right'help_string2 = '     (R)Restart (Q)Exit'gameover_string = '           GAME OVER'win_string = '          YOU WIN!'def cast(string):screen.addstr(string + '\n')#绘制水平分割线def draw_hor_separator():line = '+' + ('+------' * self.width + '+')[1:]separator = defaultdict(lambda: line)if not hasattr(draw_hor_separator, "counter"):draw_hor_separator.counter = 0cast(separator[draw_hor_separator.counter])draw_hor_separator.counter += 1def draw_row(row):cast(''.join('|{: ^5} '.format(num) if num > 0 else '|      ' for num in row) + '|')screen.clear()cast('SCORE: ' + str(self.score))if 0 != self.highscore:cast('HGHSCORE: ' + str(self.highscore))for row in self.field:draw_hor_separator()draw_row(row)draw_hor_separator()if self.is_win():cast(win_string)else:if self.is_gameover():cast(gameover_string)else:cast(help_string1)cast(help_string2)

完成主逻辑

完成以上工作后,我们就可以补完主逻辑了!

def main(stdscr):def init():#重置游戏棋盘game_field.reset()return 'Game'def not_game(state):#画出 GameOver 或者 Win 的界面game_field.draw(stdscr)#读取用户输入得到action,判断是重启游戏还是结束游戏action = get_user_action(stdscr)responses = defaultdict(lambda: state) #默认是当前状态,没有行为就会一直在当前界面循环responses['Restart'], responses['Exit'] = 'Init', 'Exit' #对应不同的行为转换到不同的状态return responses[action]def game():#画出当前棋盘状态game_field.draw(stdscr)#读取用户输入得到actionaction = get_user_action(stdscr)if action == 'Restart':return 'Init'if action == 'Exit':return 'Exit'if game_field.move(action): # move successfulif game_field.is_win():return 'Win'if game_field.is_gameover():return 'Gameover'return 'Game'state_actions = {'Init': init,'Win': lambda: not_game('Win'),'Gameover': lambda: not_game('Gameover'),'Game': game}curses.use_default_colors()game_field = GameField(win=32)state = 'Init'#状态机开始循环while state != 'Exit':state = state_actions[state]()

运行

填上最后一行代码:

curses.wrapper(main)

运行看看吧!

$ python 2048.py

详细代码参见:http://git.shiyanlou.com/littlemonkey/shiyanlou_cs368/src/master/2048.py

转载于:https://www.cnblogs.com/snail-up/p/4682370.html

200行Python代码实现的2048小游戏相关推荐

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

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

  2. 【Python妙用】用200行Python代码制作一个迷宫小游戏

    相信大家都玩过迷宫的游戏,对于简单的迷宫,我们可以一眼就看出通路,但是对于复杂的迷宫,可能要仔细寻找好久,甚至耗费数天,然后可能还要分别从入口和出口两头寻找才能找的到通路,甚至也可能找不到通路. 虽然 ...

  3. 50行Python代码玩转微信小游戏颜色王者

    50行Python代码玩转微信小游戏"颜色王者" 游戏模式 在微信小程序里搜索"颜色王者",即可找到该游戏. 游戏的目标比拼色彩敏感度.点击图片中不一样的色块即 ...

  4. Python之路—200行Python代码搞了个打飞机游戏!!

    早就知道pygame模块,就是没怎么深入研究过,恰逢这周未没约到妹子,只能自己在家玩自己啦,一时兴起,花了几个小时写了个打飞机程序. 很有意思,跟大家分享下. 先看一下项目结构 1 2 3 4 5 6 ...

  5. 详解200行Python代码实现控制台版2048【总有一款坑适合你】【超详细】

    跟着实验楼学习了2048的Python实现,先丢个地址 200行Python代码实现2048 我接触Python时间不长,只了解一些基本的语法和容器,在学习的过程中遇到不少问题,这里做一个记录. cu ...

  6. Python实战2 - 200行Python代码实现2048(控制台)

    Python实战系列用于记录实战项目中的思路,代码实现,出现的问题与解决方案以及可行的改进方向 本文为第2篇–200行Python代码实现2048 一.分析与函数设计 1.1 游戏玩法 2048这款游 ...

  7. python换脸完整程序_小 200 行 Python 代码做了一个换脸程序

    原标题:小 200 行 Python 代码做了一个换脸程序 简介 在这篇文章中我将介绍如何写一个简短(200行)的 Python 脚本,来自动地将一幅图片的脸替换为另一幅图片的脸. 这个过程分四步: ...

  8. 用 200 行 Python 代码掌握基本音乐理论

    本文作者是一位多年自学成才的吉他手,但对西方乐理一无所知,因此决定编写一些代码来搞懂它. 本文用了大约200行Python代码来帮助我们理解西方音乐理论的基础知识. 我们将首先查看西方音乐理论中的音符 ...

  9. python换脸教程_教你如何用200行Python代码“换脸”教程

    原标题:教你如何用200行Python代码"换脸"教程 本文将介绍如何编写一个只有200行的Python脚本,为两张肖像照上人物的"换脸". 这个过程可分为四步 ...

  10. 炫酷!200 行 Python 代码实现马赛克拼图!

    在一图胜千言的时代,没有什么比一张图片更有冲击力的了,那如果一千张图片拼接起来是什么效果呢? 别问,问就是两字 -- 炫酷! 你有没有想过上面的图片是怎么实现的,难道这是用 ps 一张张拼起来的?当然 ...

最新文章

  1. 屏蔽storm ui的kill功能
  2. 1-6 数据查询(下)——复杂查询
  3. 【Python】Pandas profiling 生成报告并部署的一站式解决方案
  4. phpMyAdmin开发人员访谈——4个人支持整个项目
  5. AJAX 带有 取消功能的 UpdateProgress
  6. NAPI 技术在 Linux 网络驱动上的应用和完善
  7. 什么是Reactive Streams in Java 译
  8. Oracle location,oracle秘境探索之11g tablespace prellocation
  9. linux导入多个文件到myql
  10. 离线中技术方案的场景
  11. 内点法(interior point method)求解二次规划,附python代码
  12. 黑群晖一键生成视频缩略图
  13. android 自带TextToSpeech没有声音
  14. 树莓派WiFi设置固定IP地址
  15. KICAD——手动生成嘉立创可识别的BOM和POS文件
  16. 银盒子智慧餐厅硬件尺寸规格推荐机型
  17. jQuery weui Select组件显示指定值
  18. 谷歌搜索 的几种方法
  19. OLED显示STM32
  20. 数据可视化软件有哪些?

热门文章

  1. c语言创建若干个成绩栏目,2015年计算机二级《C语言》考试上机测试题(6)
  2. word2vec训练与相似度计算
  3. Docker 容器使用教程
  4. 【289天】每日项目总结系列027(2017.11.21)
  5. 搜狐畅游一面(c++)
  6. JS与OC交互--简单使用
  7. Struts2基础总结
  8. MYSQL查询重复记录的方法
  9. Spring Batch的事务-Part 1:基础
  10. ISAKMP主模式分析二