-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtetris.py
170 lines (148 loc) · 5.78 KB
/
tetris.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/env python3
# ========================================================================
# tetris.py
#
# Description: Tetris on the Sense HAT.
#
# Author: Jim Ing
# Date: 2024-09-23
# ========================================================================
import time
import random
from copy import deepcopy
from config import sense
# Define Tetromino shapes (4x4 matrix for each)
TETROMINOS = {
'I': [[1, 1, 1, 1]],
'O': [[1, 1], [1, 1]],
'T': [[0, 1, 0], [1, 1, 1]],
'L': [[1, 0], [1, 0], [1, 1]],
'J': [[0, 1], [0, 1], [1, 1]],
'S': [[0, 1, 1], [1, 1, 0]],
'Z': [[1, 1, 0], [0, 1, 1]]
}
# Board size (8x8 grid)
WIDTH, HEIGHT = 8, 8
# Tetromino colors
COLORS = {
'I': (0, 255, 255), # Cyan
'O': (255, 255, 0), # Yellow
'T': (128, 0, 128), # Purple
'L': (255, 165, 0), # Orange
'J': (0, 0, 255), # Blue
'S': (0, 255, 0), # Green
'Z': (255, 0, 0), # Red
}
# Initialize game board
board = [[None] * WIDTH for _ in range(HEIGHT)]
# Initialize score
score = 0
# Check if tetromino fits in the grid
def check_collision(shape, offset):
x_off, y_off = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
if (x + x_off >= WIDTH or x + x_off < 0 or
y + y_off >= HEIGHT or board[y + y_off][x + x_off]):
return True
return False
# Add tetromino to the board
def merge_tetromino(shape, offset, tetromino_type):
x_off, y_off = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
board[y + y_off][x + x_off] = tetromino_type
# Remove tetromino from board (before moving)
def remove_tetromino(shape, offset):
x_off, y_off = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
board[y + y_off][x + x_off] = None
# Rotate tetromino (90 degrees clockwise)
def rotate_tetromino(shape):
return [list(reversed(col)) for col in zip(*shape)]
# Draw only changes in the board
def draw_board():
for y, row in enumerate(board):
for x, cell in enumerate(row):
if cell:
sense.set_pixel(x, y, COLORS[cell]) # Use tetromino name for color
else:
sense.set_pixel(x, y, (0, 0, 0)) # Empty space
# Clear full lines
def clear_lines():
global score
lines_cleared = 0
new_board = [row for row in board if any(cell is None for cell in row)] # Keep only rows with empty cells
lines_cleared = HEIGHT - len(new_board)
# If any lines were cleared, add empty rows on top
if lines_cleared > 0:
new_board = [[None] * WIDTH for _ in range(lines_cleared)] + new_board
for y in range(HEIGHT):
board[y] = new_board[y]
# Update the score based on lines cleared
if lines_cleared == 1:
score += 100
elif lines_cleared == 2:
score += 300
elif lines_cleared == 3:
score += 500
elif lines_cleared == 4:
score += 800
print(f"Score: {score}") # Print the updated score
# Game over check
def check_game_over():
return any(board[0])
# Main game loop
def tetris_game():
current_tetromino = random.choice(list(TETROMINOS.keys()))
current_shape = deepcopy(TETROMINOS[current_tetromino])
current_offset = [3, 0] # Start near the top-middle of the grid
speed = 2.0 # Falling speed (adjustable)
drop_time = time.time()
while True:
# Check if it's time to drop the tetromino
if time.time() - drop_time > speed:
remove_tetromino(current_shape, current_offset)
current_offset[1] += 1 # Move down
if check_collision(current_shape, current_offset):
current_offset[1] -= 1 # Revert move if collision
merge_tetromino(current_shape, current_offset, current_tetromino)
clear_lines() # Check for cleared lines
if check_game_over():
sense.show_message("Game Over", text_colour=(255, 0, 0))
break
# Spawn new tetromino
current_tetromino = random.choice(list(TETROMINOS.keys()))
current_shape = deepcopy(TETROMINOS[current_tetromino])
current_offset = [3, 0]
else:
merge_tetromino(current_shape, current_offset, current_tetromino)
drop_time = time.time()
# Joystick controls
for event in sense.stick.get_events():
if event.action == "pressed":
remove_tetromino(current_shape, current_offset)
if event.direction == "left":
current_offset[0] -= 1 # Move left
if check_collision(current_shape, current_offset):
current_offset[0] += 1 # Revert if collision
elif event.direction == "right":
current_offset[0] += 1 # Move right
if check_collision(current_shape, current_offset):
current_offset[0] -= 1 # Revert if collision
elif event.direction == "down":
current_offset[1] += 1 # Move down faster
if check_collision(current_shape, current_offset):
current_offset[1] -= 1 # Revert if collision
elif event.direction == "up":
rotated_shape = rotate_tetromino(current_shape)
if not check_collision(rotated_shape, current_offset):
current_shape = rotated_shape # Rotate if no collision
merge_tetromino(current_shape, current_offset, current_tetromino)
draw_board() # Only update the board if there's a change
# Run the game
tetris_game()