[Python] 纯文本查看 复制代码
import pygame
import random
import sys
# 初始化pygame
pygame.init()
# ------ 游戏参数 ------
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600
BLOCK_SIZE = 30 # 每个方块大小
GRID_WIDTH, GRID_HEIGHT = SCREEN_WIDTH // BLOCK_SIZE, SCREEN_HEIGHT // BLOCK_SIZE
# 颜色定义
BLACK = (0, 0, 0)
GRAY = (128, 128, 128)
WHITE = (255, 255, 255)
COLORS = [
(0, 255, 255), # I - 青色
(0, 0, 255), # J - 蓝色
(255, 165, 0), # L - 橙色
(255, 255, 0), # O - 黄色
(0, 255, 0), # S - 绿色
(128, 0, 128), # T - 紫色
(255, 0, 0) # Z - 红色
]
# 7种方块形状,使用二维列表(1表示方块)
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 0, 0], [1, 1, 1]], # J
[[0, 0, 1], [1, 1, 1]], # L
[[1, 1], [1, 1]], # O
[[0, 1, 1], [1, 1, 0]], # S
[[0, 1, 0], [1, 1, 1]], # T
[[1, 1, 0], [0, 1, 1]] # Z
]
# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("俄罗斯方块")
clock = pygame.time.Clock()
# 创建空网格
def create_grid(locked_positions={}):
grid = [[BLACK for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
for (x, y), color in locked_positions.items():
if y >= 0:
grid[y][x] = color
return grid
# 画网格线
def draw_grid(surface):
for y in range(GRID_HEIGHT):
pygame.draw.line(surface, GRAY, (0, y * BLOCK_SIZE),
(SCREEN_WIDTH, y * BLOCK_SIZE))
for x in range(GRID_WIDTH):
pygame.draw.line(surface, GRAY, (x * BLOCK_SIZE, 0),
(x * BLOCK_SIZE, SCREEN_HEIGHT))
# 画窗口内容
def draw_window(surface, grid, score=0):
surface.fill(BLACK)
# 画所有方块
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
color = grid[y][x]
if color != BLACK:
pygame.draw.rect(surface, color, (x*BLOCK_SIZE,
y*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
draw_grid(surface)
# 显示分数
font = pygame.font.SysFont('comicsans', 30)
score_text = font.render(f"分数: {score}", True, WHITE)
surface.blit(score_text, (10, 10))
pygame.display.update()
# 方块类
class Piece:
def __init__(self, x, y, shape_idx):
self.x = x
self.y = y
self.shape_idx = shape_idx
self.shape = SHAPES[shape_idx]
self.color = COLORS[shape_idx]
self.rotation = 0
def get_shape(self):
# 根据旋转返回当前形状
shape = self.shape
for _ in range(self.rotation % 4):
shape = [list(row) for row in zip(*shape[::-1])] # 顺时针旋转90度
return shape
def positions(self):
positions = []
shape = self.get_shape()
for i, row in enumerate(shape):
for j, val in enumerate(row):
if val:
positions.append((self.x + j, self.y + i))
return positions
# 检查方块位置是否有效
def valid_space(piece, grid):
accepted_positions = [[(x, y) for x in range(
GRID_WIDTH) if grid[y][x] == BLACK] for y in range(GRID_HEIGHT)]
accepted_positions = [pos for sub in accepted_positions for pos in sub]
for pos in piece.positions():
if pos not in accepted_positions:
if pos[1] >= 0:
return False
return True
# 检查是否游戏结束
def check_lost(locked_positions):
for (x, y) in locked_positions:
if y < 1:
return True
return False
# 消除满行
def clear_rows(grid, locked):
cleared = 0
for y in range(GRID_HEIGHT-1, -1, -1):
if BLACK not in grid[y]:
cleared += 1
# 删除该行所有锁定方块
for x in range(GRID_WIDTH):
try:
del locked[(x, y)]
except:
pass
# 向上移动所有锁定方块
keys = sorted(locked.keys(), key=lambda k: k[1])
for key in keys[::-1]:
x, y2 = key
if y2 < y:
locked[(x, y2 + 1)] = locked.pop(key)
return cleared
def main():
locked_positions = {}
grid = create_grid(locked_positions)
current_piece = Piece(GRID_WIDTH//2 - 2, 0,
random.randint(0, len(SHAPES)-1))
next_piece = Piece(GRID_WIDTH//2 - 2, 0, random.randint(0, len(SHAPES)-1))
fall_time = 0
fall_speed = 0.5
score = 0
run = True
while run:
grid = create_grid(locked_positions)
fall_time += clock.get_rawtime()
clock.tick()
# 自动下落
if fall_time / 1000 >= fall_speed:
fall_time = 0
current_piece.y += 1
if not valid_space(current_piece, grid):
current_piece.y -= 1
# 固定方块
for pos in current_piece.positions():
locked_positions[pos] = current_piece.color
current_piece = next_piece
next_piece = Piece(GRID_WIDTH//2 - 2, 0,
random.randint(0, len(SHAPES)-1))
# 清除满行
cleared = clear_rows(grid, locked_positions)
if cleared > 0:
score += cleared * 10
if check_lost(locked_positions):
run = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
current_piece.x -= 1
if not valid_space(current_piece, grid):
current_piece.x += 1
elif event.key == pygame.K_RIGHT:
current_piece.x += 1
if not valid_space(current_piece, grid):
current_piece.x -= 1
elif event.key == pygame.K_DOWN:
current_piece.y += 1
if not valid_space(current_piece, grid):
current_piece.y -= 1
elif event.key == pygame.K_UP:
current_piece.rotation = (current_piece.rotation + 1) % 4
if not valid_space(current_piece, grid):
current_piece.rotation = (
current_piece.rotation - 1) % 4
elif event.key == pygame.K_SPACE:
# 直接硬下落
while valid_space(current_piece, grid):
current_piece.y += 1
current_piece.y -= 1
# 在网格上画当前方块
for pos in current_piece.positions():
x, y = pos
if y >= 0:
grid[y][x] = current_piece.color
draw_window(screen, grid, score)
# 游戏结束
screen.fill(BLACK)
font = pygame.font.SysFont('comicsans', 40)
text = font.render("游戏结束!分数: " + str(score), True, WHITE)
screen.blit(text, (SCREEN_WIDTH//2 - text.get_width() //
2, SCREEN_HEIGHT//2 - text.get_height()//2))
pygame.display.update()
pygame.time.wait(3000)
pygame.quit()
if __name__ == "__main__":
main()