Skip to content
Snippets Groups Projects
Select Git revision
  • 627b102eb75b42881a95c93e584014683a97053f
  • main default protected
  • develop
  • feature/Mars
  • feature/MarsRover
  • feature/Plateau
  • feature/Testcases_Rover
  • feature/obstacle_detection
  • feature/sequence_processing
  • feature/turn_right
  • feature/turn_left
  • feature/move_backwards
  • feature/move_forward
  • feature/base_model
  • feature/testcases
  • feature/user_stories
16 results

rover.py

Blame
  • DaniRafeh28's avatar
    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
    627b102e
    History
    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()