最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用Pygame實(shí)現(xiàn)一個(gè)經(jīng)典2048數(shù)字合并游戲

 更新時(shí)間:2026年06月17日 09:15:52   作者:Wang ruoxi  
Pygame 是 Python 中一個(gè)功能強(qiáng)大的 2D 游戲開(kāi)發(fā)庫(kù),它提供了處理圖形、聲音、輸入和事件循環(huán)的完整工具集,本文通過(guò) Pygame 實(shí)現(xiàn)一個(gè)經(jīng)典 2048 數(shù)字合并游戲,需要的朋友可以參考下

項(xiàng)目概述

Pygame 是 Python 中一個(gè)功能強(qiáng)大的 2D 游戲開(kāi)發(fā)庫(kù),它提供了處理圖形、聲音、輸入和事件循環(huán)的完整工具集。本文通過(guò) Pygame 實(shí)現(xiàn)一個(gè)經(jīng)典 2048 數(shù)字合并游戲。

在這個(gè)游戲中,玩家在一個(gè) 4×4 的網(wǎng)格上滑動(dòng)所有方塊,相同數(shù)字的方塊相撞后會(huì)合并為它們的和,目標(biāo)是合成出數(shù)值為 2048 的方塊。其中:

  • 移動(dòng):使用方向鍵(↑ ↓ ← →)或 WASD 鍵控制所有方塊同時(shí)向該方向滑動(dòng);同一行/列中數(shù)值相同的相鄰方塊會(huì)合并,每次移動(dòng)后在隨機(jī)空位生成一個(gè)新方塊(90% 概率為 2,10% 概率為 4)。
  • 得分:每次合并兩個(gè)數(shù)值為 N 的方塊,得分增加 2N;分?jǐn)?shù)實(shí)時(shí)更新并記錄本局最高分。
  • 鍵盤(pán)操作:R:重新開(kāi)始游戲。
  • 勝利條件:棋盤(pán)上出現(xiàn)數(shù)值為 2048 的方塊 = 游戲勝利(勝利后可繼續(xù)挑戰(zhàn)更高數(shù)值)。
  • 失敗條件:棋盤(pán)已滿且沒(méi)有任何可合并的相鄰方塊 = 游戲失敗。

游戲?qū)崿F(xiàn)

初始化與基礎(chǔ)設(shè)置

在游戲啟動(dòng)前,需要初始化 Pygame 并定義棋盤(pán)布局、顏色方案等基礎(chǔ)參數(shù)。

pygame.init()

SIZE     = 520       # 窗口寬度(正方形)
GRID_OFF = 70        # 頂部 HUD 區(qū)域高度
COLS     = 4         # 列數(shù)(同時(shí)也是行數(shù))
GAP      = 12        # 方塊間距
TILE_W   = (SIZE - GAP * (COLS + 1)) // COLS   # 單個(gè)方塊寬度
TILE_H   = TILE_W

screen = pygame.display.set_mode((SIZE, SIZE + GRID_OFF))
pygame.display.set_caption("2048")
clock = pygame.time.Clock()

顏色與方塊樣式配置

不同數(shù)值的方塊使用獨(dú)立的背景色(bg)、前景文字色(fg)和字號(hào)(fs),數(shù)值越大顏色越深,視覺(jué)層次分明:

BG_COLOR    = (18,  14,   6)   # 全局背景(深褐黑)
GRID_COLOR  = (26,  20,   6)   # 網(wǎng)格背景
EMPTY_COLOR = (40,  30,   8)   # 空格顏色

TILE_STYLES = {
    0:    {"bg": (40,  30,   8), "fg": (40,  30,   8), "fs": 36},
    2:    {"bg": (250,199, 117), "fg": (99,  56,   6), "fs": 36},
    4:    {"bg": (239,159,  39), "fg": (65,  36,   2), "fs": 36},
    8:    {"bg": (186,117,  23), "fg": (255, 230, 180), "fs": 36},
    16:   {"bg": (133, 79,  11), "fg": (255, 220, 150), "fs": 36},
    32:   {"bg": ( 99, 56,   6), "fg": (250, 199, 117), "fs": 36},
    64:   {"bg": ( 65, 36,   2), "fg": (250, 199, 117), "fs": 36},
    128:  {"bg": ( 83, 74, 183), "fg": (238, 237, 254), "fs": 30},
    256:  {"bg": ( 60, 52, 137), "fg": (206, 203, 246), "fs": 30},
    512:  {"bg": ( 38, 33,  92), "fg": (175, 169, 236), "fs": 30},
    1024: {"bg": ( 24, 95, 165), "fg": (230, 241, 251), "fs": 24},
    2048: {"bg": (226, 75,  74), "fg": (255, 255, 255), "fs": 24},
}

字體加載函數(shù)

CHINESE_FONT_PATH = r"C:/Windows/Fonts/simsun.ttc"

font_hud = pygame.font.Font(CHINESE_FONT_PATH, 22)
font_big = pygame.font.Font(CHINESE_FONT_PATH, 48)

def get_font(size):
    return pygame.font.Font(CHINESE_FONT_PATH, size)

通過(guò)直接引用系統(tǒng)字體文件路徑來(lái)支持中文顯示。如需跨平臺(tái)兼容,可替換為 pygame.font.SysFont(None, size) 使用系統(tǒng)默認(rèn)字體。

核心函數(shù)設(shè)計(jì)

1. 網(wǎng)格操作

創(chuàng)建空網(wǎng)格 new_grid

def new_grid():
    return [[0] * COLS for _ in range(COLS)]

用二維列表表示棋盤(pán),0 代表空格。

隨機(jī)生成新方塊 add_random

def add_random(grid):
    empty = [(r, c) for r in range(COLS) for c in range(COLS) if grid[r][c] == 0]
    if not empty:
        return
    r, c = random.choice(empty)
    grid[r][c] = 4 if random.random() < 0.1 else 2

收集所有空格位置后隨機(jī)選擇一個(gè),以 10% 的概率生成 4,其余情況生成 2。

2. 核心滑動(dòng)算法

單行滑動(dòng) slide_row

def slide_row(row):
    tiles = [v for v in row if v != 0]   # 去除空格,壓縮到一側(cè)
    gained = 0
    i = 0
    while i < len(tiles) - 1:
        if tiles[i] == tiles[i + 1]:     # 相鄰相同則合并
            tiles[i] *= 2
            gained += tiles[i]
            tiles.pop(i + 1)
        i += 1
    while len(tiles) < COLS:             # 末尾補(bǔ)零
        tiles.append(0)
    return tiles, gained

該算法是 2048 的核心:

  1. 壓縮:先過(guò)濾掉所有 0,把非零數(shù)字左移緊靠。
  2. 合并:從左到右掃描,相鄰相等則合并(每個(gè)方塊每次移動(dòng)只能參與一次合并)。
  3. 補(bǔ)零:將合并后的結(jié)果右側(cè)填充 0 至原長(zhǎng)度。

四方向移動(dòng) move

def move(grid, direction):
    gained = 0
    changed = False
    g = [row[:] for row in grid]   # 深拷貝,不修改原始網(wǎng)格

    if direction == "left":
        for r in range(COLS):
            new_row, pts = slide_row(g[r])
            if new_row != g[r]:
                changed = True
            g[r] = new_row
            gained += pts

    elif direction == "right":
        for r in range(COLS):
            rev, pts = slide_row(g[r][::-1])   # 翻轉(zhuǎn)后滑動(dòng),再翻轉(zhuǎn)回來(lái)
            new_row = rev[::-1]
            if new_row != g[r]:
                changed = True
            g[r] = new_row
            gained += pts

    elif direction == "up":
        for c in range(COLS):
            col = [g[r][c] for r in range(COLS)]   # 提取列
            new_col, pts = slide_row(col)
            for r in range(COLS):
                if g[r][c] != new_col[r]:
                    changed = True
                g[r][c] = new_col[r]
            gained += pts

    elif direction == "down":
        for c in range(COLS):
            col = [g[r][c] for r in range(COLS)]
            new_col, pts = slide_row(col[::-1])     # 翻轉(zhuǎn)列后滑動(dòng),再翻轉(zhuǎn)回來(lái)
            new_col = new_col[::-1]
            for r in range(COLS):
                if g[r][c] != new_col[r]:
                    changed = True
                g[r][c] = new_col[r]
            gained += pts

    return g, gained, changed

四個(gè)方向的實(shí)現(xiàn)統(tǒng)一復(fù)用 slide_row,利用翻轉(zhuǎn)技巧避免重復(fù)邏輯:

  • 向右 = 翻轉(zhuǎn)每行 → 向左滑動(dòng) → 再翻轉(zhuǎn)。
  • 向上 = 轉(zhuǎn)置為列 → 向左滑動(dòng) → 寫(xiě)回。
  • 向下 = 轉(zhuǎn)置為列 → 翻轉(zhuǎn) → 向左滑動(dòng) → 翻轉(zhuǎn) → 寫(xiě)回。

3. 游戲狀態(tài)檢測(cè)

檢測(cè)是否還有合法移動(dòng) can_move

def can_move(grid):
    for r in range(COLS):
        for c in range(COLS):
            if grid[r][c] == 0:          # 存在空格
                return True
            if c + 1 < COLS and grid[r][c] == grid[r][c + 1]:  # 水平相鄰相等
                return True
            if r + 1 < COLS and grid[r][c] == grid[r + 1][c]:  # 垂直相鄰相等
                return True
    return False

檢測(cè)是否勝利 has_won

def has_won(grid):
    return any(grid[r][c] == 2048 for r in range(COLS) for c in range(COLS))

核心類(lèi)設(shè)計(jì)

1. 動(dòng)畫(huà)類(lèi)(AnimTile)

AnimTile 負(fù)責(zé)處理方塊出現(xiàn)和合并時(shí)的縮放彈出動(dòng)畫(huà):

class AnimTile:
    def __init__(self, value, scale=0.0):
        self.value = value
        self.scale = scale     # 當(dāng)前縮放比例,0.0 = 不可見(jiàn),1.0 = 完整大小

    def update(self):
        if self.scale < 1.0:
            self.scale = min(1.0, self.scale + 0.12)   # 每幀遞增,約 8 幀完成動(dòng)畫(huà)

新方塊初始 scale=0.0,每幀調(diào)用 update() 逐步放大到 1.0,實(shí)現(xiàn)平滑的彈出效果。

2. 游戲主類(lèi)(Game)

Game 類(lèi)是整個(gè)游戲的控制中心,負(fù)責(zé)狀態(tài)管理、事件處理、邏輯更新和渲染。

構(gòu)造函數(shù) __init__

def __init__(self):
    self.best = 0    # 最高分(跨局保留)
    self.reset()

重置游戲 reset

def reset(self):
    self.grid      = new_grid()
    self.score     = 0
    self.game_over = False
    self.won       = False
    self.anims     = [[AnimTile(0, 1.0)] * COLS for _ in range(COLS)]
    add_random(self.grid)
    add_random(self.grid)
    self._sync_anims(set())

初始放置兩個(gè)隨機(jī)方塊,并同步動(dòng)畫(huà)狀態(tài)。

同步動(dòng)畫(huà)狀態(tài) _sync_anims

def _sync_anims(self, new_cells):
    for r in range(COLS):
        for c in range(COLS):
            v = self.grid[r][c]
            if (r, c) in new_cells:
                self.anims[r][c] = AnimTile(v, 0.0)   # 新出現(xiàn)的方塊從 0 開(kāi)始動(dòng)畫(huà)
            else:
                self.anims[r][c] = AnimTile(v, 1.0)   # 已有方塊直接顯示完整大小

執(zhí)行移動(dòng) do_move

def do_move(self, direction):
    if self.game_over:
        return
    new_grid_, gained, changed = move(self.grid, direction)
    if not changed:        # 移動(dòng)無(wú)效,直接返回
        return
    self.grid   = new_grid_
    self.score += gained
    if self.score > self.best:
        self.best = self.score
    add_random(self.grid)
    self._sync_anims(set())
    if not can_move(self.grid):
        self.game_over = True
    if has_won(self.grid) and not self.won:
        self.won = True

事件處理 handle_events

def handle_events(self):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit(); sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_r:
                self.reset()
            key_dir = {
                pygame.K_LEFT:  "left",  pygame.K_a: "left",
                pygame.K_RIGHT: "right", pygame.K_d: "right",
                pygame.K_UP:    "up",    pygame.K_w: "up",
                pygame.K_DOWN:  "down",  pygame.K_s: "down",
            }
            if event.key in key_dir:
                self.do_move(key_dir[event.key])

支持方向鍵和 WASD 兩套操作方案,R 鍵重新開(kāi)始。

繪制方法 draw

def draw(self):
    screen.fill(BG_COLOR)

    # 繪制 HUD 信息欄
    pygame.draw.rect(screen, (22, 16, 5), (0, 0, SIZE, GRID_OFF))
    pygame.draw.line(screen, (80, 60, 20), (0, GRID_OFF), (SIZE, GRID_OFF), 1)
    screen.blit(font_hud.render("2048", True, (250, 199, 117)), (14, 14))
    screen.blit(font_hud.render(f"得分 {self.score}", True, WHITE), (14, 38))
    screen.blit(font_hud.render(f"最高 {self.best}",  True, GRAY),  (200, 38))
    screen.blit(font_hud.render("R=重來(lái)", True, GRAY),              (SIZE - 100, 38))

    # 繪制網(wǎng)格背景
    grid_rect = pygame.Rect(GAP - 2, GRID_OFF + GAP - 2,
                            SIZE - 2 * GAP + 4,
                            COLS * (TILE_H + GAP) + 4)
    pygame.draw.rect(screen, GRID_COLOR, grid_rect, border_radius=10)

    # 繪制每個(gè)方塊(含縮放動(dòng)畫(huà))
    for r in range(COLS):
        for c in range(COLS):
            rect  = tile_rect(r, c)
            anim  = self.anims[r][c]
            v     = self.grid[r][c]
            style = TILE_STYLES.get(v, TILE_STYLES[2048])

            pygame.draw.rect(screen, EMPTY_COLOR, rect, border_radius=6)
            if v == 0:
                continue

            sc = anim.scale
            sw, sh = int(TILE_W * sc), int(TILE_H * sc)
            sx = rect.centerx - sw // 2
            sy = rect.centery - sh // 2
            tile_surf = pygame.Surface((sw, sh), pygame.SRCALPHA)
            pygame.draw.rect(tile_surf, style["bg"], (0, 0, sw, sh),
                             border_radius=int(6 * sc))
            screen.blit(tile_surf, (sx, sy))

            if sc > 0.5:
                fnt  = get_font(style["fs"])
                text = fnt.render(str(v), True, style["fg"])
                screen.blit(text, (rect.centerx - text.get_width() // 2,
                                   rect.centery - text.get_height() // 2))

    # 游戲結(jié)束/勝利遮罩
    if self.game_over or self.won:
        overlay = pygame.Surface((SIZE, SIZE), pygame.SRCALPHA)
        overlay.fill((18, 14, 6, 185))
        screen.blit(overlay, (0, GRID_OFF))
        t1 = font_big.render("YOU WIN!" if self.won else "GAME OVER", True,
                             (250, 199, 117) if self.won else (226, 75, 74))
        t2 = font_hud.render(f"得分 {self.score}  最高 {self.best}", True, WHITE)
        t3 = font_hud.render("按 R 重新開(kāi)始", True, GRAY)
        cx = SIZE // 2
        cy = GRID_OFF + (SIZE - GRID_OFF) // 2
        screen.blit(t1, (cx - t1.get_width() // 2, cy - 60))
        screen.blit(t2, (cx - t2.get_width() // 2, cy + 10))
        screen.blit(t3, (cx - t3.get_width() // 2, cy + 46))

    pygame.display.flip()

輔助函數(shù) tile_rect

def tile_rect(row, col):
    x = GAP + col * (TILE_W + GAP)
    y = GRID_OFF + GAP + row * (TILE_H + GAP)
    return pygame.Rect(x, y, TILE_W, TILE_H)

根據(jù)行列索引計(jì)算方塊的屏幕坐標(biāo),統(tǒng)一由 GAP 控制間距。

主循環(huán) run

def run(self):
    while True:
        self.handle_events()
        self.update()
        self.draw()
        clock.tick(60)

以 60 FPS 運(yùn)行,保證動(dòng)畫(huà)流暢。

全部代碼

import pygame
import sys
import random
import copy

pygame.init()

SIZE     = 520
GRID_OFF = 70           # top HUD height
COLS     = 4
GAP      = 12
TILE_W   = (SIZE - GAP * (COLS + 1)) // COLS
TILE_H   = TILE_W

screen = pygame.display.set_mode((SIZE, SIZE + GRID_OFF))
pygame.display.set_caption("2048")
clock = pygame.time.Clock()

BG_COLOR   = (18,  14,  6)
GRID_COLOR = (26,  20,  6)
EMPTY_COLOR= (40,  30,  8)
WHITE      = (230, 225, 210)
GRAY       = (130, 120, 100)

TILE_STYLES = {
    0:    {"bg": (40,  30,   8), "fg": (40,  30,   8), "fs": 36},
    2:    {"bg": (250,199, 117), "fg": (99,  56,   6), "fs": 36},
    4:    {"bg": (239,159,  39), "fg": (65,  36,   2), "fs": 36},
    8:    {"bg": (186,117,  23), "fg": (255, 230, 180), "fs": 36},
    16:   {"bg": (133, 79,  11), "fg": (255, 220, 150), "fs": 36},
    32:   {"bg": ( 99, 56,   6), "fg": (250, 199, 117), "fs": 36},
    64:   {"bg": ( 65, 36,   2), "fg": (250, 199, 117), "fs": 36},
    128:  {"bg": ( 83, 74, 183), "fg": (238, 237, 254), "fs": 30},
    256:  {"bg": ( 60, 52, 137), "fg": (206, 203, 246), "fs": 30},
    512:  {"bg": ( 38, 33,  92), "fg": (175, 169, 236), "fs": 30},
    1024: {"bg": ( 24, 95, 165), "fg": (230, 241, 251), "fs": 24},
    2048: {"bg": (226, 75,  74), "fg": (255, 255, 255), "fs": 24},
}

CHINESE_FONT_PATH = r"C:/Windows/Fonts/simsun.ttc"
# 使用具體字體文件(如果系統(tǒng)有):
font_hud = pygame.font.Font(CHINESE_FONT_PATH, 22)
font_big = pygame.font.Font(CHINESE_FONT_PATH, 48)


def get_font(size):
    # return pygame.font.SysFont("Courier New", size, bold=True)
    return pygame.font.Font(CHINESE_FONT_PATH, size)  # 回退到默認(rèn)字體


def tile_rect(row, col):
    x = GAP + col * (TILE_W + GAP)
    y = GRID_OFF + GAP + row * (TILE_H + GAP)
    return pygame.Rect(x, y, TILE_W, TILE_H)


def new_grid():
    return [[0] * COLS for _ in range(COLS)]


def add_random(grid):
    empty = [(r, c) for r in range(COLS) for c in range(COLS) if grid[r][c] == 0]
    if not empty:
        return
    r, c = random.choice(empty)
    grid[r][c] = 4 if random.random() < 0.1 else 2


def slide_row(row):
    tiles = [v for v in row if v != 0]
    gained = 0
    i = 0
    while i < len(tiles) - 1:
        if tiles[i] == tiles[i + 1]:
            tiles[i] *= 2
            gained += tiles[i]
            tiles.pop(i + 1)
        i += 1
    while len(tiles) < COLS:
        tiles.append(0)
    return tiles, gained


def move(grid, direction):
    gained = 0
    changed = False
    g = [row[:] for row in grid]

    if direction == "left":
        for r in range(COLS):
            new_row, pts = slide_row(g[r])
            if new_row != g[r]:
                changed = True
            g[r] = new_row
            gained += pts

    elif direction == "right":
        for r in range(COLS):
            rev, pts = slide_row(g[r][::-1])
            new_row = rev[::-1]
            if new_row != g[r]:
                changed = True
            g[r] = new_row
            gained += pts

    elif direction == "up":
        for c in range(COLS):
            col = [g[r][c] for r in range(COLS)]
            new_col, pts = slide_row(col)
            for r in range(COLS):
                if g[r][c] != new_col[r]:
                    changed = True
                g[r][c] = new_col[r]
            gained += pts

    elif direction == "down":
        for c in range(COLS):
            col = [g[r][c] for r in range(COLS)]
            new_col, pts = slide_row(col[::-1])
            new_col = new_col[::-1]
            for r in range(COLS):
                if g[r][c] != new_col[r]:
                    changed = True
                g[r][c] = new_col[r]
            gained += pts

    return g, gained, changed


def can_move(grid):
    for r in range(COLS):
        for c in range(COLS):
            if grid[r][c] == 0:
                return True
            if c + 1 < COLS and grid[r][c] == grid[r][c + 1]:
                return True
            if r + 1 < COLS and grid[r][c] == grid[r + 1][c]:
                return True
    return False


def has_won(grid):
    return any(grid[r][c] == 2048 for r in range(COLS) for c in range(COLS))


class AnimTile:
    """Handles scale-pop animation when a tile appears / merges."""
    def __init__(self, value, scale=0.0):
        self.value = value
        self.scale = scale          # 0..1

    def update(self):
        if self.scale < 1.0:
            self.scale = min(1.0, self.scale + 0.12)


class Game:
    def __init__(self):
        self.best = 0
        self.reset()

    def reset(self):
        self.grid      = new_grid()
        self.score     = 0
        self.game_over = False
        self.won       = False
        self.anims     = [[AnimTile(0, 1.0)] * COLS for _ in range(COLS)]
        add_random(self.grid); add_random(self.grid)
        self._sync_anims(set())

    def _sync_anims(self, new_cells):
        for r in range(COLS):
            for c in range(COLS):
                v = self.grid[r][c]
                if (r, c) in new_cells:
                    self.anims[r][c] = AnimTile(v, 0.0)
                else:
                    self.anims[r][c] = AnimTile(v, 1.0)

    def do_move(self, direction):
        if self.game_over:
            return
        new_grid_, gained, changed = move(self.grid, direction)
        if not changed:
            return
        self.grid   = new_grid_
        self.score += gained
        if self.score > self.best:
            self.best = self.score
        new_cells = set()
        add_random(self.grid)
        # mark newly appeared cell for animation
        for r in range(COLS):
            for c in range(COLS):
                if self.grid[r][c] != 0 and (gained > 0 or self.anims[r][c].value == 0):
                    pass
        # simple: animate all cells
        self._sync_anims(set())
        if not can_move(self.grid):
            self.game_over = True
        if has_won(self.grid) and not self.won:
            self.won = True

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    self.reset()
                key_dir = {
                    pygame.K_LEFT:  "left",  pygame.K_a: "left",
                    pygame.K_RIGHT: "right", pygame.K_d: "right",
                    pygame.K_UP:    "up",    pygame.K_w: "up",
                    pygame.K_DOWN:  "down",  pygame.K_s: "down",
                }
                if event.key in key_dir:
                    self.do_move(key_dir[event.key])

    def update(self):
        for r in range(COLS):
            for c in range(COLS):
                self.anims[r][c].update()

    def draw(self):
        screen.fill(BG_COLOR)

        # --- HUD ---
        pygame.draw.rect(screen, (22, 16, 5), (0, 0, SIZE, GRID_OFF))
        pygame.draw.line(screen, (80, 60, 20), (0, GRID_OFF), (SIZE, GRID_OFF), 1)
        screen.blit(font_hud.render("2048", True, (250, 199, 117)), (14, 14))
        screen.blit(font_hud.render(f"得分 {self.score}", True, WHITE),  (14, 38))
        screen.blit(font_hud.render(f"最高 {self.best}",  True, GRAY),   (200, 38))
        screen.blit(font_hud.render("R=重來(lái)", True, GRAY),               (SIZE - 100, 38))

        # --- Grid background ---
        grid_rect = pygame.Rect(GAP - 2, GRID_OFF + GAP - 2,
                                SIZE - 2 * GAP + 4,
                                COLS * (TILE_H + GAP) + 4)
        pygame.draw.rect(screen, GRID_COLOR, grid_rect, border_radius=10)

        # --- Tiles ---
        for r in range(COLS):
            for c in range(COLS):
                rect = tile_rect(r, c)
                anim = self.anims[r][c]
                v = self.grid[r][c]
                style = TILE_STYLES.get(v, TILE_STYLES[2048])

                # empty slot
                pygame.draw.rect(screen, EMPTY_COLOR, rect, border_radius=6)
                if v == 0:
                    continue

                # scale-pop effect
                sc = anim.scale
                sw = int(TILE_W * sc)
                sh = int(TILE_H * sc)
                sx = rect.centerx - sw // 2
                sy = rect.centery - sh // 2
                tile_surf = pygame.Surface((sw, sh), pygame.SRCALPHA)
                pygame.draw.rect(tile_surf, style["bg"],
                                 (0, 0, sw, sh), border_radius=int(6 * sc))
                screen.blit(tile_surf, (sx, sy))

                # number
                if sc > 0.5:
                    fs   = style["fs"]
                    fnt  = get_font(fs)
                    text = fnt.render(str(v), True, style["fg"])
                    screen.blit(text, (rect.centerx - text.get_width() // 2,
                                       rect.centery - text.get_height() // 2))

        # --- Game over / Win overlay ---
        if self.game_over or self.won:
            overlay = pygame.Surface((SIZE, SIZE + GRID_OFF - GRID_OFF), pygame.SRCALPHA)
            overlay.fill((18, 14, 6, 185))
            screen.blit(overlay, (0, GRID_OFF))
            if self.won:
                t1 = font_big.render("YOU WIN!", True, (250, 199, 117))
            else:
                t1 = font_big.render("GAME OVER", True, (226, 75, 74))
            t2 = font_hud.render(f"得分 {self.score}  最高 {self.best}", True, WHITE)
            t3 = font_hud.render("按 R 重新開(kāi)始", True, GRAY)
            cx = SIZE // 2
            cy = GRID_OFF + (SIZE - GRID_OFF) // 2
            screen.blit(t1, (cx - t1.get_width() // 2, cy - 60))
            screen.blit(t2, (cx - t2.get_width() // 2, cy + 10))
            screen.blit(t3, (cx - t3.get_width() // 2, cy + 46))

        pygame.display.flip()

    def run(self):
        while True:
            self.handle_events()
            self.update()
            self.draw()
            clock.tick(60)


if __name__ == "__main__":
    Game().run()

以上就是Python使用Pygame實(shí)現(xiàn)一個(gè)經(jīng)典2048數(shù)字合并游戲的詳細(xì)內(nèi)容,更多關(guān)于Python Pygame 2048數(shù)字合并游戲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Python3序列賦值、序列解包

    詳解Python3序列賦值、序列解包

    這篇文章主要介紹了Python3序列賦值、序列解包的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • python?memory_profiler庫(kù)生成器和迭代器內(nèi)存占用的時(shí)間分析

    python?memory_profiler庫(kù)生成器和迭代器內(nèi)存占用的時(shí)間分析

    這篇文章主要介紹了python?memory_profiler庫(kù)生成器和迭代器內(nèi)存占用的時(shí)間分析,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,感興趣的小伙伴可以參考一下
    2022-06-06
  • python PIL模塊與隨機(jī)生成中文驗(yàn)證碼

    python PIL模塊與隨機(jī)生成中文驗(yàn)證碼

    今天我們要學(xué)習(xí)的內(nèi)容是如何利用Python生成一個(gè)隨機(jī)的中文驗(yàn)證碼,并將圖片保存為.jpeg格式,需要的朋友可以參考下
    2016-02-02
  • Python中requests、aiohttp、httpx性能比拼

    Python中requests、aiohttp、httpx性能比拼

    本文主要介紹了Python中requests、aiohttp、httpx性能比拼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 通過(guò)python的matplotlib包將Tensorflow數(shù)據(jù)進(jìn)行可視化的方法

    通過(guò)python的matplotlib包將Tensorflow數(shù)據(jù)進(jìn)行可視化的方法

    今天小編就為大家分享一篇通過(guò)python的matplotlib包將Tensorflow數(shù)據(jù)進(jìn)行可視化的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • python利用正則表達(dá)式搜索單詞示例代碼

    python利用正則表達(dá)式搜索單詞示例代碼

    正則表達(dá)式本身是一種小型的、高度專(zhuān)業(yè)化的編程語(yǔ)言,下面這篇文章主要給大家介紹了關(guān)于python利用正則表達(dá)式實(shí)現(xiàn)搜索單詞的相關(guān)資料,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-09-09
  • Python詳解argparse參數(shù)模塊之命令行參數(shù)

    Python詳解argparse參數(shù)模塊之命令行參數(shù)

    這篇文章主要介紹了Python詳解argparse參數(shù)模塊之命令行參數(shù),文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考下面文章詳解
    2022-07-07
  • Python使用Matplotlib庫(kù)創(chuàng)建3D 圖形和交互式圖形詳解

    Python使用Matplotlib庫(kù)創(chuàng)建3D 圖形和交互式圖形詳解

    Matplotlib 是 Python 中最重要的數(shù)據(jù)可視化庫(kù)之一,在本文中,我們將深入研究 Matplotlib 的高級(jí)特性,特別是如何創(chuàng)建 3D 圖形和交互式圖形,需要的朋友可以參考下
    2023-07-07
  • Python控制線程和函數(shù)超時(shí)處理

    Python控制線程和函數(shù)超時(shí)處理

    這篇文章主要介紹了Python控制線程和函數(shù)超時(shí)處理,文中利用兩種方法進(jìn)行eventlet庫(kù)和@func_set_timeout修飾器,文章具體詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-06-06
  • Python中使用threading.Event協(xié)調(diào)線程的運(yùn)行詳解

    Python中使用threading.Event協(xié)調(diào)線程的運(yùn)行詳解

    這篇文章主要介紹了Python中使用threading.Event協(xié)調(diào)線程的運(yùn)行詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05

最新評(píng)論

宾阳县| 邹城市| 许昌县| 长治市| 吉林市| 凉城县| 景宁| 共和县| 镇远县| 郁南县| 平南县| 昌乐县| 定州市| 景宁| 普兰县| 神木县| 深圳市| 通化县| 龙里县| 宁德市| 大化| 五指山市| 襄樊市| 阿尔山市| 新巴尔虎左旗| 阳曲县| 大邑县| 乡宁县| 镇平县| 历史| 沙坪坝区| 偏关县| 商城县| 安宁市| 大名县| 隆回县| 元谋县| 承德县| 龙山县| 息烽县| 视频|