小白学Python - 用Python制作 2048 游戏

2023-10-26 14:12:49 浏览数 (1)

使用Python 制作2048 游戏

在本文中,我们将通过 Python 代码和逻辑来设计一款您在智能手机上经常玩的 2048 游戏。如果您对游戏不熟悉,强烈建议您先玩一下游戏,以便了解游戏的基本功能。

如何玩2048:

1.有一个4*4的网格,可以填充任意数字。最初,两个随机单元格中填充有 2。休息单元是空的。

2.我们必须按四个键中的任意一个来上、下、左、右移动。当我们按下任意键时,单元格的元素会沿该方向移动,这样,如果该特定行(向左或向右移动的情况下)或列(向上和向下移动的情况下)包含任何两个相同的数字,它们就会得到加起来,该方向的极端单元用该数字填充自身,其余单元再次变空。

3.网格压缩后,任何随机的空单元格都会被 2 填充。

4.按照上述过程,我们必须将任意单元格中的元素相加,使其加倍,得到 2048。如果我们能够做到这一点,我们就赢了。

5.但是,如果在游戏过程中没有剩余的空单元格可以用新的 2 填充,则游戏结束。

在上面的过程中,您可以看到 2048 游戏图形用户界面的快照。但所有的逻辑都在主代码中。因此,为了单独理解其背后的逻辑,我们可以假设上面的网格是一个 4*4 矩阵(具有四行四列的列表)。您可以在下面看到上述游戏在没有 GUI 的情况下进行输入和输出的方法。

例子 :

代码语言:javascript复制
命令如下:
'W' 或 'w' : 向上移动
'S' 或 's' : 下移
'A' 或 'a' :向左移动
'D' 或 'd' :向右移动
[0,0,0,0]
[0,0,0,0]
[0,0,0,0]
[0,0,2,0]
按命令:a
游戏尚未结束
[0,0,0,2]
[0,0,0,0]
[0,0,0,0]
[2, 0, 0, 0]
按命令:s
游戏尚未结束
[0,0,0,0]
[0,0,0,0]
[0,0,2,0]
[2, 0, 0, 2]
按命令:d
游戏尚未结束
[0,0,0,0]
[0,0,0,0]
[2, 0, 0, 2]
[0,0,0,4]
按命令:a
游戏尚未结束
[0,2,0,0]
[0,0,0,0]
[4,0,0,0]
[4,0,0,0]
按命令:s
游戏尚未结束
[0,0,0,0]
[0,0,0,0]
[0,0,0,0]
[8,2,0,2]
...
而这一系列的输入输出将会一直持续下去,直到我们输或赢!

编程方法:

  1. 我们将设计每个逻辑功能,例如我们正在执行向左滑动,然后我们将通过反转矩阵并执行向左滑动来将其用于向右滑动。
  2. 可以通过转置然后向左移动来完成向上移动。
  3. 向下移动可以通过右移转置来完成。
  4. 程序中的所有逻辑都在注释中详细解释了。强烈建议仔细阅读所有评论。

下面有两个 python 文件,一个是 2048.py,其中包含主要驱动程序代码,另一个是logic.py,其中包含所有使用的函数。应该在 2048.py 中导入logic.py才能使用这些函数。只需将这两个文件放在同一个文件夹中,然后运行 2048.py 即可完美运行。

logic.py:

代码语言:javascript复制
# logic.py 
# 导入到2048.py文件中

# 导入随机包
# 用于生成随机数的方法 numbers.
import random

# 初始化游戏/网格的函数在开始时
def start_game():

	# 声明一个空列表 添加4个具有四个元素的列表,每个元素都为0。
	mat =[]
	for i in range(4):
		mat.append([0] * 4)

	# 为用户提供打印控制
	print("Commands are as follows : ")
	print("'W' or 'w' : Move Up")
	print("'S' or 's' : Move Down")
	print("'A' or 'a' : Move Left")
	print("'D' or 'd' : Move Right")

	# 调用函数添加 每一步后在网格中新增一个2
	add_new_2(mat)
	return mat

# 在任意空单元格中添加新的2的函数网格
def add_new_2(mat):

	# 为行和列选择一个随机索引。
	r = random.randint(0, 3)
	c = random.randint(0, 3)

	# 当循环遇到随机选择的单元格为空(或者包含零)时,循环将会终止。
	while(mat[r] != 0):
		r = random.randint(0, 3)
		c = random.randint(0, 3)

	# 我们将在那个空白的随机单元格中放置一个2。
	mat[r] = 2

# 获取当前的函数
# 开始游戏
def get_current_state(mat):

	# 如果任何单元格包含2048,我们就赢了
	for i in range(4):
		for j in range(4):
			if(mat[i][j]== 2048):
				return 'WON'

	# 如果我们仍然有至少一个空单元格游戏还没有结束
	for i in range(4):
		for j in range(4):
			if(mat[i][j]== 0):
				return 'GAME NOT OVER'

	# 或者如果现在没有空单元格但是,如果向左、向右、向上或向下移动后,任何两个单元格合并并创建一个空的单元格,则游戏还未结束
	for i in range(3):
		for j in range(3):
			if(mat[i][j]== mat[i   1][j] or mat[i][j]== mat[i][j   1]):
				return 'GAME NOT OVER'

	for j in range(3):
		if(mat[3][j]== mat[3][j   1]):
			return 'GAME NOT OVER'

	for i in range(3):
		if(mat[i][3]== mat[i   1][3]):
			return 'GAME NOT OVER'

	# 否则我们就输掉了比赛
	return 'LOST'

# 所有下面定义的函数 都是用于左交换初始状态的。

# 压缩网格的函数在每一步之前和之后合并单元格之后。
def compress(mat):

	# 用于确定是否发生了任何更改的布尔变量
	changed = False

	# 空网格
	new_mat = []

	# 所有单元格为空
	for i in range(4):
		new_mat.append([0] * 4)
		
	# 在这里,我们将移动条目每个单元格到它的极限左边逐行循环遍历行
	for i in range(4):
		pos = 0

		# 循环遍历每一列在相应的行中
		for j in range(4):
			if(mat[i][j] != 0):
				
			# 如果单元格非空,则将其数字移至该行中前一个空单元格,由pos变量表示。
				new_mat[i][pos] = mat[i][j]
				
				if(j != pos):
					changed = True
				pos  = 1

	# 返回新的压缩矩阵和标志变量。
	return new_mat, changed

# 合并单元格的函数在压缩后的矩阵中
def merge(mat):
	
	changed = False
	
	for i in range(4):
		for j in range(3):

			# 如果当前单元格与同一行中的下一个单元格具有相同的值,并且它们都不为空,则
			if(mat[i][j] == mat[i][j   1] and mat[i][j] != 0):

				# 将当前单元格值加倍,并 清空下一个单元格
				mat[i][j] = mat[i][j] * 2
				mat[i][j   1] = 0

				# 将布尔变量设置为True,表示合并后的新网格不同。
				changed = True

	return mat, changed

# 反转矩阵的函数表示反转每行的内容(即反转序列)
def reverse(mat):
	new_mat =[]
	for i in range(4):
		new_mat.append([])
		for j in range(4):
			new_mat[i].append(mat[i][3 - j])
	return new_mat

# 获取转置的函数矩阵的行和列
def transpose(mat):
	new_mat = []
	for i in range(4):
		new_mat.append([])
		for j in range(4):
			new_mat[i].append(mat[j][i])
	return new_mat

# 更新矩阵的函数
# if we move / swipe left
def move_left(grid):

	# 首先压缩网格
	new_grid, changed1 = compress(grid)

	# 然后合并单元格。
	new_grid, changed2 = merge(new_grid)
	
	changed = changed1 or changed2

	# 合并后再次压缩。
	new_grid, temp = compress(new_grid)

	# 返回新矩阵和已更改的 bool告知网格是相同或不同
	return new_grid, changed

# 更新矩阵的函数
# if we move / swipe right
def move_right(grid):

	# 要向右移动,我们只需倒转矩阵
	new_grid = reverse(grid)

	# 然后向左移动
	new_grid, changed = move_left(new_grid)

	# 然后再反转矩阵得到我们想要的结果
	new_grid = reverse(new_grid)
	return new_grid, changed

# 更新矩阵的函数
# if we move / swipe up
def move_up(grid):

	# 要向上移动,我们只需矩阵的转置
	new_grid = transpose(grid)

	# 然后向左移动
	new_grid, changed = move_left(new_grid)

	# 再次进行转置就能得到理想的结果
	new_grid = transpose(new_grid)
	return new_grid, changed

# 更新矩阵的函数
# 如果我们向下移动/轻扫
def move_down(grid):

	# 向下移动时,我们进行转置
	new_grid = transpose(grid)

	# 向右移动,然后再向右移动
	new_grid, changed = move_right(new_grid)

	# 采取转置会得到想要的结果。
	new_grid = transpose(new_grid)
	return new_grid, changed
# 此文件仅包含所有逻辑在主函数中调用的功能存在于其他文件中

2048.py

代码语言:javascript复制
# 2048.py 完全代码

# 导入 logic.py 文件
# 使用的逻辑函数。
import logic

# 主代码
if __name__ == '__main__':
	
# 调用 start_game 函数
# 初始化矩阵
	mat = logic.start_game()

while(True):

	# 接收用户输入下一步
	x = input("Press the command : ")

	# 我们必须向上移动	
	if(x == 'W' or x == 'w'):

		# 调用 move_up 函数
		mat, flag = logic.move_up(mat)

		# 获取当前状态并打印
		status = logic.get_current_state(mat)
		print(status)

		# 如果游戏没有结束,则继续并添加一个新的2
		if(status == 'GAME NOT OVER'):
			logic.add_new_2(mat)

		# 退出循环
		else:
			break

	# 以上程序将按照 # 在每种类型的情况下移动下面

	# 向下移动
	elif(x == 'S' or x == 's'):
		mat, flag = logic.move_down(mat)
		status = logic.get_current_state(mat)
		print(status)
		if(status == 'GAME NOT OVER'):
			logic.add_new_2(mat)
		else:
			break

	# 向左移动
	elif(x == 'A' or x == 'a'):
		mat, flag = logic.move_left(mat)
		status = logic.get_current_state(mat)
		print(status)
		if(status == 'GAME NOT OVER'):
			logic.add_new_2(mat)
		else:
			break

	# 向右移动
	elif(x == 'D' or x == 'd'):
		mat, flag = logic.move_right(mat)
		status = logic.get_current_state(mat)
		print(status)
		if(status == 'GAME NOT OVER'):
			logic.add_new_2(mat)
		else:
			break
	else:
		print("Invalid Key Pressed")

	# 在每次移动后打印矩阵。
	print(mat)

输出:

所有的代码中都有注释,大家可以研究研究,可以玩出自己的花样。

以下是 2048 游戏的界面

0 人点赞