200 行代码实现简易版 2048 游戏
admin
2023-07-31 00:40:46
0

创建游戏文件 2048.py

首先导入需要的包:

123 import cursesfrom random import randrange, choicefrom collections import defaultdict

主逻辑

用户行为

所有的有效输入都可以转换为”上,下,左,右,游戏重置,退出”这六种行为,用 actions 表示

1 actions = [\’Up\’, \’Left\’, \’Down\’, \’Right\’, \’Restart\’, \’Exit\’]

有效输入键是最常见的 W(上),A(左),S(下),D(右),R(重置),Q(退出),这里要考虑到大写键开启的情况,获得有效键值列表:

1 letter_codes = [ord(ch) for ch in \’WASDRQwasdrq\’]

将输入与行为进行关联:

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

状态机

处理游戏主逻辑的时候我们会用到一种十分常用的技术:状态机,或者更准确的说是有限状态机(FSM)

你会发现 2048 游戏很容易就能分解成几种状态的转换。

state 存储当前状态, state_actions 这个词典变量作为状态转换的规则,它的 key 是状态,value 是返回下一个状态的函数:

  • Init: init()
    • Game
  • Game: game()
    • Game
    • Win
    • GameOver
    • Exit
  • Win: lambda: not_game(‘Win’)
    • Init
    • Exit
  • Gameover: lambda: not_game(‘Gameover’)
    • Init
    • Exit
  • Exit: 退出循环

状态机会不断循环,直到达到 Exit 终结状态结束程序。

下面是经过提取的主逻辑的代码,会在后面进行补全:

12345678910111213141516171819202122232425262728293031323334353637383940 def main(stdscr):     def init():        #重置游戏棋盘        return \’Game\’     def not_game(state):        #画出 GameOver 或者 Win 的界面        #读取用户输入得到action,判断是重启游戏还是结束游戏        responses = defaultdict(lambda: state) #默认是当前状态,没有行为就会一直在当前界面循环        responses[\’Restart\’], responses[\’Exit\’] = \’Init\’, \’Exit\’ #对应不同的行为转换到不同的状态        return responses[action]     def game():        #画出当前棋盘状态        #读取用户输入得到action        if action == \’Restart\’:            return \’Init\’        if action == \’Exit\’:            return \’Exit\’        #if 成功移动了一步:            if 游戏胜利了:                return \’Win\’            if 游戏失败了:                return \’Gameover\’        return \’Game\’      state_actions = {            \’Init\’: init,            \’Win\’: lambda: not_game(\’Win\’),            \’Gameover\’: lambda: not_game(\’Gameover\’),            \’Game\’: game        }     state = \’Init\’     #状态机开始循环    while state != \’Exit\’:        state = state_actions[state]()

用户输入处理

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

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

矩阵转置与矩阵逆转

加入这两个操作可以大大节省我们的代码量,减少重复劳动,看到后面就知道了。

矩阵转置:

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

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

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

创建棋盘

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

12345678 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

1234 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

重置棋盘

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

一行向左合并

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

12345678

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...