import pygame
import random
pygame.init()
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
GAP_LEFT = 30
GAP_TOP = 30
SCREEN_WIDTH = GAP_LEFT + GRID_WIDTH * BLOCK_SIZE + 200
SCREEN_HEIGHT = GAP_TOP + GRID_HEIGHT * BLOCK_SIZE + 50
COLORS = [
(0, 0, 0),
(0, 255, 255),
(255, 255, 0),
(128, 0, 128),
(255, 165, 0),
(0, 0, 255),
(255, 0, 0),
(0, 255, 0)
]
SHAPES = [
[[(-1, 0), (0, 0), (1, 0), (2, 0)],
[(0, -1), (0, 0), (0, 1), (0, 2)]],
[[(0, 0), (1, 0), (0, 1), (1, 1)]],
[[(-1, 0), (0, 0), (1, 0), (0, 1)],
[(0, -1), (0, 0), (0, 1), (-1, 0)],
[(-1, 0), (0, 0), (1, 0), (0, -1)],
[(0, -1), (0, 0), (0, 1), (1, 0)]],
[[(-1, 0), (0, 0), (1, 0), (1, 1)],
[(0, -1), (0, 0), (0, 1), (-1, 1)],
[(-1, -1), (-1, 0), (0, 0), (1, 0)],
[(0, -1), (0, 0), (0, 1), (1, -1)]],
[[(-1, 0), (0, 0), (1, 0), (-1, 1)],
[(0, -1), (0, 0), (0, 1), (-1, -1)],
[(-1, 0), (0, 0), (1, 0), (1, -1)],
[(0, -1), (0, 0), (0, 1), (1, 1)]],
[[(-1, 0), (0, 0), (0, 1), (1, 1)],
[(0, -1), (0, 0), (-1, 0), (-1, 1)]],
[[(-1, 1), (0, 1), (0, 0), (1, 0)],
[(1, -1), (1, 0), (0, 0), (0, 1)]]
]
SHAPE_ROTATIONS = [2, 1, 4, 4, 4, 2, 2]
class Piece:
def __init__(self, shape_type):
self.shape_type = shape_type
self.rotation = 0
self.x = GRID_WIDTH // 2
self.y = 0
def get_blocks(self):
shape_group = SHAPES[self.shape_type]
rotation = self.rotation % SHAPE_ROTATIONS[self.shape_type]
return [(self.x + dx, self.y + dy) for (dx, dy) in shape_group[rotation]]
def is_collision(grid, piece):
for (x, y) in piece.get_blocks():
if x < 0 or x >= GRID_WIDTH:
return True
if y >= GRID_HEIGHT:
return True
if y >= 0 and grid[y][x]:
return True
return False
def merge_piece(grid, piece):
for (x, y) in piece.get_blocks():
if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT:
grid[y][x] = piece.shape_type + 1
def clear_lines(grid):
lines_cleared = 0
y = GRID_HEIGHT - 1
while y >= 0:
if all(grid[y]):
del grid[y]
grid.insert(0, [0]*GRID_WIDTH)
lines_cleared += 1
else:
y -= 1
return lines_cleared
def draw_piece(screen, piece):
color = COLORS[piece.shape_type + 1]
for (x, y) in piece.get_blocks():
if y >= 0:
pygame.draw.rect(screen, color,
(GAP_LEFT + x*BLOCK_SIZE,
GAP_TOP + y*BLOCK_SIZE,
BLOCK_SIZE-1, BLOCK_SIZE-1))
def draw_grid(screen, grid):
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
color_idx = grid[y][x]
if color_idx:
pygame.draw.rect(screen, COLORS[color_idx],
(GAP_LEFT + x*BLOCK_SIZE,
GAP_TOP + y*BLOCK_SIZE,
BLOCK_SIZE-1, BLOCK_SIZE-1))
def main():
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("俄罗斯方块")
clock = pygame.time.Clock()
grid = [[0]*GRID_WIDTH for _ in range(GRID_HEIGHT)]
current_piece = Piece(random.randint(0, 6))
next_piece = Piece(random.randint(0, 6))
fall_time = 0
fall_speed = 500
running = True
game_over = False
while running:
screen.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if game_over:
continue
if event.key == pygame.K_LEFT:
current_piece.x -= 1
if is_collision(grid, current_piece):
current_piece.x += 1
elif event.key == pygame.K_RIGHT:
current_piece.x += 1
if is_collision(grid, current_piece):
current_piece.x -= 1
elif event.key == pygame.K_DOWN:
current_piece.y += 1
if is_collision(grid, current_piece):
current_piece.y -= 1
merge_piece(grid, current_piece)
clear_lines(grid)
current_piece = next_piece
next_piece = Piece(random.randint(0, 6))
if is_collision(grid, current_piece):
game_over = True
elif event.key == pygame.K_UP:
original_rotation = current_piece.rotation
current_piece.rotation += 1
if is_collision(grid, current_piece):
current_piece.rotation = original_rotation
if not game_over:
fall_time += clock.get_rawtime()
if fall_time >= fall_speed:
fall_time = 0
current_piece.y += 1
if is_collision(grid, current_piece):
current_piece.y -= 1
merge_piece(grid, current_piece)
clear_lines(grid)
current_piece = next_piece
next_piece = Piece(random.randint(0, 6))
if is_collision(grid, current_piece):
game_over = True
draw_grid(screen, grid)
if not game_over:
draw_piece(screen, current_piece)
if game_over:
font = pygame.font.SysFont('arial', 48)
text = font.render('Game Over', True, (255, 0, 0))
screen.blit(text, (SCREEN_WIDTH//2 - text.get_width()//2,
SCREEN_HEIGHT//2 - text.get_height()//2))
pygame.display.update()
clock.tick(60)
pygame.quit()
if __name__ == "__main__":
main()