python小游戏之俄罗斯方块,供消遣娱乐:

import tkinter as tk
import random
# 游戏参数
CELL_SIZE = 30
COLS = 12
ROWS = 20
COLORS = ['#000000', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF']
SHAPES = {
'I': [(0, -1), (0, 0), (0, 1), (0, 2)],
'O': [(-1, 0), (0, 0), (-1, 1), (0, 1)],
'T': [(-1, 0), (0, 0), (1, 0), (0, 1)],
'S': [(-1, 0), (0, 0), (0, 1), (1, 1)],
'Z': [(-1, 1), (0, 1), (0, 0), (1, 0)],
'J': [(-1, -1), (-1, 0), (0, 0), (1, 0)],
'L': [(1, -1), (-1, 0), (0, 0), (1, 0)]
}
class Tetris:
def __init__(self):
self.win = tk.Tk()
self.canvas = tk.Canvas(self.win, width=COLS*CELL_SIZE, height=ROWS*CELL_SIZE)
self.canvas.pack()
self.board = [[0]*COLS for _ in range(ROWS)]
self.current_piece = self.new_piece()
self.score = 0
self.game_over = False
# 绑定键盘事件
self.win.bind('<Left>', lambda e: self.move(-1))
self.win.bind('<Right>', lambda e: self.move(1))
self.win.bind('<Down>', lambda e: self.move_down())
self.win.bind('<Up>', lambda e: self.rotate())
self.win.bind('<space>', lambda e: self.drop())
self.draw_board()
self.update()
self.win.mainloop()
def new_piece(self):
shape = random.choice(list(SHAPES.keys()))
return {
'shape': shape,
'cells': SHAPES[shape],
'x': COLS//2,
'y': 0,
'color': random.randint(1, len(COLORS)-1)
}
def draw_cell(self, x, y, color):
x1 = x * CELL_SIZE
y1 = y * CELL_SIZE
x2 = x1 + CELL_SIZE
y2 = y1 + CELL_SIZE
self.canvas.create_rectangle(x1, y1, x2, y2, fill=COLORS[color], outline='white')
def draw_board(self):
self.canvas.delete('all')
for y in range(ROWS):
for x in range(COLS):
if self.board[y][x]:
self.draw_cell(x, y, self.board[y][x])
for (dx, dy) in self.current_piece['cells']:
x = self.current_piece['x'] + dx
y = self.current_piece['y'] + dy
if 0 <= x < COLS and 0 <= y < ROWS:
self.draw_cell(x, y, self.current_piece['color'])
def valid_move(self, dx=0, dy=0, rotation=0):
new_cells = [(dy + dx*cell[1], dx - dy*cell[0])
for cell in self.current_piece['cells']] if rotation else self.current_piece['cells']
for (cx, cy) in new_cells:
x = self.current_piece['x'] + cx + dx
y = self.current_piece['y'] + cy + dy
if x < 0 or x >= COLS or y >= ROWS or (y >=0 and self.board[y][x]):
return False
return True
def move(self, dx):
if not self.game_over and self.valid_move(dx=dx):
self.current_piece['x'] += dx
self.draw_board()
def move_down(self):
if not self.game_over and self.valid_move(dy=1):
self.current_piece['y'] += 1
self.draw_board()
else:
self.merge_piece()
def rotate(self):
if self.valid_move(rotation=1):
self.current_piece['cells'] = [(-cell[1], cell[0])
for cell in self.current_piece['cells']]
self.draw_board()
def drop(self):
while self.valid_move(dy=1):
self.current_piece['y'] += 1
self.merge_piece()
def merge_piece(self):
for (dx, dy) in self.current_piece['cells']:
x = self.current_piece['x'] + dx
y = self.current_piece['y'] + dy
if y >= 0:
self.board[y][x] = self.current_piece['color']
self.clear_lines()
self.current_piece = self.new_piece()
if not self.valid_move():
self.game_over = True
self.canvas.create_text(COLS*CELL_SIZE//2, ROWS*CELL_SIZE//2,
text=f"Game Over! Score: {self.score}", fill="red", font=('Arial', 20))
def clear_lines(self):
lines = 0
for y in range(ROWS-1, -1, -1):
if 0 not in self.board[y]:
del self.board[y]
self.board.insert(0, [0]*COLS)
lines += 1
self.score += lines**2 * 100
def update(self):
if not self.game_over:
self.move_down()
self.win.after(800, self.update)
if __name__ == "__main__":
Tetris()