2048小游戏--pygame来实现

2048小游戏-pygame来实现.(借鉴网友代码,仅供学习)

文件结构如下:

 main.py代码

# main.py
"""
 功能:2048小游戏
 作者:指尖魔法师
 QQ:14555110
"""

import pygame
from sys import exit
from modules.game2048 import *
from modules.utils import *
import cfg
from modules.endInterface import *


def main(cfg):
    # 初始化pygame
    pygame.init()

    pygame.mixer.music.load(cfg.BGMPATH)
    pygame.mixer.music.play(-1)

    # 创建一个窗口
    screen = pygame.display.set_mode(cfg.SCREENSIZE, 0, 32)

    # 设置窗口标题
    pygame.display.set_caption("2048小游戏--作者:指尖魔法师 QQ:14555110")

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

    # 游戏主循环
    is_running = True
    while is_running:
        # 填充背景颜色
        screen.fill(pygame.Color(cfg.BG_COLOR))

        # 按键检测
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                # 接受到退出事件后退出
                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:
            print('游戏结束')
            is_running = False
            game_2048.saveMaxScore()

        # 将元素画到屏幕上
        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()

    # 游戏结束界面
    return endInterface(screen, cfg)

if __name__ =='__main__':
    while True:
        if not main(cfg):
            break

cfg.py代码

# cfg.py
"""
 功能:配置文件
 作者:指尖魔法师
 QQ:14555110
"""
import os

# 屏幕大小
SCREENSIZE = (650, 370)

# 背景颜色
BG_COLOR = '#92877d'

# 背景音乐路径
BGMPATH = 'resources/shaonian.mp3'

# 字体路径
FONTPATH = os.path.join(os.getcwd(), 'resources/gabriola.ttf')

# 4 * 4 大小
GAME_MATRIX_SIZE = (4, 4)

# 方块大小
MATRIX_SIZE = 80

# 方块间间距
MARGIN_SIZE = 10

# 保存最高分文件路径
MAX_SCORE_FILEPATH = 'score'

 

game2048.py代码

# game2048.py
"""
 功能:Game2048类
 作者:指尖魔法师
 QQ:14555110
"""

import pygame
import random
import copy
class Game2048(object):
    def __init__(self, matrix_size=(4, 4), max_score_filepath=None):
        self.matrix_size = matrix_size
        # 游戏最高分保存路径
        self.max_score_filepath = max_score_filepath

        self.initialize()

    def initialize(self):
        """初始化"""
        self.game_matrix = [['null' for _ in range(self.matrix_size[1])] for _ in range(self.matrix_size[0])]

        # 读取最高分
        self.score = 0
        self.max_score = self.readMaxScore()

        # 初始化时随机2位数值
        self.randomGenerateNumber()
        self.randomGenerateNumber()
        # 当前所有位置的数值
        print(self.game_matrix)

        self.move_direction = None

    def update(self):
        """更新游戏状态"""
        self.game_matrix_before = copy.deepcopy(self.game_matrix)
        self.move()
        if self.game_matrix != self.game_matrix_before:
            # 方块变化后,随机一个新的数字
            self.randomGenerateNumber()

        # 游戏分数大于最高分,更新最高分
        if self.score > self.max_score:
            self.max_score = self.score

    def randomGenerateNumber(self):
        """在空白位置产生随机数 2 或者 4"""
        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])
        # 空白位置列表
        # print(empty_pos)

        # 随机位置生成
        i, j = random.choice(empty_pos)

        # 随机数生成
        self.game_matrix[i][j] = 2 if random.random() > 0.1 else 4

        print('随机数位置为[{0}][{1}] = 数值{2}'.format(i, j, self.game_matrix[i][j]))

    def readMaxScore(self):
        """读取文件中的最高分"""
        try:
            f = open(self.max_score_filepath, 'r', encoding='utf-8')
            score = int(f.read().strip())
            f.close()
            return score
        except:
            return 0

    def setDirection(self, direction):
        assert direction in ['UP', 'DOWN', 'LEFT', 'RIGHT']
        self.move_direction = direction
        print(self.move_direction)

    def move(self):

        # 提取非空数值
        def extract(array):
            new_array = []
            for arr in array:
                if arr != 'null':
                    new_array.append(arr)
            return new_array

        # 合并非空数字
        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] += array[i+1]
                    score += array[i]
                    array.pop(i+1)
                    array.append('null')
            return extract(array), score

        # 不需要移动的话直接返回
        if self.move_direction is None:
            return

        if self.move_direction == 'UP':
            # print("向上移动一次")
            for j in range(self.matrix_size[1]):
                # 获取该列数据
                col = []
                for i in range(self.matrix_size[0]):
                    col.append(self.game_matrix[i][j])

                # 提取非空数值
                new_col = extract(col)

                # 合并非空数字
                new_col, score = merge(new_col)
                self.score += score

                # 补全列表null
                new_col.extend('null' for _ in range(self.matrix_size[0] - len(new_col)))

                # 从上往下更新该列数据
                for i in range(self.matrix_size[0]):
                    self.game_matrix[i][j] = new_col[i]
                # print(self.game_matrix)

        elif self.move_direction == 'DOWN':
            # print("向下移动一次")
            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.reverse()

                # 提取非空数值
                new_col = extract(col)

                # 合并非空数字
                new_col, score = merge(new_col)
                self.score += score

                # 补全列表null
                new_col.extend('null' for _ in range(self.matrix_size[0] - len(new_col)))

                # 翻转列
                new_col.reverse()

                # 从上往下更新该列数据
                for i in range(self.matrix_size[0]):
                    self.game_matrix[i][j] = new_col[i]
                # print(self.game_matrix)

        elif self.move_direction == 'LEFT':
            # print("向左移动一次")
            for i in range(self.matrix_size[0]):
                # 获取该和行数据
                row = []
                for j in range(self.matrix_size[1]):
                    row.append(self.game_matrix[i][j])

                # 提取非空数值
                new_row = extract(row)

                # 合并非空数字
                new_row, score = merge(new_row)
                self.score += score

                # 补全列表null
                new_row.extend('null' for _ in range(self.matrix_size[1] - len(new_row)))

                # 从左往右更新该该行数据
                for j in range(self.matrix_size[1]):
                    self.game_matrix[i][j] = new_row[j]
                # print(self.game_matrix)

        elif self.move_direction == 'RIGHT':
            # print("向右移动一次")
            for i in range(self.matrix_size[0]):
                # 获取该和行数据
                row = []
                for j in range(self.matrix_size[1]):
                    row.append(self.game_matrix[i][j])

                # 翻转行列表
                row.reverse()
                # 提取非空数值
                new_row = extract(row)

                # 合并非空数字
                new_row, score = merge(new_row)
                self.score += score

                # 补全列表null
                new_row.extend('null' for _ in range(self.matrix_size[1] - len(new_row)))

                # 翻转行列表
                new_row.reverse()

                # 从左往右更新该该行数据
                for j in range(self.matrix_size[1]):
                    self.game_matrix[i][j] = new_row[j]

                # print(self.game_matrix)

        # 状态置空
        self.move_direction = None

    def saveMaxScore(self):
        """保存最高分"""
        f = open(self.max_score_filepath, 'w', encoding='utf-8')
        f.write(str(self.max_score))
        f.close()

    @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
                elif (j + 1 <= self.matrix_size[1] - 1) and (self.game_matrix[i][j] == self.game_matrix[i][j+1]):
                    return False
                elif (i + 1 <= self.matrix_size[0] - 1) and (self.game_matrix[i][j] == self.game_matrix[i+1][j]):
                    return False
        return True


if __name__ == "__main__":
    game_2048 = Game2048(matrix_size=(4, 4), max_score_filepath='../score')

utils.py代码

"""
 功能:部分函数
 作者:指尖魔法师
 QQ:14555110
"""
import pygame

# 方块背景颜色和字体颜色
def getColorByNumber(number):
    number2Color_dict = {2: ['#eee4da', '#776e65'],4: ['#ede0c8', '#776e65'], 8: ['#f2b179', '#f9f6f2'],
                        16: ['#f59563', '#f9f6f2'], 32: ['#f67c5f', '#f9f6f2'], 64: ['#f65e3b', '#f9f6f2'],
                        128: ['#edcf72', '#f9f6f2'], 256: ['#edcc61', '#f9f6f2'], 512: ['#edc850', '#f9f6f2'],
                        1024: ['#edc53f', '#f9f6f2'], 2048: ['#edc22e', '#f9f6f2'], 4096: ['#eee4da', '#776e65'],
                        8192: ['#edc22e', '#f9f6f2'], 16384: ['#f2b179', '#776e65'], 32768: ['#f59563', '#776e65'],
                        65536: ['#f67c5f', '#f9f6f2'], 'null': ['#9e948a', None]}
    return number2Color_dict[number]

# 绘制游戏方块
def drawGameMatrix(screen,game_matrix, cfg):
    for i in range(len(game_matrix)):
        for j in range(len(game_matrix[i])):
            number = game_matrix[i][j]
            x = (j+1)*cfg.MARGIN_SIZE + j*cfg.MATRIX_SIZE
            y = (i+1)*cfg.MARGIN_SIZE + i*cfg.MATRIX_SIZE

            pygame.draw.rect(screen, pygame.Color(getColorByNumber(number)[0]), (x, y, cfg.MATRIX_SIZE, cfg.MATRIX_SIZE))
            # print('game_matrix[{0}][{1}]={2}'.format(i, j, number))

            if number != 'null':
                font_color = pygame.Color(getColorByNumber(number)[1])
                font_size = cfg.MATRIX_SIZE - cfg.MARGIN_SIZE*len(str(number))
                font = pygame.font.Font(cfg.FONTPATH, font_size)
                text = font.render(str(number), True, font_color)
                text_rect = text.get_rect()
                text_rect.centerx, text_rect.centery = x + cfg.MATRIX_SIZE / 2, y + cfg.MATRIX_SIZE / 2
                screen.blit(text, text_rect)


# 绘制分数
def drawScore(screen, score, max_score, cfg):
    font_color = (255, 255, 255)
    font_size = 30
    font = pygame.font.Font(cfg.FONTPATH, font_size)
    text_score = font.render('Score:  '+str(score), True, font_color)
    text_max_score = font.render('Best Score:  ' + str(max_score), True, font_color)
    start_x = cfg.GAME_MATRIX_SIZE[1] * cfg.MATRIX_SIZE + (cfg.GAME_MATRIX_SIZE[1] + 1) * cfg.MARGIN_SIZE
    screen.blit(text_max_score, (start_x+10, 10))
    screen.blit(text_score, (start_x + 10, 20 + text_score.get_height()))
    start_y = 30 + text_score.get_height() * 2

    return (start_x, start_y)

# 绘制游戏介绍
def drawGameIntro(screen, start_x, start_y, cfg):
    start_y += 40
    font_color = (255, 255, 255)
    font_size_big = 30
    font_size_small = 20
    font_big = pygame.font.Font(cfg.FONTPATH, font_size_big)
    font_small = pygame.font.Font(cfg.FONTPATH, font_size_small)
    intros = ['TIPS:', 'Use arrow keys to move the number blocks.', 'Adjacent blocks with the same number will',
              'be merged. Just try to merge the blocks as', 'many as you can!']
    for idx, intro in enumerate(intros):
        font = font_big if idx == 0 else font_small
        text = font.render(intro, True, font_color)
        screen.blit(text, (start_x + 10, start_y))
        start_y += font.get_height() + 10

 

endInterface.py

"""
 功能:游戏结束页面
 作者:指尖魔法师
 QQ:14555110
"""

import pygame
import sys

def endInterface(screen,cfg):
    font_size_big = 60
    font_size_small = 30
    font_color = (255, 255, 255)
    font_big = pygame.font.Font(cfg.FONTPATH, font_size_big)
    font_small = pygame.font.Font(cfg.FONTPATH, font_size_small)
    surface = screen.convert_alpha()
    surface.fill((188, 188, 188, 2))
    text = font_big.render('Game Over!', True, font_color)
    text_rect = text.get_rect()
    text_rect.centerx, text_rect.centery = cfg.SCREENSIZE[0] / 2, cfg.SCREENSIZE[1] / 2 - 50
    surface.blit(text, text_rect)
    button_width, button_height = 100, 40
    button_start_x_left = cfg.SCREENSIZE[0] / 2 - button_width - 20
    button_start_x_right = cfg.SCREENSIZE[0] / 2 + 20
    button_start_y = cfg.SCREENSIZE[1] / 2 - button_height / 2 + 20
    pygame.draw.rect(surface, (156, 139, 125), (button_start_x_left, button_start_y, button_width, button_height))
    text_restart = font_small.render('Restart', True, font_color)
    text_restart_rect = text_restart.get_rect()
    text_restart_rect.centerx, text_restart_rect.centery = button_start_x_left + button_width / 2, button_start_y + button_height / 2
    surface.blit(text_restart, text_restart_rect)
    pygame.draw.rect(surface, (156, 139, 125), (button_start_x_right, button_start_y, button_width, button_height))
    text_quit = font_small.render('Quit', True, font_color)
    text_quit_rect = text_quit.get_rect()
    text_quit_rect.centerx, text_quit_rect.centery = button_start_x_right + button_width / 2, button_start_y + button_height / 2
    surface.blit(text_quit, text_quit_rect)

    while True:
        screen.blit(surface, (0, 0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button:
                if text_quit_rect.collidepoint(pygame.mouse.get_pos()):
                    return False
                if text_restart_rect.collidepoint(pygame.mouse.get_pos()):
                    return True

        # 刷新画面
        pygame.display.update()

github代码链接:

github代码链接

运行界面:

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值