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代碼鏈接

運行界面:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章