如何用 Python 写出简单的 2048 小遊戏
大家好,我是一个喜欢研究算法、机械学习和生物计算的小青年 如果您喜欢我的笔记,那么请点一下关注、点赞和收藏。如果内容有错或者有改进的空间,也可以在评论让我知道。😄
平时工作太忙,为了舒缓下身心,有空的时候我就会写些杂七杂八的东西😂一方面可以放空下自己的,另一方面顺便训练下自己的写代码能力👨🏻💻。
下面是我之前自己用 Python3 复现了一个之前挺火的小游戏 — 2048。因为只是纯粹觉得有趣才写,没有考虑复杂度的问题,也没有用多余的 Python packages来辅助 (只用了Python3 自己的 built-in packages),所以美观和算法上不怎麽好,勿见怪。
接下来,介绍一下这个程序的整个构成:
1. 大纲
整个程序其实就是一个 Class
物件,不需要其它参数,只需要定义Class
方法就能运行。
整个程序的大纲如下 (细节后面会讲):
class Playboard2048:
# 初始化2048遊戏数格
def __init__(self):
self.row = 4 # 设定数格为4列
self.col = 4 # 设定数格为4栏
self.field = [[0 for c in range(self.col)] for r in range(self.row)] # 初始所有格子为数字"0"
def __generate_number(self) # 隨机生成一个数字
def __check_stuck(self) # 检查是否死局
def get_maximum(self) # 找出现时最大数字
def show(self) # 展示遊戏数格
def move_left(self) # 把数字往左移动
def move_up(self) # 把数字往上移动
def move_right(self) # 把数字往右移动
def move_down(self) # 把数字往下移动
def play(self) # 开始遊戏
game = Playboard2048()
game.play()
2. 准备遊戏
代码里有两个物件方法直接与遊戏运行相关,分別是show(self)
和play(self)
。
show(self)
是用来显示2048的遊戏数格,把数格里面的 "0"换成空格,以便辨认哪儿是可以移动的方向。
def show(self):
for r in range(self.row):
temp = self.field[r].copy()
for i in range(len(temp)):
if temp[i] == 0:
temp[i] = " "
print(temp)
play(self)
用是用来初始化遊戏和管理遊戏进行时的控制。
def play(self):
exit_ = False # 检查是否登出遊戏
stuck_ = False # 检查是否死局
step = "" # 玩家的方向选择
print("Generating a playboard...") #开始遊戏
while not exit_ and not stuck_:
step = ""
stuck_ = self.__check_stuck()
if stuck_: # 判断为死局
self.show()
print("Game over! You are stuck.")
return
self.__generate_number()
self.show()
while step == "": # 开局,玩家输入方向
step = input("Your step (Up/Down/Left/Right/Exit): ")
step = step.lower()
if step == "exit": # 登出遊戏
print("Thanks for playing, now ending...")
return
print(step)
if step != "up" and step != "down" and step != "left" and step != "right":
step = ""
print("Only Up/Down/Left/Right/Exit is accepted... please re-input: ")
if step == "left":
self.move_left() #左移
elif step == "right":
self.move_right() #右移
elif step == "up":
self.move_up() #上移
elif step == "down":
self.move_down() #下移
max_ = self.get_maximum() # 找出当前最大数字
if max_ == 2048: # 当出现2048,判断玩家胜利
self.show()
print("You win!!!")
return
3. 移动数字
在平时我们玩的 2048 遊戏中,每个回合玩家都可以选择把数字往上、下、左、右四个方向其中一个推。只要该方向还有空位,数字就可以往该方向。
下面用 往左移动做一個例子,另外三个写法大同小异:
def move_left(self):
for r in range(self.row):
diff = 0
for c in range(self.col):
if self.field[r][c] == 0:
diff += 1
elif self.field[r][c] != 0 and diff > 0:
self.field[r][c - diff] = self.field[r][c]
self.field[r][c] = 0
for r in range(self.row):
for c in range(1, self.col):
if self.field[r][c] == self.field[r][c - 1] and c != 0:
self.field[r][c - 1] += self.field[r][c]
self.field[r][c] = 0
if self.field[r][c - 1] == 0:
self.field[r][c - 1] = self.field[r][c]
self.field[r][c] = 0
4. 数字生成 & 系统检查
这段代码远用了random
和math
的built-in packages,可以让系统在任意空格中隨机生成数字
p.s.: 生成数字的计算方法是我自己想出来的,效果未必很好。
def __generate_number(self):
import random
import math
empty = []
for r in range(self.row):
for c in range(self.col):
if self.field[r][c] == 0:
empty.append([r, c])
[picked_r, picked_c] = random.choice(empty)
max_ = 0
for r in range(self.row):
if max_ <= max(self.field[r]):
max_ = max(self.field[r])
self.field[picked_r][picked_c] = 2**(max(0, int(math.log(max_ + 0.00000001, 2)) - 1)) #生成数字的计算方法
当然,这遊戏是有机会死局的,所以每个回合都要检查数格上还有没有空格子给玩家移动。如果四个方向没有,那就返回 stuck = True
。
def __check_stuck(self):
stuck = True
for r in range(self.row):
for c in range(self.col):
current = self.field[r][c]
if 0 <= r < self.row - 1:
if current == self.field[r + 1][c]:
stuck = False
if 0 < r <= self.row - 1:
if current == self.field[r - 1][c]:
stuck = False
if 0 <= c < self.col - 1:
if current == self.field[r][c + 1]:
stuck = False
if 0 < c <= self.col - 1:
if current == self.field[r][c - 1]:
stuck = False
return stuck
5. 玩遊戏
最后,所有代码都写好的话,保存成Python 文件 (.py)。如果在 Linux,可以直接用 python3 -i
這类工具在terminal运行;在Windows也很简单 只要系统里有Python,双击2048.py文件就能进入遊戏。