Example #1
0
        /// <summary>
        /// The SimulationTimerEventHandler method is called when the simulation timer expires.
        /// It updates the current state of the simulation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SimulationTimerEventHandler(object sender, EventArgs e)
        {
            try
            {
                if (SimulationState == SimulationState.Running)
                {
                    MazeCell robotLocation = MazeCells.First(x => x.ContainsRobot); // Retrieve the current location of the robot.
                    int      cellIndex     = MazeCells.IndexOf(robotLocation);      // Retrieve the index of the cell.

                    // Determine the indexes for the cell's neighbours.
                    int northNeighbourIndex = cellIndex - MazeWidthHeightCells;
                    int eastNeighbourIndex  = cellIndex + 1;
                    int southNeighbourIndex = cellIndex + MazeWidthHeightCells;
                    int westNeighbourIndex  = cellIndex - 1;

                    // Determine if the cell is on the north/east/south/west edge of the maze - certain neighbours must be ignored if the current cell is on an edge.
                    bool northEdge = cellIndex < MazeWidthHeightCells ? true : false;
                    bool eastEdge  = ((cellIndex + 1) % MazeWidthHeightCells) == 0 ? true : false;
                    bool westEdge  = (cellIndex % MazeWidthHeightCells) == 0 ? true : false;
                    bool southEdge = (cellIndex + MazeWidthHeightCells) >= (MazeWidthHeightCells * MazeWidthHeightCells) ? true : false;

                    // Retrieve the cell's neighbours.
                    MazeCell northCell = null;
                    MazeCell eastCell  = null;
                    MazeCell southCell = null;
                    MazeCell westCell  = null;
                    // North cell.
                    if (!northEdge && IsCellIndexValid(northNeighbourIndex))
                    {
                        northCell = MazeCells[northNeighbourIndex];
                    }
                    // East cell.
                    if (!eastEdge && IsCellIndexValid(eastNeighbourIndex))
                    {
                        eastCell = MazeCells[eastNeighbourIndex];
                    }
                    // South cell.
                    if (!southEdge && IsCellIndexValid(southNeighbourIndex))
                    {
                        southCell = MazeCells[southNeighbourIndex];
                    }
                    // West cell.
                    if (!westEdge && IsCellIndexValid(westNeighbourIndex))
                    {
                        westCell = MazeCells[westNeighbourIndex];
                    }

                    // Create a maze segment at the robot's current location.
                    MazeSegment mazeSegment = new MazeSegment(robotLocation, northCell, eastCell, southCell, westCell);

                    _robot.Move(mazeSegment);   // Move the robot.

                    SimulationTime = SimulationTime.Add(TimeSpan.FromMilliseconds(Constants.DefaultStepIntervalMilliSeconds));
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Maze.SimulationTimerEventHandler(object sender, EventArgs e): " + ex.ToString());
            }
        }
Example #2
0
        /// <summary>
        /// The Move method is called to move the robot.
        /// The Trémaux's algorithm is used to control the robot.
        /// https://en.wikipedia.org/wiki/Maze_solving_algorithm#Tr%C3%A9maux's_algorithm
        /// </summary>
        /// <param name="mazeSegment"></param>
        public void Move(MazeSegment mazeSegment)
        {
            try
            {
                if (mazeSegment == null)
                {
                    throw new Exception("maze segment can not be null.");
                }

                if (CurrentLocation == null)
                {
                    // The robot is not in the maze - do nothing.
                    return;
                }

                // If the robot is NOT at a junction, mark the location.
                if (mazeSegment.SegmentType != SegmentType.Junction)
                {
                    CurrentLocation.MarkCell();
                }

                // If the robot is at a dead-end (except for the start of the maze), mark the location a second time.
                if (mazeSegment.SegmentType == SegmentType.DeadEnd && CurrentLocation.CellRole != CellRole.Start)
                {
                    CurrentLocation.MarkCell();
                }

                // Turn the robot, based on the type of maze segment.
                CurrentDirection = mazeSegment.ChooseDirection(CurrentDirection);

                // Attempt to move the robot forwards.
                MazeCell newCurrentLocation = null;
                if (CurrentDirection == Direction.North && mazeSegment.NorthCell.CellMark != CellMark.Twice)
                {
                    newCurrentLocation = mazeSegment.NorthCell;
                }
                else if (CurrentDirection == Direction.East && mazeSegment.EastCell.CellMark != CellMark.Twice)
                {
                    newCurrentLocation = mazeSegment.EastCell;
                }
                else if (CurrentDirection == Direction.South && mazeSegment.SouthCell.CellMark != CellMark.Twice)
                {
                    newCurrentLocation = mazeSegment.SouthCell;
                }
                else if (CurrentDirection == Direction.West && mazeSegment.WestCell.CellMark != CellMark.Twice)
                {
                    newCurrentLocation = mazeSegment.WestCell;
                }

                // Update the current location.
                CurrentLocation.ContainsRobot = false;
                CurrentLocation = newCurrentLocation != null ? newCurrentLocation : CurrentLocation;
                CurrentLocation.ContainsRobot = true;

                if (CurrentLocation.CellRole == CellRole.End)
                {
                    OnReachedTheEnd?.Invoke();  // The robot has reached the end of the maze.
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Robot.Move(MazeSegment mazeSegment): " + ex.ToString());
            }
        }