Skip to content
This repository was archived by the owner on Apr 24, 2025. It is now read-only.

Commit a082507

Browse files
committed
refactor original code into separate modules
1 parent 814a2e3 commit a082507

File tree

5 files changed

+157
-139
lines changed

5 files changed

+157
-139
lines changed

projects/Snake Game/constants.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from enum import Enum
2+
from collections import namedtuple
3+
4+
5+
class RgbColors:
6+
WHITE = (255, 255, 255)
7+
RED = (200, 0, 0)
8+
BLUE1 = (0, 0, 255)
9+
BLUE2 = (0, 100, 255)
10+
BLACK = (0, 0, 0)
11+
12+
13+
class GameSettings:
14+
BLOCK_SIZE = 20
15+
SPEED = 5
16+
WIDTH = 640
17+
HEIGHT = 480
18+
19+
20+
class Direction(Enum):
21+
RIGHT = 1
22+
LEFT = 2
23+
UP = 3
24+
DOWN = 4
25+
26+
27+
Point = namedtuple('Point', ['x', 'y'])

projects/Snake Game/display.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pygame
2+
from constants import RgbColors, GameSettings
3+
4+
5+
class Display:
6+
def __init__(self):
7+
pygame.init()
8+
self.width = GameSettings.WIDTH
9+
self.height = GameSettings.HEIGHT
10+
self.font = pygame.font.Font(None, 25)
11+
self.window = pygame.display.set_mode((self.width, self.height))
12+
pygame.display.set_caption("Snake")
13+
self.clock = pygame.time.Clock()
14+
15+
def update_ui(self, snake, food, score):
16+
self.window.fill(RgbColors.BLACK)
17+
# Draw snake
18+
for block in snake.blocks:
19+
pygame.draw.rect(
20+
self.window, RgbColors.BLUE1,
21+
pygame.Rect(block.x, block.y, GameSettings.BLOCK_SIZE, GameSettings.BLOCK_SIZE)
22+
)
23+
pygame.draw.rect(
24+
self.window, RgbColors.BLUE2, pygame.Rect(block.x + 4, block.y + 4, 12, 12)
25+
)
26+
# Draw food
27+
pygame.draw.rect(
28+
self.window,
29+
RgbColors.RED,
30+
pygame.Rect(food.x, food.y, GameSettings.BLOCK_SIZE, GameSettings.BLOCK_SIZE),
31+
)
32+
# Draw score
33+
score_display = self.font.render(f"Score: {score}", True, RgbColors.WHITE)
34+
self.window.blit(score_display, [0, 0]) # score in top left corner of window
35+
pygame.display.flip()
36+
37+
def clock_tick(self, speed):
38+
self.clock.tick(speed)

projects/Snake Game/game.py

Lines changed: 58 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,162 +1,81 @@
11
import pygame
22
import random
3-
from enum import Enum
4-
from collections import namedtuple
3+
from snake import Snake, Direction, Point
4+
from display import Display
5+
from constants import GameSettings
56

6-
pygame.init()
7-
font = pygame.font.Font(None, 25)
8-
9-
10-
class Direction(Enum):
11-
RIGHT = 1
12-
LEFT = 2
13-
UP = 3
14-
DOWN = 4
15-
16-
17-
Point = namedtuple("Point", "x, y")
18-
19-
# rgb colors
20-
WHITE = (255, 255, 255)
21-
RED = (200, 0, 0)
22-
BLUE1 = (0, 0, 255)
23-
BLUE2 = (0, 100, 255)
24-
BLACK = (0, 0, 0)
25-
26-
BLOCK_SIZE = 20
27-
SPEED = 5
28-
29-
30-
class SnakeGame:
31-
def __init__(self, w=640, h=480):
32-
self.w = w
33-
self.h = h
34-
# init display
35-
self.display = pygame.display.set_mode((self.w, self.h))
36-
pygame.display.set_caption("Snake")
37-
self.clock = pygame.time.Clock()
38-
39-
# init game state
40-
self.direction = Direction.RIGHT
41-
42-
self.head = Point(self.w / 2, self.h / 2)
43-
self.snake = [
44-
self.head,
45-
Point(self.head.x - BLOCK_SIZE, self.head.y),
46-
Point(self.head.x - (2 * BLOCK_SIZE), self.head.y),
47-
]
487

8+
class Game:
9+
def __init__(self):
10+
self.display = Display()
11+
self.snake = Snake()
4912
self.score = 0
5013
self.food = None
51-
self._place_food()
14+
self.place_food()
15+
16+
def game_loop(self):
17+
while True:
18+
self.play_step()
19+
game_over, score = self.play_step()
20+
if game_over:
21+
break
22+
print("Final Score:", self.score)
23+
pygame.quit()
24+
25+
def is_collision(self):
26+
# Snake hits boundary
27+
if (
28+
self.snake.head.x > self.display.width - self.snake.block_size
29+
or self.snake.head.x < 0
30+
or self.snake.head.y > self.display.height - self.snake.block_size
31+
or self.snake.head.y < 0
32+
):
33+
return True
34+
# Snake hits itself
35+
if self.snake.self_collision():
36+
return True
37+
return False
5238

53-
def _place_food(self):
54-
x = random.randint(0, (self.w - BLOCK_SIZE) // BLOCK_SIZE) * BLOCK_SIZE
55-
y = random.randint(0, (self.h - BLOCK_SIZE) // BLOCK_SIZE) * BLOCK_SIZE
56-
self.food = Point(x, y)
57-
if self.food in self.snake:
58-
self._place_food()
39+
def game_over(self):
40+
return self.is_collision()
5941

60-
def play_step(self):
61-
# 1. collect user input
42+
def get_user_input(self):
6243
for event in pygame.event.get():
6344
if event.type == pygame.QUIT:
6445
pygame.quit()
6546
quit()
6647
if event.type == pygame.KEYDOWN:
6748
if event.key == pygame.K_LEFT:
68-
self.direction = Direction.LEFT
49+
self.snake.direction = Direction.LEFT
6950
elif event.key == pygame.K_RIGHT:
70-
self.direction = Direction.RIGHT
51+
self.snake.direction = Direction.RIGHT
7152
elif event.key == pygame.K_UP:
72-
self.direction = Direction.UP
53+
self.snake.direction = Direction.UP
7354
elif event.key == pygame.K_DOWN:
74-
self.direction = Direction.DOWN
75-
76-
# 2. move
77-
self._move(self.direction) # update the head
78-
self.snake.insert(0, self.head)
55+
self.snake.direction = Direction.DOWN
7956

80-
# 3. check if game over
81-
game_over = False
82-
if self._is_collision():
83-
game_over = True
84-
return game_over, self.score
85-
86-
# 4. place new food or just move
87-
if self.head == self.food:
57+
def play_step(self):
58+
self.get_user_input()
59+
self.snake.move(self.snake.direction)
60+
if self.snake.head == self.food:
8861
self.score += 1
89-
self._place_food()
62+
self.place_food()
9063
else:
91-
self.snake.pop()
92-
93-
# 5. update ui and clock
94-
self._update_ui()
95-
self.clock.tick(SPEED)
96-
# 6. return game over and score
64+
self.snake.blocks.pop()
65+
# Update UI and Clock
66+
self.display.update_ui(self.snake, self.food, self.score)
67+
self.display.clock_tick(GameSettings.SPEED)
68+
game_over = self.is_collision()
9769
return game_over, self.score
9870

99-
def _is_collision(self):
100-
# hits boundary
101-
if (
102-
self.head.x > self.w - BLOCK_SIZE
103-
or self.head.x < 0
104-
or self.head.y > self.h - BLOCK_SIZE
105-
or self.head.y < 0
106-
):
107-
return True
108-
# hits itself
109-
if self.head in self.snake[1:]:
110-
return True
111-
112-
return False
113-
114-
def _update_ui(self):
115-
self.display.fill(BLACK)
116-
117-
for pt in self.snake:
118-
pygame.draw.rect(
119-
self.display, BLUE1, pygame.Rect(pt.x, pt.y, BLOCK_SIZE, BLOCK_SIZE)
120-
)
121-
pygame.draw.rect(
122-
self.display, BLUE2, pygame.Rect(pt.x + 4, pt.y + 4, 12, 12)
123-
)
124-
125-
pygame.draw.rect(
126-
self.display,
127-
RED,
128-
pygame.Rect(self.food.x, self.food.y, BLOCK_SIZE, BLOCK_SIZE),
129-
)
130-
131-
text = font.render("Score: " + str(self.score), True, WHITE)
132-
self.display.blit(text, [0, 0])
133-
pygame.display.flip()
134-
135-
def _move(self, direction):
136-
x = self.head.x
137-
y = self.head.y
138-
if direction == Direction.RIGHT:
139-
x += BLOCK_SIZE
140-
elif direction == Direction.LEFT:
141-
x -= BLOCK_SIZE
142-
elif direction == Direction.DOWN:
143-
y += BLOCK_SIZE
144-
elif direction == Direction.UP:
145-
y -= BLOCK_SIZE
146-
147-
self.head = Point(x, y)
148-
149-
150-
if __name__ == "__main__":
151-
game = SnakeGame()
152-
153-
# game loop
154-
while True:
155-
game_over, score = game.play_step()
156-
157-
if game_over == True:
158-
break
159-
160-
print("Final Score", score)
71+
def place_food(self):
72+
x = random.randint(0, (
73+
self.display.width - GameSettings.BLOCK_SIZE) // GameSettings.BLOCK_SIZE) * GameSettings.BLOCK_SIZE
74+
y = random.randint(0, (
75+
self.display.height - GameSettings.BLOCK_SIZE) // GameSettings.BLOCK_SIZE) * GameSettings.BLOCK_SIZE
76+
self.food = Point(x, y)
77+
if self.food in self.snake.blocks:
78+
self.place_food()
16179

162-
pygame.quit()
80+
def get_score(self):
81+
return self.score

projects/Snake Game/main.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from game import Game
2+
3+
if __name__ == "__main__":
4+
game = Game()
5+
game.game_loop()

projects/Snake Game/snake.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from constants import GameSettings, Direction, Point
2+
3+
4+
class Snake:
5+
def __init__(self, init_length=3):
6+
self.head = Point(GameSettings.WIDTH / 2, GameSettings.HEIGHT / 2)
7+
self.block_size = GameSettings.BLOCK_SIZE
8+
self.blocks = ([self.head] +
9+
[Point(self.head.x - (i * self.block_size), self.head.y) for i in range(1, init_length)])
10+
self.direction = Direction.RIGHT
11+
12+
def move(self, direction):
13+
x, y = self.head
14+
if direction == Direction.RIGHT:
15+
x += self.block_size
16+
elif direction == Direction.LEFT:
17+
x -= self.block_size
18+
elif direction == Direction.DOWN:
19+
y += self.block_size
20+
elif direction == Direction.UP:
21+
y -= self.block_size
22+
self.head = Point(x, y)
23+
self.blocks.insert(0, self.head)
24+
return self.head
25+
26+
def self_collision(self):
27+
if self.head in self.blocks[1:]:
28+
return True
29+
return False

0 commit comments

Comments
 (0)