zoukankan      html  css  js  c++  java
  • python作业-2048小游戏

    需了解的知识

    Pygame中的各个模块及其功能:

    Pygame.init():初始化所有导入的模块

    pygame.display:

    pygame.display.init()  —  初始化 display 模块

    pygame.display.set_mode()  —  初始化一个准备显示的窗口或屏幕

    pygame.display.set_caption()  — 设置当前窗口标题

    pygame.mixer.music:

    pygame.mixer.music.load()  —  加载音乐进行播放

    pygame.mixer.music.play()  —  开始播放音乐(参数:int播放次数,-1为无限重复。。)

    pygame.time,Clock(创建一个对象帮助跟踪时间):

    pygame.time.Clock.tick():  —  更新时钟

    pygame.event(用户事件和队列进行交互):

    pygame.event.get():  —  在队列中获取事件

    pygame.key(与键盘使用的关系):

    常用列表:

    pygame

    Constant      ASCII   Description

    ---------------------------------

    K_BACKSPACE         backspace

    K_TAB               tab

    K_CLEAR               clear

    K_RETURN            return

    K_PAUSE               pause

    K_ESCAPE      ^[      escape

    K_SPACE               space

    K_EXCLAIM     !       exclaim

    K_QUOTEDBL    "       quotedbl

    K_HASH        #       hash

    K_DOLLAR      $       dollar

    K_AMPERSAND   &       ampersand

    K_QUOTE               quote

    K_LEFTPAREN   (       left parenthesis

    K_RIGHTPAREN  )       right parenthesis

    K_ASTERISK    *       asterisk

    K_PLUS        +       plus sign

    K_COMMA       ,       comma

    K_MINUS       -       minus sign

    K_PERIOD      .       period

    K_SLASH       /       forward slash

    K_0           0       0

    。。。

    K_COLON       :       colon

    K_SEMICOLON   ;       semicolon

    K_LESS        <       less-than sign

    K_EQUALS      =       equals sign

    K_GREATER     >       greater-than sign

    K_QUESTION    ?       question mark

    K_AT          @       at

    K_LEFTBRACKET [       left bracket

    K_BACKSLASH          backslash

    K_RIGHTBRACKET ]      right bracket

    K_CARET       ^       caret

    K_UNDERSCORE  _       underscore

    K_BACKQUOTE   `       grave

    K_a           a       a

    。。。

    K_DELETE              delete

    K_KP0                 keypad 0

    。。。

    K_KP_PERIOD   .       keypad period

    K_KP_DIVIDE   /       keypad divide

    K_KP_MULTIPLY *       keypad multiply

    K_KP_MINUS    -       keypad minus

    K_KP_PLUS     +       keypad plus

    K_KP_ENTER          keypad enter

    K_KP_EQUALS   =       keypad equals

    K_UP                  up arrow

    K_DOWN                down arrow

    K_RIGHT               right arrow

    K_LEFT                left arrow

    K_INSERT              insert

    K_HOME                home

    K_END                 end

    K_PAGEUP              page up

    K_PAGEDOWN            page down

    K_F1                  F1

    。。。

    K_NUMLOCK             numlock

    K_CAPSLOCK            capslock

    K_SCROLLOCK           scrollock

    K_RSHIFT              right shift

    K_LSHIFT              left shift

    K_RCTRL               right control

    K_LCTRL               left control

    K_RALT                right alt

    K_LALT                left alt

    K_RMETA               right meta

    K_LMETA               left meta

    K_LSUPER              left Windows key

    K_RSUPER              right Windows key

    K_MODE                mode shift

    K_HELP                help

    K_PRINT               print screen

    K_SYSREQ              sysrq

    K_BREAK               break

    K_MENU                menu

    K_POWER               power

    K_EURO                Euro

     

    系统结构

    Modules存放实现的模块

    Resources存放游戏资源文件

    cfg.py存放配置文件

    实现代码

    cfg.py配置文件:

     

    import os
    
    '''FPS'''
    FPS = 60
    '''背景颜色'''
    BG_COLOR = '#92877d'
    '''屏幕大小'''
    SCREENSIZE = (650, 370)
    '''保存当前最高分的文件'''
    MAX_SCORE_FILEPATH = 'score'
    '''字体路径'''
    FONTPATH = os.path.join(os.getcwd(), 'resources/font/Gabriola.ttf')
    '''背景音乐路径'''
    BGMPATH = os.path.join(os.getcwd(), 'resources/audio/bgm.mp3')
    '''其他一些必要的常量'''
    MARGIN_SIZE = 10
    BLOCK_SIZE = 80
    GAME_MATRIX_SIZE = (4, 4)

    执行文件2048Game.py

    # 游戏初始化
    
    
    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)

    # 实例化2048游戏
    game_2048 = Game2048(matrix_size=cfg.GAME_MATRIX_SIZE, max_score_filepath=cfg.MAX_SCORE_FILEPATH)

    # 游戏主循环
    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)

    在modules中定义一个Game2048的类(里面主要负责实现2048的各种游戏规则):

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

    游戏开始时需要随机的在二维列表里随机选择两个位置生成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

    然后,当玩家按下方向键(↑↓← →)时,这个二维列表要根据玩家的操作指令进行更新,主要分为两个部分:

    移动所有的数字块并进行必要的合并和记分;

    随机地在一个还没有数字的位置上生成一个数字。

    更新游戏状态

    def update(self):
       game_matrix_before = copy.deepcopy(self.game_matrix)
       self.move()
       if game_matrix_before != self.game_matrix: self.randomGenerateNumber()
       if self.score > self.max_score: self.max_score = self.score

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

    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

    判断游戏是否结束:

    游戏是否结束

     

    @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

    在游戏主循环里根据用户操作来更新当前的游戏状态并将游戏里所有必要的元素显示在屏幕:

    # 游戏主循环

     

    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 ./Game2048来执行:

     

    总结和展望

           通过此次学习,我了解了python的灵活性以及代码的可阅读性比一般的语言要强,并且如今python社区有许多活跃的用户可以在网络上找到许多相关的资料资源。通过此次学习深刻理解了python中的面向对象思想,也了解了一些游戏的设计想法和可供实现的模块。现如今正在学习其他东西,如果未来有更多充裕的时间可以加深python的理解,学习更多的内容,自己做出更好的项目。

    参考:https://mp.weixin.qq.com/s/WJhg4J0MuuEcmDasRzuE9Q

  • 相关阅读:
    linux查看用户组所有成员
    navicat for mysql 在Mac上安装后没有连接列表,就是左边的那一列连接项目怎么办?
    mysql启动问题access denied for user 'root'@'localhost'(using password:YES)
    phpcms多站点表单统一到主站点管理的解决方案
    thinkphp5.0 session驱动方式问题汇总
    Python__开启进程的两种方式
    Python并发编程之操作系统理论部分
    操作系统简介
    Python__基于udp的套接字
    网络编程1
  • 原文地址:https://www.cnblogs.com/jev-0987/p/13073461.html
Copyright © 2011-2022 走看看