PyGame-俄罗斯方块
难度:⭐⭐⭐⭐
1. 题目描述
题目描述
使用 Pygame
库实现俄罗斯方块
2. 关键点
- pygame 的使用;运行
pip install pygame
进行安装 - 方块形状的定义
3. 代码实现
点击显示代码
python
import pygame
import random
# 方块颜色
colors = [
(0, 240, 240),
(240, 0, 0),
(0, 240, 0),
(0, 0, 240),
(240, 160, 0),
(160, 0, 240),
(240, 240, 0),
]
class Figure:
"""方块类"""
x = 0
y = 0
# 方块形状
figures = [
[[1, 5, 9, 13], [4, 5, 6, 7]],
[[4, 5, 9, 10], [2, 6, 5, 9]],
[[6, 7, 9, 10], [1, 5, 6, 10]],
[[1, 2, 5, 9], [0, 4, 5, 6], [1, 5, 9, 8], [4, 5, 6, 10]],
[[1, 2, 6, 10], [5, 6, 7, 9], [2, 6, 10, 11], [3, 5, 6, 7]],
[[1, 4, 5, 6], [1, 4, 5, 9], [4, 5, 6, 9], [1, 5, 6, 9]],
[[1, 2, 5, 6]],
]
def __init__(self, x, y):
self.x = x
self.y = y
self.type = random.randint(0, len(self.figures) - 1)
self.color = random.randint(1, len(colors) - 1)
self.rotation = 0
def image(self):
return self.figures[self.type][self.rotation]
def rotate(self):
self.rotation = (self.rotation + 1) % len(self.figures[self.type])
class Tetris:
level = 2
x = y = 0
zoom = 30 # 方块大小
figure = None
def __init__(self, height, width):
self.height = height
self.width = width
self.field = []
self.state = "start"
for i in range(height):
new_line = []
for j in range(width):
new_line.append(0)
self.field.append(new_line)
def new_figure(self):
self.figure = Figure(3, 0)
def intersects(self):
"""判断是否到底"""
intersection = False
for i in range(4):
for j in range(4):
if i * 4 + j in self.figure.image():
if i + self.figure.y > self.height - 1 or \
j + self.figure.x > self.width - 1 or \
j + self.figure.x < 0 or \
self.field[i + self.figure.y][
j + self.figure.x] > 0:
intersection = True
return intersection
def break_lines(self):
"""消除"""
lines = 0
for i in range(1, self.height):
zeros = 0
for j in range(self.width):
if self.field[i][j] == 0:
zeros += 1
if zeros == 0:
lines += 1
for i1 in range(i, 1, -1):
for j in range(self.width):
self.field[i1][j] = self.field[i1 - 1][j]
def go_space(self):
"""一键落下"""
while not self.intersects():
self.figure.y += 1
self.figure.y -= 1
self.freeze()
def go_down(self):
self.figure.y += 1
if self.intersects():
self.figure.y -= 1
self.freeze()
def freeze(self):
"""触底之后留住方块"""
for i in range(4):
for j in range(4):
if i * 4 + j in self.figure.image():
self.field[i + self.figure.y][j + self.figure.x] \
= self.figure.color
self.break_lines()
self.new_figure()
if self.intersects():
self.state = "gameover"
def go_side(self, dx):
old_x = self.figure.x
self.figure.x += dx
if self.intersects():
self.figure.x = old_x
def rotate(self):
old_rotation = self.figure.rotation
self.figure.rotate()
if self.intersects():
self.figure.rotation = old_rotation
pygame.init()
screen_width = 12
screen_height = 20
screen_color = (0, 0, 0)
size = (
screen_width*Tetris.zoom+Tetris.x*2,
screen_height*Tetris.zoom+Tetris.y*2
)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("俄罗斯方块")
# Loop until the user clicks the close button.
done = False
clock = pygame.time.Clock()
fps = 25
game = Tetris(screen_height, screen_width)
counter = 0
pressing_down = False
while not done:
if game.figure is None:
game.new_figure()
counter += 1
if counter > 100000:
counter = 0
if counter % (fps // game.level // 2) == 0 or pressing_down:
if game.state == "start":
game.go_down()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
game.rotate()
if event.key == pygame.K_DOWN:
pressing_down = True
if event.key == pygame.K_LEFT:
game.go_side(-1)
if event.key == pygame.K_RIGHT:
game.go_side(1)
if event.key == pygame.K_SPACE:
game.go_space()
if event.key == pygame.K_ESCAPE:
game.__init__(screen_height, screen_width)
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
pressing_down = False
screen.fill(screen_color)
for i in range(game.height):
for j in range(game.width):
if game.field[i][j] > 0:
pygame.draw.rect(screen, colors[game.field[i][j]], [
game.x + game.zoom * j + 1,
game.y + game.zoom * i + 1, game.zoom - 2, game.zoom - 1])
if game.figure is not None:
for i in range(4):
for j in range(4):
p = i * 4 + j
if p in game.figure.image():
pygame.draw.rect(screen, colors[game.figure.color], [
game.x + game.zoom * (j + game.figure.x) + 1,
game.y + game.zoom * (i + game.figure.y) + 1,
game.zoom - 2, game.zoom - 2])
if game.state == "gameover":
done = True
pygame.display.flip()
clock.tick(fps)
pygame.quit()
4. 运行示例
5. 进阶思考
- 按住左右键的时候可连续移动
- 记录分数