导入模块和定义颜色
import pygame
import random
# 定义颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
这段代码导入了pygame模块用于游戏开发,同时导入了random模块用于生成随机数。接着定义了几种颜色常量,分别代表黑色、白色、红色、绿色和蓝色,这些颜色将在游戏中用于绘制不同的元素。
定义方块形状
# 定义方块形状
SHAPES = [
[[1, 1, 1, 1]],
[[1, 1], [1, 1]],
[[1, 1, 0], [0, 1, 1]],
[[0, 1, 1], [1, 1, 0]],
[[1, 1, 1], [0, 1, 0]],
[[1, 1, 1], [1, 0, 0]],
[[1, 1, 1], [0, 0, 1]]
]
这里定义了一个列表SHAPES,其中包含了七种不同的方块形状,每个形状用二维列表表示,其中1表示有方块,0表示为空。
定义方块类
# 定义方块类
class Shape:
def __init__(self):
self.shape = random.choice(SHAPES)
self.color = random.choice([RED, GREEN, BLUE])
self.x = 3
self.y = 0
这部分定义了一个Shape类,用于表示游戏中的方块。在构造函数中,随机选择一种方块形状,并随机选择一种颜色(红、绿、蓝之一)。同时,初始化方块的横坐标x为 3,纵坐标y为 0,表示方块初始位置在游戏网格的中间偏左,高度为 0。
def rotate(self):
new_shape = [list(reversed(col)) for col in zip(*self.shape)]
return Shape(new_shape, self.color)
这个方法实现了方块的旋转功能。通过对当前方块形状的矩阵进行转置和反转列操作,得到新的旋转后的形状,并返回一个新的Shape对象。
def move_down(self):
self.y -= 1
这个方法使方块向左移动一格,即减少横坐标x的值。
def move_right(self):
self.x += 1
这个方法使方块向右移动一格,即增加横坐标x的值。
初始化 Pygame 和设置屏幕尺寸
# 初始化 Pygame
pygame.init()
# 设置屏幕尺寸
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("俄罗斯方块")
# 游戏时钟
clock = pygame.time.Clock()
这部分代码首先初始化pygame库。然后设置游戏屏幕的宽度为 800 像素,高度为 600 像素,并创建一个窗口。设置窗口标题为 “俄罗斯方块”。接着创建一个游戏时钟对象,用于控制游戏的帧率。
游戏主循环
# 游戏主循环
def game_loop():
shape = Shape()
grid = [[BLACK for _ in range(10)] for _ in range(20)]
score = 0
game_over = False
定义了游戏主循环函数game_loop。在函数内部,首先创建一个初始方块对象shape,创建一个 20 行 10 列的二维列表grid表示游戏网格,初始颜色为黑色。初始化分数score为 0,设置游戏结束标志game_over为False。
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
shape.move_left()
elif event.key == pygame.K_RIGHT:
shape.move_right()
elif event.key == pygame.K_DOWN:
shape.move_down()
elif event.key == pygame.K_UP:
new_shape = shape.rotate()
if is_valid_position(new_shape, grid):
shape = new_shape
这是游戏的主循环部分,当game_over为False时持续运行。循环中遍历pygame的事件队列,如果检测到窗口关闭事件(pygame.QUIT),则设置game_over为True,结束游戏。如果检测到键盘按下事件(pygame.KEYDOWN),根据不同的按键执行相应的方块移动或旋转操作。如果按下左方向键,调用方块的move_left方法向左移动方块;按下右方向键,调用move_right方法向右移动方块;按下下方向键,调用move_down方法向下移动方块;按下上方向键,先创建一个旋转后的新方块对象new_shape,如果新方块位置合法(通过调用is_valid_position函数判断),则将当前方块更新为新旋转后的方块。
if not is_valid_position(shape, grid):
if shape.y == 0:
game_over = True
else:
place_shape(shape, grid)
clear_lines(grid, score)
shape = Shape()
如果当前方块位置不合法(通过调用is_valid_position函数判断),如果方块已经在最顶部(shape.y == 0),则设置游戏结束标志。否则,将方块放置在网格中(调用place_shape函数),检查并清除满行(调用clear_lines函数),然后创建一个新的方块对象。
draw_grid(grid, shape)
pygame.display.flip()
clock.tick(10)
调用draw_grid函数绘制游戏画面,然后使用pygame.display.flip()更新屏幕显示。最后,通过clock.tick(10)控制游戏帧率,这里设置为每秒 10 帧。
pygame.quit()
quit()
当游戏结束时,退出pygame并退出程序。
检查方块位置是否合法
# 检查方块位置是否合法
def is_valid_position(shape, grid):
for y, row in enumerate(shape.shape):
for x, cell in enumerate(row):
if cell and (shape.x + x >= 10 or shape.x + x < 0 or shape.y + y >= 20 or grid[shape.y + y][shape.x + x]!= BLACK):
return False
return True
这个函数用于检查给定方块在游戏网格中的位置是否合法。遍历方块的形状矩阵,如果方块中的某个格子为1(表示有方块),则检查该格子对应的在游戏网格中的位置是否超出边界(横坐标超出 0 到 9 的范围或纵坐标超出 0 到 19 的范围),或者该位置在游戏网格中已经被其他方块占据(不是黑色)。如果有任何不合法的情况,返回False;如果所有格子都合法,返回True。
将方块放置在网格中
# 将方块放置在网格中
def place_shape(shape, grid):
for y, row in enumerate(shape.shape):
for x, cell in enumerate(row):
if cell:
grid[shape.y + y][shape.x + x] = shape.color
这个函数将给定的方块放置在游戏网格中。遍历方块的形状矩阵,如果某个格子为1,则将该格子对应的游戏网格位置设置为方块的颜色。
清除满行并更新分数
# 清除满行并更新分数
def clear_lines(grid, score):
lines_cleared = 0
for y in range(len(grid)):
if all(cell!= BLACK for cell in grid[y]):
del grid[y]
grid.insert(0, [BLACK for _ in range(10)])
lines_cleared += 1
这个函数检查游戏网格中是否有满行,并清除满行同时更新分数。遍历游戏网格的每一行,如果一行中的所有格子都不是黑色(表示该行被方块填满),则删除该行,并在顶部插入一行黑色的空行。同时,记录清除的行数。
if lines_cleared == 1:
score += 100
elif lines_cleared == 2:
score += 300
elif lines_cleared == 3:
score += 500
elif lines_cleared == 4:
score += 800
根据清除的行数更新分数。如果清除了 1 行,分数增加 100;清除 2 行,分数增加 300;清除 3 行,分数增加 500;清除 4 行,分数增加 800。最后返回更新后的分数。
绘制游戏画面
# 绘制游戏画面
def draw_grid(grid, shape):
screen.fill(BLACK)
for y, row in enumerate(grid):
for x, cell in enumerate(row):
pygame.draw.rect(screen, cell, [x * 40, y * 40, 38, 38])
这个函数绘制游戏画面。首先用黑色填充整个屏幕。然后遍历游戏网格,对于每个非黑色的格子,在屏幕上绘制一个矩形,表示该格子中的方块。矩形的位置根据格子的坐标和每个格子的大小(40x40 像素)计算得出。
启动游戏
game_loop()
完整代码
import pygame
import random
# 定义颜色
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# 定义七种不同的方块形状,用二维列表表示
SHAPES = [
[[1, 1, 1, 1]], # 长条形状
[[1, 1], [1, 1]], # 正方形形状
[[1, 1, 0], [0, 1, 1]], # Z 字形(向左)
[[0, 1, 1], [1, 1, 0]], # Z 字形(向右)
[[1, 1, 1], [0, 1, 0]], # T 字形
[[1, 1, 1], [1, 0, 0]], # L 字形(向左)
[[1, 1, 1], [0, 0, 1]] # L 字形(向右)
]
# 定义方块类
class Shape:
def __init__(self):
# 随机选择一种形状并设置颜色,初始位置在网格中间偏左,高度为 0
self.shape = random.choice(SHAPES)
self.color = random.choice([RED, GREEN, BLUE])
self.x = 3
self.y = 0
def rotate(self):
# 实现方块的旋转,通过对形状矩阵进行转置和反转列得到新形状
new_shape = [list(reversed(col)) for col in zip(*self.shape)]
return Shape(new_shape, self.color)
def move_down(self):
# 向下移动一格
self.y += 1
def move_left(self):
# 向左移动一格
self.x -= 1
def move_right(self):
# 向右移动一格
self.x += 1
# 初始化 Pygame
pygame.init()
# 设置屏幕尺寸
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("俄罗斯方块")
# 游戏时钟,用于控制游戏帧率
clock = pygame.time.Clock()
# 游戏主循环
def game_loop():
shape = Shape()
# 创建一个 20 行 10 列的二维列表表示游戏网格,初始颜色为黑色
grid = [[BLACK for _ in range(10)] for _ in range(20)]
score = 0
game_over = False
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 窗口关闭事件,设置游戏结束标志
game_over = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
# 按下左方向键,向左移动方块
shape.move_left()
elif event.key == pygame.K_RIGHT:
# 按下右方向键,向右移动方块
shape.move_right()
elif event.key == pygame.K_DOWN:
# 按下下方向键,向下移动方块
shape.move_down()
elif event.key == pygame.K_UP:
# 按下上方向键,旋转方块
new_shape = shape.rotate()
if is_valid_position(new_shape, grid):
shape = new_shape
if not is_valid_position(shape, grid):
if shape.y == 0:
# 如果方块已经在最顶部且位置不合法,游戏结束
game_over = True
else:
# 将方块放置在网格中
place_shape(shape, grid)
# 检查并清除满行,更新分数
clear_lines(grid, score)
# 创建新的方块
shape = Shape()
# 绘制游戏画面
draw_grid(grid, shape)
pygame.display.flip()
# 控制游戏帧率
clock.tick(10)
pygame.quit()
quit()
# 检查方块位置是否合法
def is_valid_position(shape, grid):
for y, row in enumerate(shape.shape):
for x, cell in enumerate(row):
if cell and (shape.x + x >= 10 or shape.x + x < 0 or shape.y + y >= 20 or grid[shape.y + y][shape.x + x]!= BLACK):
# 如果方块超出网格边界或者与已存在的方块重叠,则位置不合法
return False
return True
# 将方块放置在网格中
def place_shape(shape, grid):
for y, row in enumerate(shape.shape):
for x, cell in enumerate(row):
if cell:
# 将方块的颜色设置到对应的网格位置
grid[shape.y + y][shape.x + x] = shape.color
# 清除满行并更新分数
def clear_lines(grid, score):
lines_cleared = 0
for y in range(len(grid)):
if all(cell!= BLACK for cell in grid[y]):
# 如果一行全是非黑色(即被方块占据),则为满行
del grid[y]
grid.insert(0, [BLACK for _ in range(10)])
lines_cleared += 1
if lines_cleared == 1:
score += 100
elif lines_cleared == 2:
score += 300
elif lines_cleared == 3:
score += 500
elif lines_cleared == 4:
score += 800
return score
# 绘制游戏画面
def draw_grid(grid, shape):
screen.fill(BLACK)
for y, row in enumerate(grid):
for x, cell in enumerate(row):
pygame.draw.rect(screen, cell, [x * 40, y * 40, 38, 38])
# 绘制网格中的每个方块
for y, row in enumerate(shape.shape):
for x, cell in enumerate(row):
if cell:
pygame.draw.rect(screen, shape.color, [(shape.x + x) * 40, (shape.y + y) * 40, 38, 38])
# 绘制当前正在下落的方块
game_loop()
4723

被折叠的 条评论
为什么被折叠?



