Esempio n. 1
0
        private Enums.MazeValidationOutcome GetMazeValidationOutcome(StreamWriter logFile, Maze mazeFromPlayer)
        {
            logFile.WriteLine("[GAME] : Received maze from player " + _currentPlayer.GetPlayerName());
            var mazeValidationOutcome = (MazeValidator.ValidateMaze(mazeFromPlayer, _maze, logFile));

            logFile.WriteLine("[MAZE] : " + mazeValidationOutcome);
            return(mazeValidationOutcome);
        }
        // there are many maze generator algorithms but I just made a simple random one to provide a different source for input than files
        public Maze GenerateMaze(int rows, int columns, int startX, int startY, int endX, int endY, int nrOfWalls)
        {
            if (!MazeValidator.IsMazeParamtersValid(rows, columns, startX, startY, endX, endY) ||
                nrOfWalls >= ((rows - 2) * (columns - 2) - 2) * 0.5)
            {
                throw new InvalidMazeInputException("Invalid maze inputs.");
            }

            var mazeMatrix = new bool[rows, columns];

            // create walls as a frame for the maze
            for (var j = 0; j < columns; j++)
            {
                mazeMatrix[0, j]        = true;
                mazeMatrix[rows - 1, j] = true;
            }
            for (var i = 1; i < rows - 1; i++)
            {
                mazeMatrix[i, 0]           = true;
                mazeMatrix[i, columns - 1] = true;
            }

            // randomly generate where the walls should reside
            for (var k = 0; k < nrOfWalls; k++)
            {
                int i, j;

                do
                {
                    i = new Random().Next(1, rows - 2);
                    j = new Random().Next(1, columns - 2);
                } while (i == startX && j == startY || i == endX && j == endY || mazeMatrix[i, j]);

                // set wall
                mazeMatrix[i, j] = true;
            }

            var maze = new Maze(mazeMatrix)
            {
                Rows    = rows,
                Columns = columns,
                StartX  = startX,
                StartY  = startY,
                EndX    = endX,
                EndY    = endY
            };

            return(maze);
        }
        public void Solve(Maze maze)
        {
            if (maze == null)
            {
                throw new ArgumentNullException("maze");
            }
            if (!MazeValidator.IsMazeValid(maze))
            {
                throw new InvalidMazeInputException();
            }

            var mazeMatrix = maze.MazeMatrix;

            // set up a new maze matrix based on the input maze matrix
            var levelMatrix = new int[maze.Rows, maze.Columns];

            for (var i = 0; i < maze.Rows; i++)
            {
                for (var j = 0; j < maze.Columns; j++)
                {
                    levelMatrix[i, j] = mazeMatrix[i, j] ? -1 : 0;
                }
            }

            // this queue will help to track the way how we reached the endpoint
            // queue firstly processes those who were the earliest because they have a lower level which is closer to the shortest path
            var queue = new Queue <Cell>();
            var start = new Cell(maze.StartX, maze.StartY);
            var end   = new Cell(maze.EndX, maze.EndY);

            queue.Enqueue(start);
            // set start position
            levelMatrix[start.Row, start.Col] = 1;

            while (queue.Count > 0)
            {
                var cell = queue.Dequeue();
                // if current cell equals the 'end' cell then the shortest path has been found.
                if (cell.Equals(end))
                {
                    break;
                }

                // otherwise check neighbours, level indicates the shortest path from the start point to the particular cell
                var level     = levelMatrix[cell.Row, cell.Col];
                var nextCells = new Cell[4];
                nextCells[3] = new Cell(cell.Row, cell.Col - 1);
                nextCells[2] = new Cell(cell.Row - 1, cell.Col);
                nextCells[1] = new Cell(cell.Row, cell.Col + 1);
                nextCells[0] = new Cell(cell.Row + 1, cell.Col);

                foreach (var nextCell in nextCells)
                {
                    // if the neighbour is the margin of the maze then ignore and continue
                    if (nextCell.Row < 0 || nextCell.Col < 0)
                    {
                        continue;
                    }
                    if (nextCell.Row == maze.Rows ||
                        nextCell.Col == maze.Columns)
                    {
                        continue;
                    }

                    // if the neighbour is an unvisited/available field then add it to the queue for further investigation
                    if (levelMatrix[nextCell.Row, nextCell.Col] == 0)
                    {
                        queue.Enqueue(nextCell);
                        levelMatrix[nextCell.Row, nextCell.Col] = level + 1;
                    }
                }
            }

            // if 'end' cell remained unvisited, then there is no path found from 'start' to 'end'
            if (levelMatrix[end.Row, end.Col] == 0)
            {
                maze.Solution = new List <Cell>();
                return;
            }

            // use stack because it will give a reverse order such as the last in will be the first element of the list
            var path      = new Stack <Cell>();
            var backTrack = end;

            while (!backTrack.Equals(start))
            {
                path.Push(backTrack);
                var level     = levelMatrix[backTrack.Row, backTrack.Col];
                var nextCells = new Cell[4];
                nextCells[0] = new Cell(backTrack.Row + 1, backTrack.Col);
                nextCells[1] = new Cell(backTrack.Row, backTrack.Col + 1);
                nextCells[2] = new Cell(backTrack.Row - 1, backTrack.Col);
                nextCells[3] = new Cell(backTrack.Row, backTrack.Col - 1);
                foreach (var nextCell in nextCells)
                {
                    // check edge cases
                    if (nextCell.Row < 0 || nextCell.Col < 0)
                    {
                        continue;
                    }
                    if (nextCell.Row == maze.Rows ||
                        nextCell.Col == maze.Columns)
                    {
                        continue;
                    }
                    // get closer to 'start' cell by considering the cells with a lower level
                    if (levelMatrix[nextCell.Row, nextCell.Col] == level - 1)
                    {
                        backTrack = nextCell;
                        break;
                    }
                }
            }

            maze.Solution = path;
        }
 public void SetUp()
 {
     _mazeValidator = new MazeValidator();
 }