Python实战:手把手教你编写2048小游戏

感觉好久没有写小游戏玩了,今天恰巧有空.这次我来用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小游戏的文章就介绍到这了,喜欢且对你有用的话,点个关注吧 ! 下回见~

    以上就是今天的全部内容分享,觉得有用的话欢迎点赞收藏哦!

    Python经验分享

    学好 Python 不论是用于就业还是做副业赚钱都不错,而且学好Python还能契合未来发展趋势——人工智能、机器学习、深度学习等。
    小编是一名Python开发工程师,自己整理了一套最新的Python系统学习教程,包括从基础的python脚本到web开发、爬虫、数据分析、数据可视化、机器学习等。如果你也喜欢编程,想通过学习Python转行、做副业或者提升工作效率,这份【最新全套Python学习资料】 一定对你有用!

    小编为对Python感兴趣的小伙伴准备了以下籽料 !

    对于0基础小白入门:

    如果你是零基础小白,想快速入门Python是可以考虑培训的!

  • 学习时间相对较短,学习内容更全面更集中
  • 可以找到适合自己的学习方案
  • 包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、机器学习、Python量化交易等学习教程。带你从零基础系统性的学好Python!

    一、Python所有方向的学习路线

    Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

    二、学习软件

    工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

    三、入门学习视频

    我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

    四、实战案例

    光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

    五、面试资料

    我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。


    最新全套【Python入门到进阶资料 & 实战源码 &安装工具】(安全链接,放心点击)

    我已经上传至CSDN官方,如果需要可以扫描下方官方二维码免费获取【保证100%免费】

    *今天的分享就到这里,喜欢且对你有所帮助的话,记得点赞关注哦~下回见 !

    作者:码农必胜客

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python实战:手把手教你编写2048小游戏

    发表回复