예제 #1
0
    // goes through all the MazeParts + another horizontal and vertical row
    // creates a wall if the wall is not open for these mazeparts
    private void CreateWalls()
    {
        for (int x = 0; x < maze.GetLength(0); x++)
        {
            for (int y = 0; y < maze.GetLength(1); y++)
            {
                MazePart mazePart = maze[x, y];

                // wallOpen array goes clockwise starting from the left (0 = left, 1 = top, 2 = right, 3 = bottom)

                if (!mazePart.wallOpen[(int)Direction.Left])
                {
                    CreateWall(Direction.Left, x, y);
                }
                if (!mazePart.wallOpen[(int)Direction.Up])
                {
                    CreateWall(Direction.Up, x, y);
                }

                // for the last vertical row
                if (x == maze.GetLength(0) - 1 &&
                    !mazePart.wallOpen[(int)Direction.Right])
                {
                    CreateWall(Direction.Right, x, y);
                }
                // for the last horizontal row
                if (y == 0 &&
                    !mazePart.wallOpen[(int)Direction.Down])
                {
                    CreateWall(Direction.Down, x, y);
                }
            }
        }
    }
예제 #2
0
    // will generate a maze with the specified width, height, and chosen algorithm
    // after the maze is generated a piece of fruit is placed at the end of the longest path
    // finally the walls are placed
    public void GenerateMaze(int width, int height, Algorithm algorithm)
    {
        if (maze != null)
        {
            DestroyPreviousMaze();
        }

        CreateMaze(width, height);

        fruitMazePart = maze[0, 0];

        switch (algorithm)
        {
        case Algorithm.Iterative:
            DepthFirstIterativeImplementation();
            break;

        case Algorithm.Recursive:
            DepthFirstRecursiveImplementation(maze[0, 0], 1);
            break;
        }

        fruitMazePart.hasFruit = true;
        fruit = Instantiate(fruitPrefab, fruitMazePart.transform.position, new Quaternion(0, 0, 0, 0));

        CreateWalls();
    }
예제 #3
0
        public Maze(string input)
        {
            var lines = input.SplitNewLine();

            _mazeWidth  = lines[0].Length;
            _mazeHeight = lines.Length;

            _maze = new MazePart[_mazeWidth, _mazeHeight];

            for (int y = 0; y < lines.Length; y++)
            {
                for (int x = 0; x < lines[y].Length; x++)
                {
                    char c = lines[y][x];
                    if (char.IsDigit(c))
                    {
                        Points.Add((new Vector2i(x, y), int.Parse(c.ToString())));
                        _maze[x, y] = MazePart.Digit;
                    }
                    else if (c == '#')
                    {
                        _maze[x, y] = MazePart.Wall;
                    }
                    else
                    {
                        _maze[x, y] = MazePart.Empty;
                    }
                }
            }
        }
예제 #4
0
    public void SpawnPlayer(MazePart mazePart)
    {
        currentPlayerCharacter = Instantiate(playerCharacterPrefab, mazePart.transform.position, new Quaternion(0, 0, 0, 0));
        currentPlayerCharacter.currentMazePart = mazePart;
        gameStarted = true;

        // just in case the player generates a 1 x 1 maze
        CheckForPlayerWinOrLoss(mazePart);
    }
예제 #5
0
 // will call GameOver function if the player character comes into contact with water (loss) or fruit (win)
 public void CheckForPlayerWinOrLoss(MazePart potentiallyUnderWaterMazePart)
 {
     if (potentiallyUnderWaterMazePart.hasFruit && potentiallyUnderWaterMazePart == currentPlayerCharacter.currentMazePart)
     {
         StopWaterSpreadingCoroutines();
         gameStarted = false;
         localUIManager.GameOver(true);
     }
     else if (potentiallyUnderWaterMazePart.UnderWater && potentiallyUnderWaterMazePart == currentPlayerCharacter.currentMazePart)
     {
         StopWaterSpreadingCoroutines();
         gameStarted = false;
         localUIManager.GameOver(false);
     }
 }
예제 #6
0
    // will move the player character in the specified direction,
    // except if the new place would be outside the grid or there is a wall between the current MazePart and its neighbour
    private IEnumerator TryMoveInDirection(Direction direction)
    {
        enoughTimeSinceLastMovement = false;

        PlayerCharacter currentPlayerCharacter = localPlayerManager.currentPlayerCharacter;

        MazePart potentialNewMazePart = NextMazePart(currentPlayerCharacter, direction);

        if (potentialNewMazePart != null)
        {
            currentPlayerCharacter.Move(potentialNewMazePart, direction);
        }

        yield return(waitForSeconds); //0.15f "cooldown" period before the player can move again

        enoughTimeSinceLastMovement = true;
    }
예제 #7
0
    // iterative implementation of randomised depth first algorithm
    private void DepthFirstIterativeImplementation()
    {
        Stack mazeStack = new Stack();

        // mark as visited, push to stack
        maze[0, 0].visited = true;
        mazeStack.Push(maze[0, 0]);

        while (mazeStack.Count > 0)
        {
            MazePart currentMazePart = (MazePart)mazeStack.Pop();

            List <MazePart> currentMazePartUnvistedNeighbours = currentMazePart.GetAllUnvistedNeighbours(maze);
            if (currentMazePartUnvistedNeighbours.Count > 0)
            {
                // push current cell to stack
                mazeStack.Push(currentMazePart);

                // choose unvisited neighbour
                MazePart chosenNeighbour = currentMazePartUnvistedNeighbours[random.Next(0, currentMazePartUnvistedNeighbours.Count)];

                // remove wall
                chosenNeighbour.RemoveWall(currentMazePart);

                // mark chosenNeighbour visited
                chosenNeighbour.visited = true;
                mazeStack.Push(chosenNeighbour);

                // keep track of pathLength to put fruit at the end of the longest path
                chosenNeighbour.pathLength = currentMazePart.pathLength + 1;
            }
            // the longest path in the maze gets a piece of fruit as the end goal for the player
            else
            {
                if (currentMazePart.pathLength > fruitMazePart.pathLength)
                {
                    fruitMazePart = currentMazePart;
                }
            }
        }
    }
예제 #8
0
    // recursive implementation of randomised depth first algorithm
    private void DepthFirstRecursiveImplementation(MazePart currentMazePart, int pathLength)
    {
        // added a pathLength tracker to put fruit at the end of the longest path after the maze is finished
        currentMazePart.pathLength = pathLength;
        if (currentMazePart.pathLength > fruitMazePart.pathLength)
        {
            fruitMazePart = currentMazePart;
        }

        // mark as visited
        currentMazePart.visited = true;

        // read comment in the else for why "true" is put as a condition
        while (true)
        {
            // get a list of all unvisitedNeighbours of this MazePart
            List <MazePart> currentMazePartUnvistedNeighbours = currentMazePart.GetAllUnvistedNeighbours(maze);

            if (currentMazePartUnvistedNeighbours.Count > 0)
            {
                // choose random unvisted neighbour, then remove it from the list
                MazePart chosenNeighbour = currentMazePartUnvistedNeighbours[random.Next(0, currentMazePartUnvistedNeighbours.Count)];
                currentMazePartUnvistedNeighbours.Remove(chosenNeighbour);

                // remove wall between chosenNeighbour and currentMazePart
                currentMazePart.RemoveWall(chosenNeighbour);

                // call this function with chosenNeighbour
                DepthFirstRecursiveImplementation(chosenNeighbour, pathLength + 1);
            }
            // when there are no more unvisted neighbours for currentMazePart,
            // break out of the while loop.
            else
            {
                // I understand this isn't the nicest way to do it but it works well,
                // and currentMazePartUnvistedNeighbours.Count > 0 should not be put as a condition,
                // because there could be (will be) MazeParts in that list that have been changed (visited) by a deeper call of this function.
                break;
            }
        }
    }