用Python手把手教你实现2048小游戏

作者:彳余大胆 时间:2023-02-22 23:27:57 

一、开发环境

Python版本:3.6.4
相关模块:
pygame模块;
以及一些Python自带的模块。

二、环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

三、原理介绍

“使用方向键移动方块,两个数字相同的方块撞在一起后,将会合并为一个数字是原来两倍的新方块。游戏的时候尽可能多地合并这些数字方块就行了。”
大概了解了游戏规则之后,我们就可以开始写这个游戏啦~首先,进行一下游戏初始化操作并播放一首自己喜欢的游戏背景音乐:


# 游戏初始化
pygame.init()
screen = pygame.display.set_mode(cfg.SCREENSIZE)
pygame.display.set_caption('2048 —— 彳余大胆')
# 播放背景音乐
pygame.mixer.music.load(cfg.BGMPATH)
pygame.mixer.music.play(-1, 30)

接着,我们来定义一个2048游戏类,里面主要负责实现2048的各种游戏规则:


'''2048游戏'''
class Game2048(object):
 def __init__(self, matrix_size=(4, 4), max_score_filepath=None, **kwargs):
   # matrix_size: (num_rows, num_cols)
   self.matrix_size = matrix_size
   # 游戏最高分保存路径
   self.max_score_filepath = max_score_filepath
   # 初始化
   self.initialize()

具体而言,我们先用一个二维的列表来保存当前的游戏状态:


self.game_matrix = [['null' for _ in range(self.matrix_size[1])] for _ in range(self.matrix_size[0])]

其中null表示当前的块里没有数字。否则,对应的位置则用当前的数字表示。很显然地,2048小游戏的当前游戏状态是可以用一个4*4的列表表示的:

用Python手把手教你实现2048小游戏

游戏一开始,我们需要在这个二维列表里随机地选择两个位置生成数字(即2或者4):


'''在新的位置随机生成数字'''
def randomGenerateNumber(self):
 empty_pos = []
 for i in range(self.matrix_size[0]):
   for j in range(self.matrix_size[1]):
     if self.game_matrix[i][j] == 'null': empty_pos.append([i, j])
 i, j = random.choice(empty_pos)
 self.game_matrix[i][j] = 2 if random.random() > 0.1 else 4

self.randomGenerateNumber()
self.randomGenerateNumber()

然后,当玩家按下方向键(↑↓←→)时,这个二维列表要根据玩家的操作指令进行更新,主要分为两个部分:
移动所有的数字块并进行必要的合并和记分;
随机地在一个还没有数字的位置上生成一个数字。
具体而言,代码实现如下:


'''更新游戏状态'''
def update(self):
 game_matrix_before = copy.deepcopy(self.game_matrix)
 self.move()
 if game_matrix_before != self.game_matrix: self.randomGenerateNumber()

其中,移动所有的数字并进行必要的合并的代码实现如下:


'''根据指定的方向, 移动所有数字块'''
def move(self):
 # 提取非空数字
 def extract(array):
   array_new = []
   for item in array:
     if item != 'null': array_new.append(item)
   return array_new
 # 合并非空数字
 def merge(array):
   score = 0
   if len(array) < 2: return array, score
   for i in range(len(array)-1):
     if array[i] == 'null':
       break
     if array[i] == array[i+1]:
       array[i] *= 2
       array.pop(i+1)
       array.append('null')
       score += array[i]
   return extract(array), score
 # 不需要移动的话直接return
 if self.move_direction is None: return
 # 向上
 if self.move_direction == 'up':
   for j in range(self.matrix_size[1]):
     col = []
     for i in range(self.matrix_size[0]):
       col.append(self.game_matrix[i][j])
     col = extract(col)
     col.reverse()
     col, score = merge(col)
     self.score += score
     col.reverse()
     col = col + ['null',] * (self.matrix_size[0] - len(col))
     for i in range(self.matrix_size[0]):
       self.game_matrix[i][j] = col[i]
 # 向下
 elif self.move_direction == 'down':
   for j in range(self.matrix_size[1]):
     col = []
     for i in range(self.matrix_size[0]):
       col.append(self.game_matrix[i][j])
     col = extract(col)
     col, score = merge(col)
     self.score += score
     col = ['null',] * (self.matrix_size[0] - len(col)) + col
     for i in range(self.matrix_size[0]):
       self.game_matrix[i][j] = col[i]
 # 向左
 elif self.move_direction == 'left':
   for idx, row in enumerate(copy.deepcopy(self.game_matrix)):
     row = extract(row)
     row.reverse()
     row, score = merge(row)
     self.score += score
     row.reverse()
     row = row + ['null',] * (self.matrix_size[1] - len(row))
     self.game_matrix[idx] = row
 # 向右
 elif self.move_direction == 'right':
   for idx, row in enumerate(copy.deepcopy(self.game_matrix)):
     row = extract(row)
     row, score = merge(row)
     self.score += score
     row = ['null',] * (self.matrix_size[1] - len(row)) + row
     self.game_matrix[idx] = row
 self.move_direction = None

懒得动脑子了(反正就4*4那么大T_T),所以直接遍历了这个二维列表以实现我们想要的所有操作了。最后,我们再写个函数以根据当前的游戏状态来判断游戏是否结束就ok啦:


'''游戏是否结束'''
@property
def isgameover(self):
 for i in range(self.matrix_size[0]):
   for j in range(self.matrix_size[1]):
     if self.game_matrix[i][j] == 'null': return False
     if (i == self.matrix_size[0] - 1) and (j == self.matrix_size[1] - 1):
       continue
     elif (i == self.matrix_size[0] - 1):
       if (self.game_matrix[i][j] == self.game_matrix[i][j+1]):
         return False
     elif (j == self.matrix_size[1] - 1):
       if (self.game_matrix[i][j] == self.game_matrix[i+1][j]):
         return False
     else:
       if (self.game_matrix[i][j] == self.game_matrix[i+1][j]) or (self.game_matrix[i][j] == self.game_matrix[i][j+1]):
         return False
 return True

其实很简单,如果二维列表被数字填满,且数字不能再进行合并的话,这局游戏就结束了,否则,游戏就没有结束。
定义完2048游戏类,我们的游戏基本上算是写完了。只需要在游戏主循环里根据用户操作来更新当前的游戏状态并将游戏里所有必要的元素显示在屏幕上就ok啦:


# 游戏主循环
clock = pygame.time.Clock()
is_running = True
while is_running:
 screen.fill(pygame.Color(cfg.BG_COLOR))
 # --按键检测
 for event in pygame.event.get():
   if event.type == pygame.QUIT:
     pygame.quit()
     sys.exit()
   elif event.type == pygame.KEYDOWN:
     if event.key in [pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT]:
       game_2048.setDirection({pygame.K_UP: 'up', pygame.K_DOWN: 'down', pygame.K_LEFT: 'left', pygame.K_RIGHT: 'right'}[event.key])
 # --更新游戏状态
 game_2048.update()
 if game_2048.isgameover:
   game_2048.saveMaxScore()
   is_running = False
 # --将必要的游戏元素画到屏幕上
 drawGameMatrix(screen, game_2048.game_matrix, cfg)
 start_x, start_y = drawScore(screen, game_2048.score, game_2048.max_score, cfg)
 drawGameIntro(screen, start_x, start_y, cfg)
 # --屏幕更新
 pygame.display.update()
 clock.tick(cfg.FPS)
return endInterface(screen, cfg)

四、效果图

最后的效果大概是这样的:

用Python手把手教你实现2048小游戏
用Python手把手教你实现2048小游戏

玩这个我还是一个菜鸡,嘿嘿~

来源:https://blog.csdn.net/Gtieguo/article/details/117465249

标签:Python,2048,小游戏
0
投稿

猜你喜欢

  • Python 实现PS滤镜的旋涡特效

    2022-03-03 02:53:52
  • ubuntu 18.04 安装opencv3.4.5的教程(图解)

    2022-10-29 16:36:01
  • MySQL OOM(内存溢出)的解决思路

    2024-01-26 08:38:26
  • 利用Go语言实现简单Ping过程的方法

    2024-04-25 13:22:53
  • 解析python中的jsonpath 提取器

    2021-11-18 23:06:04
  • MySQL数据库临时文件究竟储存在哪里

    2009-09-06 12:11:00
  • Bootstrap Table快速完美搭建后台管理系统

    2024-05-09 09:48:16
  • easyUI实现(alert)提示框自动关闭的实例代码

    2024-04-22 22:43:31
  • 阿里巴巴技术文章分享 Javascript继承机制的实现

    2024-04-30 09:59:16
  • Python网络爬虫与信息提取(实例讲解)

    2022-10-27 20:53:04
  • Python 调用 C++ 传递numpy 数据详情

    2021-05-12 20:00:39
  • python中as用法实例分析

    2023-08-11 01:12:26
  • 详解Python装饰器

    2023-11-12 12:40:06
  • 利用anaconda保证64位和32位的python共存

    2021-07-23 09:18:24
  • Javascript的常规数组和关联数组对比小结

    2024-04-28 09:47:29
  • 使用python处理题库表格并转化为word形式的实现

    2023-07-25 12:33:18
  • Python os.mkdir()与os.makedirs()的使用区别

    2023-08-19 20:01:56
  • 浅析python中SQLAlchemy排序的一个坑

    2023-03-29 10:47:23
  • Java实现学生信息管理系统(使用数据库)

    2024-01-25 11:22:03
  • Python Selenium参数配置方法解析

    2023-12-28 09:20:02
  • asp之家 网络编程 m.aspxhome.com