+18
-2
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
The class follows the lectures "Create a Snake Class & Move to OOP", "Animating
|
The class follows the lectures "Create a Snake Class & Move to OOP", "Animating
|
||||||
the Snake Segments on Screen" and "Controlling the Snake with Keypresses", and
|
the Snake Segments on Screen" and "Controlling the Snake with Keypresses", and
|
||||||
the day-21 steps in which the snake grows and the game ends. It keeps the lectures'
|
the day-21 steps in which the snake grows, and the day-24 step in which it is reset
|
||||||
|
after a collision. It keeps the lectures'
|
||||||
names: `Snake`, `segments`, `create_snake`, `add_segment`, `extend`, `move`, `head`,
|
names: `Snake`, `segments`, `create_snake`, `add_segment`, `extend`, `move`, `head`,
|
||||||
`up`, `down`, `left` and `right`. The only differences are that the snake gets
|
`reset`, `up`, `down`, `left` and `right`. The only differences are that the snake gets
|
||||||
the function that makes a segment as a parameter, so that a test can pass a fake
|
the function that makes a segment as a parameter, so that a test can pass a fake
|
||||||
and needs no window, and how a reversal is refused (see Snake).
|
and needs no window, and how a reversal is refused (see Snake).
|
||||||
"""
|
"""
|
||||||
@@ -20,6 +21,7 @@ from snake_game.constants import (
|
|||||||
LEFT,
|
LEFT,
|
||||||
MOVE_DISTANCE,
|
MOVE_DISTANCE,
|
||||||
RIGHT,
|
RIGHT,
|
||||||
|
SEGMENT_PARKING_POSITION,
|
||||||
SEGMENT_SHAPE,
|
SEGMENT_SHAPE,
|
||||||
STARTING_POSITIONS,
|
STARTING_POSITIONS,
|
||||||
TAIL_COLLISION_DISTANCE,
|
TAIL_COLLISION_DISTANCE,
|
||||||
@@ -204,6 +206,20 @@ class Snake:
|
|||||||
self.head.forward(MOVE_DISTANCE)
|
self.head.forward(MOVE_DISTANCE)
|
||||||
self._direction_of_travel = self.head.heading()
|
self._direction_of_travel = self.head.heading()
|
||||||
|
|
||||||
|
def reset(self) -> None:
|
||||||
|
"""! @brief Start again with a new snake of three segments.
|
||||||
|
|
||||||
|
Every old segment is sent far outside the screen, so it can no longer be
|
||||||
|
seen, the list is emptied, and the snake is created again at the starting
|
||||||
|
positions. The new head is the first new segment, and it points right.
|
||||||
|
"""
|
||||||
|
for segment in self.segments:
|
||||||
|
segment.goto(*SEGMENT_PARKING_POSITION)
|
||||||
|
self.segments.clear()
|
||||||
|
self.create_snake()
|
||||||
|
self.head = self.segments[0]
|
||||||
|
self._direction_of_travel = self.head.heading()
|
||||||
|
|
||||||
def hits_wall(self) -> bool:
|
def hits_wall(self) -> bool:
|
||||||
"""! @brief Tell whether the head has passed the wall on any side.
|
"""! @brief Tell whether the head has passed the wall on any side.
|
||||||
|
|
||||||
|
|||||||
@@ -407,3 +407,61 @@ def test_a_snake_of_four_segments_cannot_touch_its_tail_in_a_small_square() -> N
|
|||||||
snake.move()
|
snake.move()
|
||||||
|
|
||||||
assert not snake.hits_tail()
|
assert not snake.hits_tail()
|
||||||
|
|
||||||
|
|
||||||
|
def test_reset_sends_every_old_segment_off_the_screen() -> None:
|
||||||
|
snake, created = make_snake()
|
||||||
|
snake.extend()
|
||||||
|
old = list(created)
|
||||||
|
|
||||||
|
snake.reset()
|
||||||
|
|
||||||
|
assert len(old) == len(constants.STARTING_POSITIONS) + 1
|
||||||
|
assert all(
|
||||||
|
segment.position() == constants.SEGMENT_PARKING_POSITION for segment in old
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_reset_makes_the_snake_again_at_the_starting_positions() -> None:
|
||||||
|
snake, created = make_snake()
|
||||||
|
snake.extend()
|
||||||
|
snake.extend()
|
||||||
|
old_count = len(created)
|
||||||
|
|
||||||
|
snake.reset()
|
||||||
|
|
||||||
|
assert len(snake.segments) == len(constants.STARTING_POSITIONS)
|
||||||
|
assert positions(snake.segments) == [
|
||||||
|
(float(x), float(y)) for x, y in constants.STARTING_POSITIONS
|
||||||
|
]
|
||||||
|
assert snake.segments == created[old_count:]
|
||||||
|
|
||||||
|
|
||||||
|
def test_reset_makes_the_first_new_segment_the_head() -> None:
|
||||||
|
snake, created = make_snake()
|
||||||
|
old_head = snake.head
|
||||||
|
|
||||||
|
snake.reset()
|
||||||
|
|
||||||
|
new_head = created[len(constants.STARTING_POSITIONS)]
|
||||||
|
assert snake.head is snake.segments[0] is new_head
|
||||||
|
assert snake.head is not old_head
|
||||||
|
assert ("shape", (constants.HEAD_SHAPE,)) in new_head.calls
|
||||||
|
|
||||||
|
|
||||||
|
def test_reset_snake_moves_right_from_the_starting_positions() -> None:
|
||||||
|
snake, _ = make_snake_moving(constants.UP)
|
||||||
|
|
||||||
|
snake.reset()
|
||||||
|
snake.move()
|
||||||
|
|
||||||
|
assert snake.head.position() == (constants.MOVE_DISTANCE, 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_reset_forgets_the_direction_of_the_last_move() -> None:
|
||||||
|
snake, _ = make_snake_moving(constants.DOWN)
|
||||||
|
|
||||||
|
snake.reset()
|
||||||
|
snake.up() # allowed again: the new snake moves right, not down
|
||||||
|
|
||||||
|
assert snake.head.heading() == constants.UP
|
||||||
|
|||||||
Reference in New Issue
Block a user