软件价值4-俄罗斯方块

俄罗斯方块也是一个可以简单实现的游戏

代码:

import pygame
import random
import numpy as np

pygame.init()

# 游戏参数
WIDTH, HEIGHT = 300, 600
GRID_SIZE = 30
GRID_WIDTH = WIDTH // GRID_SIZE
GRID_HEIGHT = HEIGHT // GRID_SIZE
FPS = 3

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
PURPLE = (148, 0, 211)

# 俄罗斯方块形状定义
SHAPES = [
    [[1, 1, 1, 1]],

    [[0, 1, 0],
     [1, 1, 1]],

    [[1, 1, 1],
     [0, 0, 1]],

    [[1, 1, 1],
     [1, 0, 0]],

    [[1, 1],
     [1, 1]],

    [[1, 1, 0],
     [0, 1, 1]],

    [[0, 1, 1],
     [1, 1, 0]],
]


class TetrisGame:
    def __init__(self):
        self.grid = [[0] * GRID_WIDTH for _ in range(GRID_HEIGHT)]
        self.current_shape = None
        self.current_color = None
        self.current_x = 0
        self.current_y = 0
        self.score = 0
        self.game_over = False
        self.current_shape_index = 0
        self.colors = [RED, CYAN, MAGENTA, YELLOW, GREEN, BLUE, PURPLE]
        self.current_color_index = 0

    def new_shape(self):
        while True:
            self.current_shape = random.choice(SHAPES)
            self.current_shape_index = SHAPES.index(self.current_shape)
            self.current_color_index = self.current_shape_index
            self.current_color = self.colors[self.current_color_index]

            if self.current_shape is not None:
                break
        self.current_x = GRID_WIDTH // 2 - len(self.current_shape[0]) // 2
        self.current_y = 0

        return self.current_shape

    def rotate(self):
        if self.current_shape is not None:
            rotated_shape = np.rot90(self.current_shape)
            if not self.collision(rotated_shape):
                self.current_shape = rotated_shape

    def move_down(self):
        self.current_y += 1

        if self.collision():
            self.current_y -= 1
            self.freeze()
            self.clear_lines()
            if self.current_y <= 0:
                # 如果当前方块堆积到游戏区域的顶部,触发游戏结束
                self.game_over = True
            else:
                self.new_shape()

    def move_left(self):
        self.current_x -= 1
        if self.collision():
            self.current_x += 1

    def move_right(self):
        self.current_x += 1
        if self.collision():
            self.current_x -= 1

    def collision(self, shape=None):
        shape = shape if shape is not None else self.current_shape

        if shape is not None:
            for y, row in enumerate(shape):
                for x, cell in enumerate(row):
                    if cell and (
                            self.current_y + y >= GRID_HEIGHT
                            or self.current_x + x < 0
                            or self.current_x + x >= GRID_WIDTH
                            or self.grid[self.current_y + y][self.current_x + x]
                    ):
                        return True
        return False

    def freeze(self):
        for y, row in enumerate(self.current_shape):
            for x, cell in enumerate(row):
                if cell:
                    self.grid[self.current_y + y][self.current_x + x] = self.current_color

    def clear_lines(self):
        lines_to_clear = [i for i, row in enumerate(self.grid) if all(row)]
        for line in reversed(lines_to_clear):
            del self.grid[line]
            self.grid.insert(0, [0] * GRID_WIDTH)
            self.score += 10

    def draw_grid(self, surface):
        for y, row in enumerate(self.grid):
            for x, cell in enumerate(row):
                if cell:
                    pygame.draw.rect(
                        surface,
                        cell,
                        (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE),
                    )

    def draw_current_shape(self, surface):
        if self.current_shape is not None:
            for y, row in enumerate(self.current_shape):
                for x, cell in enumerate(row):
                    if cell:
                        pygame.draw.rect(
                            surface,
                            self.current_color,
                            ((self.current_x + x) * GRID_SIZE, (self.current_y + y) * GRID_SIZE, GRID_SIZE, GRID_SIZE),
                        )

    def draw_score(self, surface):
        font = pygame.font.Font(None, 36)
        score_text = font.render(f"Score: {self.score}", True, WHITE)
        surface.blit(score_text, (10, 10))

    def draw_game_over(self, surface):
        font = pygame.font.Font(None, 72)
        game_over_text = font.render("Game Over", True, WHITE)
        surface.blit(game_over_text, (WIDTH // 4, HEIGHT // 3))
        score_text = font.render(f"Score: {self.score}", True, WHITE)
        surface.blit(score_text, (WIDTH // 3, HEIGHT // 2))


def main():
    pygame.display.set_caption("Tetris")
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()
    game = TetrisGame()

    # 在循环外部创建第一个形状
    game.new_shape()

    while not game.game_over:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game.game_over = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_DOWN:
                    game.move_down()
                elif event.key == pygame.K_LEFT:
                    game.move_left()
                elif event.key == pygame.K_RIGHT:
                    game.move_right()
                elif event.key == pygame.K_UP:
                    game.rotate()

        # 移动下移移到事件处理外部
        game.move_down()

        screen.fill(BLACK)
        game.draw_grid(screen)
        game.draw_current_shape(screen)
        game.draw_score(screen)
        pygame.display.flip()

        clock.tick(FPS)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return


if __name__ == "__main__":
    main()

运行效果:

俄罗斯方块

失败截图:

软件价值4-俄罗斯方块_第1张图片

核心代码解释:

    def freeze(self):
        for y, row in enumerate(self.current_shape):
            for x, cell in enumerate(row):
                if cell:
                    self.grid[self.current_y + y][self.current_x + x] = self.current_color

这段代码位于 TetrisGame 类中的 freeze 方法中,其作用是将当前正在下落的方块 "冻结" 到游戏区域中。具体来说,它将方块的颜色信息赋值给游戏区域中对应位置的格子,从而将方块的形状固定在游戏区域中。

 

  1. for y, row in enumerate(self.current_shape):
    使用 enumerate 函数遍历当前正在下落的方块的每一行,其中 y 是行索引,row 是行的内容。

  2. for x, cell in enumerate(row):
    在每一行中,再次使用 enumerate 函数遍历该行的每个单元格,其中 x 是列索引,cell 是单元格的值。

  3. if cell:
    检查当前单元格是否包含方块的一部分,即是否为非零值。如果是,表示这个单元格是方块的一部分。

  4. self.grid[self.current_y + y][self.current_x + x] = self.current_color
    将当前方块的颜色信息 self.current_color 赋值给游戏区域中对应位置的格子。self.current_y + y 表示方块在游戏区域中的纵坐标,self.current_x + x 表示方块在游戏区域中的横坐标。self.current_x 表示当前方块左上角单元格在游戏区域中的横坐标,x是当前正在遍历的方块的一行中的相对横坐标。通过相加,可以得到方块中每个单元格在游戏区域中的绝对坐标。y也是类似。

可以改进的地方:

  • 方块可以更加立体,界面可以更加美化
  • 方块控制可以支持长按 
  • 增加音乐
  • 其它

你可能感兴趣的:(软件价值,python,游戏,俄罗斯方块,tetris)