Select Git revision
Daniel Rafeh authored
Implementation of new functions and new testcases - rover checks if an obstacle is in front of it to avoid colisions with them, create new testcases to check if it works properly
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
rover.py 18.27 KiB
# Vorwärtsfahren
# Wenn der Rover in Richtung Norden schaut und den Befehl "F" erhält, erhöht sich seine y-Koordinate um 1.
# Wenn der Rover in Richtung Süden schaut und den Befehl "F" erhält, verringert sich seine y-Koordinate um 1.
# Wenn der Rover in Richtung Osten schaut und den Befehl "F" erhält, erhöht sich seine x-Koordinate um 1.
# Wenn der Rover in Richtung Westen schaut und den Befehl "F" erhält, verringert sich seine x-Koordinate um 1.
# Rückwärtsfahren
# Wenn der Rover in Richtung Norden schaut und den Befehl "B" erhält, verringert sich seine y-Koordinate um 1.
# Wenn der Rover in Richtung Süden schaut und den Befehl "B" erhält, erhöht sich seine y-Koordinate um 1.
# Wenn der Rover in Richtung Osten schaut und den Befehl "B" erhält, verringert sich seine x-Koordinate um 1.
# Wenn der Rover in Richtung Westen schaut und den Befehl "B" erhält, erhöht sich seine x-Koordinate um 1.
# 45°-Links-Drehung
# Wenn der Rover in Richtung Norden schaut und den Befehl "L" erhält, ändert sich seine Blickrichtung auf Nord-West.
# Wenn der Rover in Richtung Süden schaut und den Befehl "L" erhält, ändert sich seine Blickrichtung auf Süd-Ost.
# Wenn der Rover in Richtung Osten schaut und den Befehl "L" erhält, ändert sich seine Blickrichtung auf Nord-Ost.
# Wenn der Rover in Richtung Westen schaut und den Befehl "L" erhält, ändert sich seine Blickrichtung auf Süd-West.
# 45°-Rechts-Drehung
# Wenn der Rover in Richtung Norden schaut und den Befehl "R" erhält, ändert sich seine Blickrichtung auf Nord-Ost.
# Wenn der Rover in Richtung Süden schaut und den Befehl "R" erhält, ändert sich seine Blickrichtung auf Süd-West.
# Wenn der Rover in Richtung Osten schaut und den Befehl "R" erhält, ändert sich seine Blickrichtung auf Süd-Ost.
# Wenn der Rover in Richtung Westen schaut und den Befehl "R" erhält, ändert sich seine Blickrichtung auf Nord-West.
# Sequenzverarbeitung
# Wenn der Rover in Richtung Norden schaut und den Befehl "RF" erhält, ändert sich die Blickrichtung auf Nord-Ost und die x, sowie die y-Koordinate erhöhen sich um 1.
# Wenn der Rover in Richtung Nord-Ost schaut und den Befehl "RFF" erhält, ändert sich die Blickrichtung auf Osten und die x-Koordinate erhöht sich um 2.
# Wenn der Rover in Richtung Nord-Ost schaut und den Befehl "BBBBBLL" erhählt, verringert sich die x-Koordinate um 5 und die Blickrichtung ändert sich auf Norden.
# Wenn der Rover in Richtung Norden schaut und den Befehl "BRRRFLF" erhält, verringert sich die y-Koordinate um 2, die Blickrichtung ändert sich auf Osten und die x-Koordinate erhöht sich um 2.
# Hinderniserkennung
# Wenn der Rover in Richtung Norden schaut und den Befehl "F" erhält obwohl ein Hindernis in dieser Richtung ist, bleibt der Rover stehen und die y-Koordinate ändert sich nicht.
# Wenn der Rover in Richtung Süden schaut und den Befehl "B" erhält obwohl ein Hindernis in dieser Richtung ist, bleibt der Rover stehen und die y-Koordinate ändert sich nicht.
# Wenn der Rover in Richtung Osten schaut und den Befehl "F" erhält obwohl ein Hindernis in dieser Richtung ist, bleibt der Rover stehen und die x-Koordinate ändert sich nicht.
# Wenn der Rover in Richtung Westen schaut und den Befehl "B" erhält obwohl ein Hindernis in dieser Richtung ist, bleibt der Rover stehen und die x-Koordinate ändert sich nicht.
# Wenn der Rover in Richtung Norden bei (3,3) schaut und den Befehl "FF" erhält obwohl ein Hindernis bei (3,5) ist, führt der Rover nur den ersten Befehl aus und bleibt bei (3,4) stehen.
# Wenn der Rover in Richtung Norden bei (3,4) schaut und den Befehl "FFRRFF" erhält obwohl ein Hindernis bei (3,5) ist, bleibt er bei (3,4) stehen.
# Wenn der Rover in Richtung Norden bei (3,4) schaut und den Befehl "RFF" erhält obwohl ein Hindernis bei (3,5) ist, bleibt er bei (3,4) stehen.
# Wenn der Rover in Richtung Norden bei (3,4) schaut und den Befehl "RRFLLFF" erhält obwohl ein Hindernis bei (3,5) ist, muss er bei (4,6) stehen bleiben.
# Plateau-Rand-Erkennung
# Wenn der Rover an der oberen Kante (y = 15) steht, Richtung Norden schaut und den Befehl "F" erhält, bleibt er stehen.
# Wenn der Rover an der unteren Kante (y = 0) steht, Richtung Süden schaut und den Befehl "F" erhält, bleibt er stehen.
# Wenn der Rover an der rechten Kante (x = 15) steht, Richtung Osten schaut und den Befehl "F" erhält, bleibt er stehen.
# Wenn der Rover an der linken Kante (x = 0) steht, Richtung Westen schaut und den Befehl "F" erhält, bleibt er stehen.
# Wenn der Rover in Richtung einer Plateau-Grenze fährt, werden keine weiteren Befehle in der Sequenz mehr ausgeführt.
# Beispiel: Steht der Rover bei (1,0), schaut nach Westen, und erhält "FFRF", bleibt er nach dem ersten "F" stehen (bei (0,0)) und ignoriert den Rest.
# Rückmeldung über erfolgreich ausgeführte Befehle
# Wenn der Rover die Sequenz "FFRF" ausführt und beim zweiten "F" ein Hindernis erkennt, meldet er: ["F"] erfolgreich, Stopp bei Befehl 2.
# Wenn der Rover die Sequenz "FFLF" ausführt und beim letzten "F" am Plateau-Rand steht, meldet er: ["F", "F", "L"] erfolgreich, Stopp bei Befehl 4.
# Wenn der Rover die gesamte Sequenz "FRFL" erfolgreich ausführt, wird dies vollständig gemeldet.
# Relative Position und Ausrichtung nachverfolgen
# Wenn der Rover an Position (1,1) startet, Richtung Norden schaut, und "FRF" erhält, befindet er sich danach bei (3,3) mit Blickrichtung Nord-Ost.
# Wenn der Rover bei (3,3) Richtung Westen schaut und "FLF" ausführt, endet er bei (1,3) mit Blickrichtung Süd-West.
# Wenn der Rover durch Hindernis bei zweitem Schritt gestoppt wird, ist Position und Ausrichtung entsprechend dem letzten erfolgreichen Schritt.
# Bonus: Kombination mehrerer Features
# Wenn der Rover die Sequenz "FFRBFRL" erhält, aber nach dem "R" auf ein Hindernis trifft, bleibt er stehen und ignoriert "BFRL".
# Wenn der Rover bei (15,15) steht, Richtung Nord-Ost, und "FF" erhält, wird nach dem ersten Schritt gestoppt (Plateau-Rand), Position bei (16,16) erreicht nicht – Rover bleibt bei (15,15).
import unittest
from abc import ABC, abstractmethod
class Plateau:
def __init__(self, size_x:int, size_y:int):
self.size_x = size_x
self.size_y = size_y
self.grid = [[None for _ in range(size_x)] for _ in range(size_y)]
self.obstacles = []
def move(self, x:int, y:int):
if (x, y) in self.obstacles:
raise Exception("Obstacle detected!")
print(f"Rover moved to ({x}, {y})")
class Rover:
def __init__(self, x=0, y=0, direction='N', obstacles=None):
self.x = x
self.y = y
self.direction = direction
self.directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']
self.obstacles = obstacles if obstacles else []
def check_for_obstacle(self):
next_stepx, next_stepy = self.x, self.y
if self.direction == 'N':
next_stepy += 1
check_positions = [(next_stepx, next_stepy)]
elif self.direction == 'S':
next_stepy -= 1
check_positions = [(next_stepx, next_stepy)]
elif self.direction == 'E':
next_stepx += 1
check_positions = [(next_stepx, next_stepy)]
elif self.direction == 'W':
next_stepx -= 1
check_positions = [(next_stepx, next_stepy)]
elif self.direction == 'NE':
next_stepx += 1
next_stepy += 1
check_positions = [(next_stepx, next_stepy),
(self.x + 1, self.y),
(self.x, self.y + 1)]
elif self.direction == 'NW':
next_stepx -= 1
next_stepy += 1
check_positions = [(next_stepx, next_stepy),
(self.x + 1, self.y),
(self.x, self.y + 1)]
elif self.direction == 'SE':
next_stepx += 1
next_stepy -= 1
check_positions = [(next_stepx, next_stepy),
(self.x + 1, self.y),
(self.x, self.y + 1)]
elif self.direction == 'SW':
next_stepx -= 1
next_stepy -= 1
check_positions = [(next_stepx, next_stepy),
(self.x + 1, self.y),
(self.x, self.y + 1)]
else:
check_positions = []
for pos in check_positions:
if pos in self.obstacles:
return True
return False
def move_forward(self):
if not self.check_for_obstacle():
if self.direction == 'N':
self.y += 1
elif self.direction == 'S':
self.y -= 1
elif self.direction == 'E':
self.x += 1
elif self.direction == 'W':
self.x -= 1
elif self.direction == 'NE':
self.x += 1
self.y += 1
elif self.direction == 'NW':
self.x -= 1
self.y += 1
elif self.direction == 'SE':
self.x += 1
self.y -= 1
elif self.direction == 'SW':
self.x -= 1
self.y -= 1
else:
print("Obstacle detected! Stopping movement.")
def move_backward(self):
if not self.check_for_obstacle():
if self.direction == 'N':
self.y -= 1
elif self.direction == 'S':
self.y += 1
elif self.direction == 'E':
self.x -= 1
elif self.direction == 'W':
self.x += 1
elif self.direction == 'NE':
self.x -= 1
self.y -= 1
elif self.direction == 'NW':
self.x += 1
self.y -= 1
elif self.direction == 'SE':
self.x -= 1
self.y += 1
elif self.direction == 'SW':
self.x += 1
self.y += 1
else:
print("Obstacle detected! Stopping movement.")
def turn_left(self):
current_index = self.directions.index(self.direction)
self.direction = self.directions[(current_index - 1) % len(self.directions)]
def turn_right(self):
current_index = self.directions.index(self.direction)
self.direction = self.directions[(current_index + 1) % len(self.directions)]
def drive(self, cmd: str) -> str:
i = 0
while i < len(cmd):
c = cmd[i]
if c == 'F':
if self.check_for_obstacle():
print("Obstacle detected! Stopping movement.")
break
self.move_forward()
elif c == 'B':
if self.check_for_obstacle():
print("Obstacle detected! Stopping movement.")
break
self.move_backward()
elif c == 'L' or c == 'R':
# Vorschau: nächste Bewegung nach Drehung
original_direction = self.direction
if c == 'L':
self.turn_left()
else:
self.turn_right()
# nur drehen, wenn danach kein Hindernis im Weg
if i + 1 < len(cmd) and cmd[i + 1] in ['F', 'B']:
if self.check_for_obstacle():
# Rückgängig machen!
self.direction = original_direction
print("Obstacle detected after turn preview! Cancelling turn and movement.")
break
# sonst normale Drehung ohne Folgebewegung
i += 1
class Mars:
def __init__(self, plateau:Plateau, rover:Rover):
self.plateau = plateau
self.rover = rover
self.rover_x = 0
self.rover_y = 0
def drive(self, cmd: str) -> str:
return self.rover.drive(cmd)
class Map:
def __init__(self):
self.map = []
def move(self, x:int, y:int):
print(f"Rover moved to ({x}, {y})")
class MissionControl:
def __init__(self, rover:Rover):
self.rover = rover
def execute_command(self, cmd:str) -> str:
return self.rover.drive(cmd)
class TestRover(unittest.TestCase):
# Test Move Forward in Different Directions
def test_move_forward_north(self):
rover = Rover(0, 0, 'N')
control = MissionControl(rover)
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (0,1))
def test_move_forward_south(self):
rover = Rover(0, 1, 'S')
control = MissionControl(rover)
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (0,0))
def test_move_forward_east(self):
rover = Rover(0, 0, 'E')
control = MissionControl(rover)
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (1,0))
def test_move_forward_west(self):
rover = Rover(1, 0, 'W')
control = MissionControl(rover)
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (0,0))
# Test Move Backward in Different Directions
def test_move_backward_north(self):
rover = Rover(0, 1, 'N')
control = MissionControl(rover)
control.execute_command('B')
self.assertEqual((rover.x, rover.y), (0,0))
def test_move_backward_south(self):
rover = Rover(0, 0, 'S')
control = MissionControl(rover)
control.execute_command('B')
self.assertEqual((rover.x, rover.y), (0,1))
def test_move_backward_east(self):
rover = Rover(1, 0, 'E')
control = MissionControl(rover)
control.execute_command('B')
self.assertEqual((rover.x, rover.y), (0,0))
def test_move_backward_west(self):
rover = Rover(0, 0, 'W')
control = MissionControl(rover)
control.execute_command('B')
self.assertEqual((rover.x, rover.y), (1,0))
# Test Turn Left in Different Directions
def test_turn_left_north(self):
rover = Rover(0, 0, 'N')
control = MissionControl(rover)
control.execute_command('L')
self.assertEqual(rover.direction, 'NW')
def test_turn_left_south(self):
rover = Rover(0, 0, 'S')
control = MissionControl(rover)
control.execute_command('L')
self.assertEqual(rover.direction, 'SE')
def test_turn_left_east(self):
rover = Rover(0, 0, 'E')
control = MissionControl(rover)
control.execute_command('L')
self.assertEqual(rover.direction, 'NE')
def test_turn_left_west(self):
rover = Rover(0, 0, 'W')
control = MissionControl(rover)
control.execute_command('L')
self.assertEqual(rover.direction, 'SW')
# Test Turn Right in Different Directions
def test_turn_right_north(self):
rover = Rover(0, 0, 'N')
control = MissionControl(rover)
control.execute_command('R')
self.assertEqual(rover.direction, 'NE')
def test_turn_right_south(self):
rover = Rover(0, 0, 'S')
control = MissionControl(rover)
control.execute_command('R')
self.assertEqual(rover.direction, 'SW')
def test_turn_right_east(self):
rover = Rover(0, 0, 'E')
control = MissionControl(rover)
control.execute_command('R')
self.assertEqual(rover.direction, 'SE')
def test_turn_right_west(self):
rover = Rover(0, 0, 'W')
control = MissionControl(rover)
control.execute_command('R')
self.assertEqual(rover.direction, 'NW')
# Test Sequence Processing
def test_sequence_processing(self):
rover = Rover(3, 5, 'N')
control = MissionControl(rover)
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (3,6))
self.assertEqual(rover.direction, 'N')
control.execute_command('RF')
self.assertEqual((rover.x, rover.y), (4,7))
self.assertEqual(rover.direction, 'NE')
control.execute_command('RFF')
self.assertEqual((rover.x, rover.y), (6,7))
self.assertEqual(rover.direction, 'E')
control.execute_command('BBBBBLL')
self.assertEqual((rover.x, rover.y), (1,7))
self.assertEqual(rover.direction, 'N')
control.execute_command('BRRRFLF')
self.assertEqual((rover.x, rover.y), (3,5))
self.assertEqual(rover.direction, 'E')
# Test Obstacle Detection
def test_obstacle_detection_forward_north(self):
rover = Rover(3, 5, 'N')
control = MissionControl(rover)
rover.obstacles = [(3, 6)]
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (3,5))
self.assertEqual(rover.direction, 'N')
def test_obstacle_detection_backward_south(self):
rover = Rover(3, 5, 'S')
control = MissionControl(rover)
rover.obstacles = [(3, 4)]
control.execute_command('B')
self.assertEqual((rover.x, rover.y), (3,5))
self.assertEqual(rover.direction, 'S')
def test_obstacle_detection_forward_east(self):
rover = Rover(3, 5, 'E')
control = MissionControl(rover)
rover.obstacles = [(4, 5)]
control.execute_command('F')
self.assertEqual((rover.x, rover.y), (3,5))
self.assertEqual(rover.direction, 'E')
def test_obstacle_detection_backward_west(self):
rover = Rover(3, 5, 'W')
control = MissionControl(rover)
rover.obstacles = [(2, 5)]
control.execute_command('B')
self.assertEqual((rover.x, rover.y), (3,5))
self.assertEqual(rover.direction, 'W')
# Test Obstacle Detection with Sequence
def test_obstacle_detection_sequence(self):
rover = Rover(3, 3, 'N')
control = MissionControl(rover)
rover.obstacles = [(3, 5)]
control.execute_command('FF')
self.assertEqual((rover.x, rover.y), (3,4))
self.assertEqual(rover.direction, 'N')
control.execute_command('FFRRFF')
self.assertEqual((rover.x, rover.y), (3,4))
self.assertEqual(rover.direction, 'N')
control.execute_command('RFF')
self.assertEqual((rover.x, rover.y), (3,4))
self.assertEqual(rover.direction, 'N')
control.execute_command('RRFLLFF')
self.assertEqual((rover.x, rover.y), (4,6))
self.assertEqual(rover.direction, 'N')
if __name__ == '__main__':
unittest.main()