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

 更新时间:2021年06月04日 08:38:55   作者:彳余大胆  
感觉好久没和大家一起写小游戏玩了,今天恰巧有空.这次我们来用Python做个2048小游戏吧.废话不多说,文中有非常详细的代码示例,需要的朋友可以参考下

一、开发环境

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的列表表示的:

在这里插入图片描述

游戏一开始,我们需要在这个二维列表里随机地选择两个位置生成数字(即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小游戏的文章就介绍到这了,更多相关Python2048小游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python如何解决secure_filename对中文不支持问题

    Python如何解决secure_filename对中文不支持问题

    最近使用到了secure_filename,然后悲剧的发现中文居然不展示出来,本文就详细的介绍一下解决方法,感兴趣的可以了解一下
    2021-07-07
  • 基于PyInstaller各参数的含义说明

    基于PyInstaller各参数的含义说明

    这篇文章主要介绍了基于PyInstaller各参数的含义说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • Keras预训练的ImageNet模型实现分类操作

    Keras预训练的ImageNet模型实现分类操作

    这篇文章主要介绍了Keras预训练的ImageNet模型实现分类操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • python hough变换检测直线的实现方法

    python hough变换检测直线的实现方法

    这篇文章主要介绍了python hough变换检测直线的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • python将红底证件照转成蓝底的实现方法

    python将红底证件照转成蓝底的实现方法

    这篇文章主要介绍了python将红底证件照转成蓝底,本文给大家分享四种方法通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • python 对图片进行简单的处理

    python 对图片进行简单的处理

    介绍一些图片处理的Python代码,有了这些处理代码,我们可以很方便的处理一些图片,Python这里处理图片一般都使用Pillow包,有此需求的朋友可以参考下
    2021-06-06
  • python实现稀疏矩阵示例代码

    python实现稀疏矩阵示例代码

    本篇文章主要介绍了python实现稀疏矩阵示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 运用Python3实现Two-Pass算法检测区域连通性

    运用Python3实现Two-Pass算法检测区域连通性

    如何高效的检测出连通区域的流动性是大家一直关注的话题,这篇文章主要介绍了运用Python3实现Two-Pass算法检测区域连通性,感兴趣的朋友可以一起来看看
    2021-08-08
  • Python flask框架post接口调用示例

    Python flask框架post接口调用示例

    这篇文章主要介绍了Python flask框架post接口调用,结合实例形式分析了基于flask框架的post、get请求响应及接口调用相关操作技巧,需要的朋友可以参考下
    2019-07-07
  • python 实现GUI(图形用户界面)编程详解

    python 实现GUI(图形用户界面)编程详解

    今天小编就为大家分享一篇python 实现GUI(图形用户界面)编程详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-07-07

最新评论