Balls Rolling in the Maze in C++

Introduction:

Mazes have captivated the minds of puzzle solvers and game developers for a long time; the challenge of navigating a complex lattice, weaving between the barriers, and finally reaching the goal has been something of a timeless pursuit. In this article, we will discuss how to create a maze navigation game in C++ that lets our players guide the ball (also called an object) through a maze.

Problem Statement:

The problem is to create a console-based maze game in C++, where a player navigates a ball (representing object) through the maze via controls (i.e. up, down, left, and right), given the maze is also already provided. The maze should be represented by a 2D array where the '#' characters are walls and empty spaces can be just blank spaces (most 2D arrays in C++ have '0' and other numbers to say the actual value, in our 2D array only ' ' should mean a blank space). The main goal of the maze is to get the ball from its starting position to a goal position without hitting a wall.

In this problem statement, given a 2D array maze[][] of size M x N, one ball is dropped in each column. The top and bottom of the maze are open. A diagonal wall covering two of the cell's corners in each box allows for redirecting a ball to either the left or the right. The maze's symbol for a cell that reroutes the ball to the right is "R", which spans the top-left to bottom-right corners. The maze's "L" represents a board that diverts the ball to the left, spanning the top-right to the bottom-left corners. Any ball can drop out of the bottom or end up in the box. A ball becomes trapped if it strikes the left and right "R" and "L" cells or if a cell redirects it and sends it into one of the maze's walls. After dropping the ball from the ith column at the top, return an array answer of size N, where answer[i] is the column the ball falls out of at the bottom, or -1 if the ball becomes trapped in the box.

Program 1:

Let us take an example to illustrate the Balls rolling in the maze in C++.

Output:

##########
#        #
# ### ## #
# # #  # #
# # #### #
#      # #
##### ## #
#        #
#O########
##########
Enter direction (w/a/s/d):   d

Note: The output is the continuous display of the maze grid with the ball's updated position after each movement. The given output is a sample one.

Explanation:

1. Header Files:

  • #include <iostream>: This header file is included for input/output operations.
  • #include <conio.h>: This header file is specific to Windows and is used for console input. It provides the _getch() function, which reads a single character from the console without echoing it.
  • using namespace std;: This line enable us to utilize standard C++ functions and objects without prefixing them with std::.

2. Constants:

  • const int ROWS = 10; and const int COLS = 10;: These constants define the dimensions of the maze grid.

3. Maze Grid:

  • The maze[][] array represents the maze grid. It is a 2D array of characters where '#' represents walls, ' ' represents empty spaces, and 'O' represents the ball's current position.
  • The maze is initialized with predefined characters to form a simple maze layout.

4. Position Struct:

  • The Position struct represents the position of the ball in the maze. It contains x and y coordinates to track the ball's position.

5. Display Maze Function (displayMaze()):

  • This function iterates over each cell of the maze grid and prints its content to the console.

6. isWall Function:

  • The isWall() function checks if a given position (x, y) in the maze grid contains a wall ('#'). If it's a wall, it returns true; otherwise, it returns false.

7. Move Ball Function (moveBall()):

  • This function moves the ball in the maze based on user input.
  • It takes a direction ('w' for up, 's' for down, 'a' for left, 'd' for right) as input and updates the ball's position accordingly.
  • If the new position after moving is not a wall, the ball's position is updated, and the maze grid is updated to reflect the new position of the ball.

8. Main Function:

  • The main function initializes the ball's starting position (x = 1 and ballPos.y = 1) and updates the maze grid accordingly.
  • After that, it enters an infinite loop where it continuously listens for user input using the _getch()
  • Based on the input character received, it calls the moveBall() function to move the ball in the maze.
  • After each move, it clears the console screen using system("cls") (for Windows) and redisplays the updated maze using the displayMaze()

9. User Input:

  • The user can control the movement of the ball using the arrow keys or other designated keys for up, down, left, and right movements.

Time and Space complexities:

Time Complexity:

  • This displayMaze() function iterates over each cell of the maze grid exactly once to print its content. As there are ROWS * COLS cells in the grid, the time complexity of this function is O(ROWS * COLS).
  • The moveBall() function updates the position of the ball based on the given direction.
  • It performs a constant-time operation for updating the ball's position and checking whether the new position is a wall (isWall() function).
  • Therefore, the time complexity of this function is O(1).
  • Overall, the time complexity of the provided code is O(ROWS * COLS) for initializing and displaying the maze, plus a linear time complexity for user interaction with the ball movement.

Space Complexity:

  • The maze grid is a 2D array of characters with dimensions ROWS * COLS.
  • Therefore, the space complexity of the maze grid is O(ROWS * COLS).
  • The ballPos struct stores the position of the ball (x, y coordinates).
  • It requires constant space, O(1).
  • The variable input stores the user input character for ball movement.
  • It requires constant space, O(1).

Approach 2: Grids Optimization Problem

It is the Grids optimization problem, where dynamic programming can be used to solve Iterate over all the balls one by one. It also maintains a dp[][] array so that dp[i][j] stores the final column number if the ball appears in cell (i, j).

We can use a recursive function to find the column in which the ball will fall and where the ball will go if it reaches the cell by checking the conditions for the ball to go right and left.

If the current cell has a "R" and is not the last cell in the row, the ball will move to the right; also, the cell immediately to the right should not contain a "L". If the current cell has a "L" and is not the first cell in the row, the ball will move to the left, and the cell immediately to the left should not contain a "R."

Program 2:

Output:

1 2 -1 -1 -1 

Explanation:

1. Header File:

We include certain libraries needed in our program, like iostream (for input and output operations) or vector(s) for using vectors.

  • Namespace: We're using std namespace for our convenience. We can get anything related to standard containers and algorithms without writing out std::.

2. Function Definitions :

  • findColumn: The function uses recursion to locate the final column behind a ball in a particular point (rowNo,colNo) of cells from m cost. There are some parameters for this function, such as a maze, size of maze m and n, a memoization array dp, and the current position (rowNo, colNo) of the ball.
  • solve: In this function move through every starting column, and then by column get the ball's ending position. Initialize the ans vecto as our last position and array dp for intermediate results to be remembered.

3. Main Function:

  • In the main function, we initialize the maze with the provided input values, where 'R' represents the right direction and 'L' represents the left direction.
  • After that, we call the solve function to obtain the final positions of the ball for each starting column.
  • Finally, we output the final positions of the ball.

4. Input:

  • The input is a 2-dimensional vector of characters, each character representing which direction can be taken by that cell in order to come out of the bottom row (either 'r' for right or 'l' for left).

5. Output:

  • The output contains a set of integers in a vector representing the final column where the ball falls out of the bottom for each starting column.

Time and Space Complexities:

  • Time Complexity: O(N * M), M is the number of rows, and N is the number of columns of the input matrix maze[][].
  • Auxiliary Space: O(N * M)

Conclusion:

In conclusion, this cute little rolling ball maze game was created and run in C++. You can tilt the entire maze or turn it around (90 degrees) during gameplay by dragging the left mouse button, which creates more of a challenge for you in controlling your ball in the maze with respect to the usual physical effects and the gravity force.

The code for the rolling ball maze game teaches many essential ideas about game development, collision detection, user input handling, maze generation, graphical rendering, etc. But most importantly, it allows the player to improve their spatial awareness, problem-solving skills and reflexes in the context of having fun.