Skip to content

Commit b045dd8

Browse files
committed
fix programme start and add entity parent class
1 parent 9badc70 commit b045dd8

File tree

5 files changed

+96
-63
lines changed

5 files changed

+96
-63
lines changed

api/entity/apple.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from enum import Enum
2+
from api.entity.entity import Entity
23

34

45
class AppleType(Enum):
@@ -13,21 +14,24 @@ class AppleType(Enum):
1314
GREEN = 1
1415

1516

16-
class Apple:
17+
class Apple(Entity):
1718
"""
1819
Represents an apple in the game, which can be either red or green.
1920
2021
Attributes:
2122
apple_type (AppleType): The type of the apple (RED or GREEN).
2223
"""
2324

24-
def __init__(self, apple_type: AppleType):
25+
def __init__(self, x: int, y: int, apple_type: AppleType):
2526
"""
26-
Initializes an apple with a specified type.
27+
Initializes an apple with a specified type and position.
2728
2829
Args:
30+
x (int): The x-coordinate of the apple's position.
31+
y (int): The y-coordinate of the apple's position.
2932
apple_type (AppleType): The type of the apple (RED or GREEN).
3033
"""
34+
super().__init__(x, y)
3135
self.apple_type = apple_type
3236

3337
def is_green(self) -> bool:
@@ -47,3 +51,17 @@ def is_red(self) -> bool:
4751
bool: True if the apple is red, False otherwise.
4852
"""
4953
return self.apple_type == AppleType.RED
54+
55+
def get_char(self) -> str:
56+
"""
57+
Returns a character representation of the apple, colored based on its
58+
type.
59+
60+
Returns:
61+
str: A string representing the apple with appropriate color
62+
formatting for the terminal.
63+
"""
64+
if self.is_green():
65+
return "\033[32m@\033[0m" # Green apple
66+
67+
return "\033[31m@\033[0m" # Red apple

api/entity/entity.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from abc import ABC, abstractmethod
2+
3+
4+
class Entity(ABC):
5+
def __init__(self, x: int, y: int):
6+
self.__x = x
7+
self.__y = y
8+
9+
def get_x(self) -> int:
10+
return self.__x
11+
12+
def get_y(self) -> int:
13+
return self.__y
14+
15+
def set_x(self, x: int) -> None:
16+
self.__x = x
17+
18+
def set_y(self, y: int) -> None:
19+
self.__y = y
20+
21+
@abstractmethod
22+
def get_char(self) -> str:
23+
pass
24+
25+
def __str__(self):
26+
return self.get_char()

api/entity/snake.py

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
from api.exception.gameover import GameOver
33
from api.entity.apple import Apple
44
from api.world import World
5+
from api.entity.entity import Entity
56

67

7-
class SnakeBody:
8+
class SnakeBody(Entity):
89
"""
910
Represents a segment of a snake's body in a game.
1011
@@ -18,43 +19,34 @@ def __init__(self, x: int, y: int):
1819
Initializes a body segment of the snake at a specific position.
1920
2021
Args:
21-
x (int): The initial X position.
22-
y (int): The initial Y position.
22+
x (int): The initial X position of the body segment.
23+
y (int): The initial Y position of the body segment.
2324
"""
24-
self.__x = x
25-
self.__y = y
25+
super().__init__(x, y)
2626

27-
def get_x(self) -> int:
27+
def move(self, x: int, y: int):
2828
"""
29-
Returns the X-coordinate of the body segment.
29+
Moves the body segment to a new position.
3030
31-
Returns:
32-
int: The X-coordinate.
31+
Args:
32+
x (int): The new X position of the body segment.
33+
y (int): The new Y position of the body segment.
3334
"""
34-
return self.__x
35+
self.set_x(x)
36+
self.set_y(y)
3537

36-
def get_y(self) -> int:
38+
def get_char(self) -> str:
3739
"""
38-
Returns the Y-coordinate of the body segment.
40+
Returns the character representation of a body segment for rendering in
41+
the terminal.
3942
4043
Returns:
41-
int: The Y-coordinate.
44+
str: The character "#" representing the body segment.
4245
"""
43-
return self.__y
46+
return "#"
4447

45-
def move(self, x: int, y: int):
46-
"""
47-
Moves the body segment to a new position.
4848

49-
Args:
50-
x (int): The new X position.
51-
y (int): The new Y position.
52-
"""
53-
self.__x = x
54-
self.__y = y
55-
56-
57-
class Snake:
49+
class Snake(Entity):
5850
"""
5951
Represents a snake in the game, which moves, grows, and interacts with the
6052
world.
@@ -79,11 +71,11 @@ def __init__(self, world: World, x: int, y: int, direction: Direction):
7971
y (int): The initial Y position of the snake's head.
8072
direction (Direction): The initial movement direction of the snake.
8173
"""
82-
self.__x = x
83-
self.__y = y
74+
super().__init__(x, y)
75+
8476
self.__body: list[SnakeBody] = []
85-
self.__world = world
86-
self.__last_direction = direction
77+
self.__world: World = world
78+
self.__last_direction: Direction = direction
8779

8880
dir_x, dir_y = direction.value
8981

@@ -93,7 +85,7 @@ def __init__(self, world: World, x: int, y: int, direction: Direction):
9385
y += dir_y
9486

9587
self.__body.append(SnakeBody(x, y))
96-
self.__world.spaw_entity(self.__body[-1])
88+
self.__world.spawn_entity(self.__body[-1])
9789

9890
def move(self, direction: Direction):
9991
"""
@@ -108,28 +100,27 @@ def move(self, direction: Direction):
108100
GameOver: If the snake collides with an obstacle or itself.
109101
"""
110102
x, y = direction.value
111-
info = self.__world.get_location(self.__x + x, self.__y + y)
103+
info = self.__world.get_location(self.get_x() + x, self.get_y() + y)
112104

113105
if not info.is_passable():
114106
raise GameOver("End game")
115107

116-
self.__x += x
117-
self.__y += y
108+
self.set_x(self.get_x() + x)
109+
self.set_y(self.get_y() + y)
118110
self.__last_direction = direction
119111

120112
# Move the body segments following the head
121113
for i, body in reversed(list(enumerate(self.__body))):
122114
if i == 0:
123-
body.move(self.__x - x, self.__y - y)
115+
body.move(self.get_x() - x, self.get_y() - y)
124116
else:
125117
last = self.__body[i - 1]
126118
body.move(last.get_x(), last.get_y())
127119

128120
def eat(self, apple: Apple):
129121
"""
130122
Handles the snake eating an apple. The snake grows if the apple is
131-
green,
132-
otherwise, it loses a segment.
123+
green, otherwise, it loses a segment.
133124
134125
Args:
135126
apple (Apple): The apple that the snake is eating.
@@ -141,6 +132,7 @@ def eat(self, apple: Apple):
141132
x, y = self.__last_direction
142133
last_body = self.__body[-1]
143134

135+
# Grow the snake by adding a new body segment
144136
self.__body.append(
145137
SnakeBody(
146138
last_body.get_x() + x,
@@ -151,6 +143,7 @@ def eat(self, apple: Apple):
151143
if len(self.__body) == 0:
152144
raise GameOver("End game")
153145

146+
# Remove the last body segment
154147
del self.__body[-1]
155148

156149
def size(self) -> int:
@@ -163,29 +156,21 @@ def size(self) -> int:
163156
"""
164157
return len(self.__body) + 1
165158

166-
def get_x(self) -> int:
167-
"""
168-
Returns the X-coordinate of the snake's head.
169-
170-
Returns:
171-
int: The X position of the snake's head.
172-
"""
173-
return self.__x
174-
175-
def get_y(self) -> int:
159+
def get_body(self) -> list[SnakeBody]:
176160
"""
177-
Returns the Y-coordinate of the snake's head.
161+
Returns the list of body segments of the snake.
178162
179163
Returns:
180-
int: The Y position of the snake's head.
164+
list[SnakeBody]: The body segments of the snake.
181165
"""
182-
return self.__y
166+
return self.__body
183167

184-
def get_body(self) -> list[SnakeBody]:
168+
def get_char(self) -> str:
185169
"""
186-
Returns the list of body segments of the snake.
170+
Returns the character representation of the snake, colored for
171+
terminal output.
187172
188173
Returns:
189-
list[SnakeBody]: The body segments of the snake.
174+
str: A string representing the snake, colored in yellow.
190175
"""
191-
return self.__body
176+
return "\033[33m#\033[0m"

api/world.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from api.map_location import MapLocation
2+
from api.entity.entity import Entity
23
import sys
34
import copy
45

@@ -25,7 +26,7 @@ def __init__(self, height=10, width=10):
2526
self.__world: list = []
2627
self.__height: int = height
2728
self.__width: int = width
28-
self.__entities: list = []
29+
self.__entities: list[Entity] = []
2930

3031
self.__make_world()
3132

@@ -104,7 +105,7 @@ def render(self):
104105
world = copy.deepcopy(self.__world)
105106

106107
for entity in self.__entities:
107-
world[entity.get_y()][entity.get_x()] = '#'
108+
world[entity.get_y()][entity.get_x()] = entity.get_char()
108109

109110
# Uncomment if you want to render the snake's body
110111
# for body in entity.get_body():

main.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
from api.direction import Direction
33
from api.exception.gameover import GameOver
44
from api.entity.snake import Snake
5+
from api.entity.apple import Apple, AppleType
56

67
world = World()
7-
snake = Snake(world, 5, 5, Direction.SUD)
8+
snake = Snake(world, 5, 5, Direction.SOUTH)
9+
green_apple = Apple(2, 2, AppleType.GREEN)
810

9-
world.spaw_entity(snake)
11+
world.spawn_entity(snake)
12+
world.spawn_entity(green_apple)
1013

1114
while True:
1215
world.render()
@@ -21,9 +24,9 @@
2124
if key == 'w':
2225
snake.move(Direction.NORTH)
2326
elif key == 's':
24-
snake.move(Direction.SUD)
27+
snake.move(Direction.SOUTH)
2528
elif key == 'a':
26-
snake.move(Direction.WEAST)
29+
snake.move(Direction.WEST)
2730
elif key == 'd':
2831
snake.move(Direction.EAST)
2932
except GameOver:

0 commit comments

Comments
 (0)