Initialize 2 variables to help generate the dimensions of the maze:
numRows = 6
numCols = 6
First, we will start off with a small 6 by 6 cell maze. After developing code with this smaller maze, we will then increase the number of rows and columns to create bigger mazes. In the Computer Art program, click on "Lesson 1", delete all of the code from that lesson and insert the two variable assignment statements above.
Add to your new program, two statements to calculate the width and height of each cell in the maze:
rowHeight = maxy / numRows
colWidth = maxx / numCols
In generating the maze, we will use colors to help observe the program in action. The maze will also require an Array to store information about the location of the walls in the maze. Add the following assignments to your new program:
withColors = true
Arr = []
colors = ['white','red']
At this point, your program should appear as:
Start RobotC and access a New programtest numRows = 6 numCols = 6 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] colors = ['white','red']
numRows = 6 numCols = 6 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] colors = ['white','red']Next, add a border to your maze:
rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1)
for (i=0; i<numRows; i++) {
Arr.push( [] )
for (j=0; j<numCols; j++) {
Arr[i].push( {vertical:1, horizontal:1} )
}
}
As you can see from the above for() loops, each cell in the 2-dimensional array will contain the following object:
{vertical:1, horizontal:1}
This literal object contains two properties: .vertical and .horizontal. Both properties will be assigned the value of 1. In our maze program, a "level" will be used to help show the program in action. The level can also help control the amount (or level of) recursion. Recursion occurs when a function calls itself. This can lead to a "race condition" in which the program enters an infinite loop from which it cannot escape.
The next part of the program is to "render" the maze. Render means to draw the maze based on the algorithm created so far. The maze will be rendered using the following for() loops. Add these to your program:
// Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight-5 ) if (withColors) line1.lineColor( colors[Arr[i][j].vertical] ) } if (Arr[i][j].horizontal) { line1=line( x, y, x+colWidth-5, y ) if (withColors) line1.lineColor( colors[Arr[i][j].horizontal] ) } } }At this point, your program should appear as follows:
numRows = 6 numCols = 6 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] colors = ['white','red'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:1, horizontal:1} ) } } // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight-5 ) if (withColors) line1.lineColor( colors[Arr[i][j].vertical] ) } if (Arr[i][j].horizontal) { line1=line( x, y, x+colWidth-5, y ) if (withColors) line1.lineColor( colors[Arr[i][j].horizontal] ) } } }If you run this program, you will see the array of walls.
for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal:0} ) } }Assigning the vertical and horizontal walls to zero (0) will create an open space without a wall. A function will be added to create walls between the divided areas. The random function will return an integer value between a minimum and maximum value. For example, add the following function after the initial for() loops:
function randomIntFromInterval(min, max) { // min and max included return Math.floor(Math.random() * (max - min + 1) + min) }Then add a function to perform the process of dividing the area. This function will use the random integer function you just added. Add the following function after the random integer function:
function divide(minCol, maxCol, minRow, maxRow, level) { col = randomIntFromInterval(minCol, maxCol - 1) Arr[0][col].vertical = level row = randomIntFromInterval(minRow, maxRow - 1) Arr[row][0].horizontal = level }The divide() function requires 5 parameters minimum and maximum column, minimum and maximum row, and the level. The level will be used to colorize the walls to make it more clear when and where the computer has divided the area. If .vertical or .horizontal properties are assigned a zero, there is no wall. If they are assigned any non zero integer, the wall will be drawn with a specific color. After you have defined the divide() function, you should call it with the following statement:
numRows = 6 numCols = 6 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] colors = ['white','red'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal:0} ) } } function randomIntFromInterval(min, max) { // min and max included return Math.floor(Math.random() * (max - min + 1) + min) } function divide(minCol, maxCol, minRow, maxRow, level) { col = randomIntFromInterval(minCol, maxCol - 1) Arr[0][col].vertical = level row = randomIntFromInterval(minRow, maxRow - 1) Arr[row][0].horizontal = level } divide(0, numCols, 0, numRows, 1) // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight-5 ) if (withColors) line1.lineColor( colors[Arr[i][j].vertical] ) } if (Arr[i][j].horizontal) { line1=line( x, y, x+colWidth-5, y ) if (withColors) line1.lineColor( colors[Arr[i][j].horizontal] ) } } }Now run your program.
Any error messages? I hope not. Run the program multiple times to see various possibilities for dividing the area. The area is not yet completely divided. However, you should be able to see where the division will occur.
The next step is to modify the program so that the division occurs across all rows and columns. For this, we will need to add for() loops to the divide() function. Update your divide() to use the following statements instead:
function divide(minCol, maxCol, minRow, maxRow, level) { col = randomIntFromInterval(minCol, maxCol - 1) console.log(`My column is: ${col}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical = level row = randomIntFromInterval(minRow, maxRow - 1) console.log(`My row is: ${row}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal = level // Will do the recursion here for all four quadrants // minCol to col; minRow to row // minCol to col; row to maxRow // col to maxCol; minRow to row // col to maxCol; row to maxRow }Let's remove the -5 from the rendering for() loops. By deleting that subtraction you should be able to connect the line segments.
Your program should now appear as follows:
numRows = 6 numCols = 6 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] colors = ['white','red'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal: 0} ) } } function randomIntFromInterval(min, max) { // min and max included return Math.floor(Math.random() * (max - min + 1) + min) } function divide(minCol, maxCol, minRow, maxRow, level) { col = randomIntFromInterval(minCol, maxCol - 1) console.log(`My column is: ${col}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical = level row = randomIntFromInterval(minRow, maxRow - 1) console.log(`My row is: ${row}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal = level // Will do the recursion here for all four quadrants // minCol to col; minRow to row // minCol to col; row to maxRow // col to maxCol; minRow to row // col to maxCol; row to maxRow } divide(0, numCols, 0, numRows, 1) // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight ) if (withColors) line1.lineColor(colors[Arr[i][j].vertical]) } if (Arr[i][j].horizontal) { line1 = line( x, y, x+colWidth, y ) if (withColors) line1.lineColor(colors[Arr[i][j].horizontal]) } } }Run the program several times to see where the divisions may occur. You might notice that the divisions sometimes occur at the edge of the maze boundary. This will leave little to no space to navigate around the wall. Therefore, we will need to restrict the range of the random numbers generated. To restrict the ranges, we will add 1 to the minimum values being sent into the random number generator. See updated divide() function below. Make these updates to your program as well.
function divide(minCol, maxCol, minRow, maxRow, level) { col = randomIntFromInterval(minCol + 1, maxCol - 1) console.log(`My column is: ${col}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical = level row = randomIntFromInterval(minRow + 1, maxRow - 1) console.log(`My row is: ${row}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal = level // Will do the recursion here for all four quadrants // minCol to col; minRow to row // minCol to col; row to maxRow // col to maxCol; minRow to row // col to maxCol; row to maxRow }Now run your program several times.
function divide(minCol, maxCol, minRow, maxRow, level) { if ( minCol == maxCol || minRow == maxRow ) return col = randomIntFromInterval(minCol + 1, maxCol - 1) console.log(`My column is: ${col}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical = level row = randomIntFromInterval(minRow + 1, maxRow - 1) console.log(`My row is: ${row}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal = level // Do the recursion here for all four quadrants // minCol to col; minRow to row divide(minCol, col, minRow, row, level+1) // minCol to col; row to maxRow divide(minCol, col, row, maxRow, level+1) // col to maxCol; minRow to row divide(col, maxCol, minRow, row, level+1) // col to maxCol; row to maxRow divide(col, maxCol, row, maxRow, level+1) }Run your program once. It may appear that it is no longer working. However, it may actually be working too much (a.k.a. stuck in a loop). View the console to see if there are any error messages and any indication of how many times through the divide() function the computer has performed.
How many times did it execute the divide function?
Try using the whole program below which includes a counter for the divide function.
numRows = 6 numCols = 6 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] divisionCounter = 0 colors = ['white','red','green','blue','yellow','purple','black'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal: 0} ) } } function randomIntFromInterval(min, max) { // min and max included return Math.floor(Math.random() * (max - min + 1) + min) } function divide(minCol, maxCol, minRow, maxRow, level) { divisionCounter++ if ( minCol == maxCol || minRow == maxRow ) return col = randomIntFromInterval(minCol + 1, maxCol - 1) console.log(`My column is: ${col}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level row = randomIntFromInterval(minRow + 1, maxRow - 1) console.log(`My row is: ${row}; DivisionCounter: ${divisionCounter}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level // Do the recursion here for all four quadrants // minCol to col; minRow to row divide(minCol, col, minRow, row, level+1) // minCol to col; row to maxRow divide(minCol, col, row, maxRow, level+1) // col to maxCol; minRow to row divide(col, maxCol, minRow, row, level+1) // col to maxCol; row to maxRow divide(col, maxCol, row, maxRow, level+1) } divide(0, numCols, 0, numRows, 1) // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight ) if (withColors) line1.lineColor(colors[Arr[i][j].vertical]) } if (Arr[i][j].horizontal) { line1 = line( x, y, x+colWidth, y ) if (withColors) line1.lineColor(colors[Arr[i][j].horizontal]) } } }Run the program. It probably appears that it is not working. Look at the console panel to see how many times the divide() function has been called. Your computer probably executed the function thousands of times before it crashed.
function divide(minCol, maxCol, minRow, maxRow, level, quadrant) { console.log(`Quadrant: ${quadrant}; Divider is: ${colors[level]}; Area is: ${minCol}, ${maxCol}, ${minRow}, ${maxRow}, ${level}`) if ( maxCol-minCol<2 || maxRow-minRow<2 ) { if ( maxCol-minCol<2) console.log(`This quadrant ${quadrant} does not have required column size ${minCol} and ${maxCol}`) if ( maxRow-minRow<2) console.log(`This quadrant ${quadrant} does not have required row size ${minRow} and ${maxRow}`) return } let col = randomIntFromInterval(minCol+1, maxCol-1) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1, maxRow-1) console.log(`My row is: ${row} is between ${minRow} and ${maxRow}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level if ( level > 3 ) return // Do the recursion here for all four quadrants divide(minCol, col, minRow, row, level+1, 'Quadrant1') divide(minCol, col, row, maxRow, level+1, 'Quadrant2') divide(col, maxCol, minRow, row, level+1, 'Quadrant3') divide(col, maxCol, row, maxRow, level+1, 'Quadrant4') }Note that we have added another "argument" to the list of arguments passed into the divide() function. This last argument is called: quadrant and will be a string passed into the divide function to help update the log output to include the quadrant currently being worked on. This means that you also need to update the initial call to the divide function to appear as:
Try running your program. Does it work? If not, feel free to use the code below as the complete program to this point in the lesson.
numRows = 9 numCols = 9 rowHeight = maxy / numRows colWidth = maxx / numCols withColors = true Arr = [] colors = ['white','red','green','blue','yellow','purple','black'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal: 0} ) } } function randomIntFromInterval(min, max) { // min and max included return Math.floor(Math.random() * (max - min + 1) + min) } function divide(minCol, maxCol, minRow, maxRow, level, quadrant) { console.log(`Quadrant: ${quadrant}; Divider is: ${colors[level]}; Area is: ${minCol}, ${maxCol}, ${minRow}, ${maxRow}, ${level}`) if ( maxCol-minCol<2 || maxRow-minRow<2 ) { if ( maxCol-minCol<2) console.log(`This quadrant ${quadrant} does not have required column size ${minCol} and ${maxCol}`) if ( maxRow-minRow<2) console.log(`This quadrant ${quadrant} does not have required row size ${minRow} and ${maxRow}`) return } let col = randomIntFromInterval(minCol+1, maxCol-1) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1, maxRow-1) console.log(`My row is: ${row} is between ${minRow} and ${maxRow}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level // Do the recursion here for all four quadrants if ( level > 3 ) return divide(minCol, col, minRow, row, level+1, 'Quadrant1') divide(minCol, col, row, maxRow, level+1, 'Quadrant2') divide(col, maxCol, minRow, row, level+1, 'Quadrant3') divide(col, maxCol, row, maxRow, level+1, 'Quadrant4') } divide(0, numCols, 0, numRows, 1, 'All') // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight ) if (withColors) line1.lineColor(colors[Arr[i][j].vertical]) } if (Arr[i][j].horizontal) { line1 = line( x, y, x+colWidth, y ) if (withColors) line1.lineColor(colors[Arr[i][j].horizontal]) } } }As you may have figured out, each division of the area occurs on one of the array coordinates (row and column).
function divide(minCol, maxCol, minRow, maxRow, level, quadrant) { console.log(`Quadrant: ${quadrant}; Divider is: ${colors[level]}; Area is: ${minCol}, ${maxCol}, ${minRow}, ${maxRow}, ${level}`) if ( maxCol-minCol<2 || maxRow-minRow<2 ) { if ( maxCol-minCol<2) console.log(`This quadrant ${quadrant} does not have required column size ${minCol} and ${maxCol}`) if ( maxRow-minRow<2) console.log(`This quadrant ${quadrant} does not have required row size ${minRow} and ${maxRow}`) return } let col = randomIntFromInterval(minCol+1, maxCol-1) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1, maxRow-1) console.log(`My row is: ${row} is between ${minRow} and ${maxRow}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level // Draw a text number at the intersection of row and col t1 = text(col*colWidth, row*rowHeight,level,12) if (withColors) t1.textColor(colors[level]) // Do the recursion here for all four quadrants if ( level > 5 ) return divide(minCol, col, minRow, row, level+1, 'Quadrant1') divide(minCol, col, row, maxRow, level+1, 'Quadrant2') divide(col, maxCol, minRow, row, level+1, 'Quadrant3') divide(col, maxCol, row, maxRow, level+1, 'Quadrant4') }Run the program. Does it show the level indicators at each intersection of lines?
Add the following near the beginning of your program:
openDoor = 0
This value (zero) is the value that represents an open door in a segment of the wall.
Each time an area is divided, we need to add a few doors in the walls to enable a path through the maze. Without these doors, the maze area will be divided without a way of getting from one end of the maze to the other. The doors will be added in the divide() function following the determination of where the division should occur. The position of the doors will be randomly selected using the current random integer function. Update your divide() function to use the following:
function divide(minCol, maxCol, minRow, maxRow, level, quadrant) { console.log(`Quadrant: ${quadrant}; Divider is: ${colors[level]}; Area is: ${minCol}, ${maxCol}, ${minRow}, ${maxRow}, ${level}`) if ( maxCol-minCol<2 || maxRow-minRow<2 ) { if ( maxCol-minCol<2) console.log(`This quadrant ${quadrant} does not have required column size ${minCol} and ${maxCol}`) if ( maxRow-minRow<2) console.log(`This quadrant ${quadrant} does not have required row size ${minRow} and ${maxRow}`) return } let col = randomIntFromInterval(minCol+1, maxCol-1) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1, maxRow-1) console.log(`My row is: ${row} is between ${minRow} and ${maxRow}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level // open some doors door = randomIntFromInterval(minCol, col-1) Arr[row][door].horizontal=openDoor door = randomIntFromInterval(col, maxCol-1) Arr[row][door].horizontal=openDoor door = randomIntFromInterval(minRow, row-1) Arr[door][col].vertical=openDoor door = randomIntFromInterval(row, maxRow-1) Arr[door][col].vertical=openDoor // Draw a text number at the intersection of row and col t1 = text(col*colWidth, row*rowHeight,level,12) if (withColors) t1.textColor(colors[level]) // Do the recursion here for all four quadrants if ( level > 5 ) return divide(minCol, col, minRow, row, level+1, 'Quadrant1') divide(minCol, col, row, maxRow, level+1, 'Quadrant2') divide(col, maxCol, minRow, row, level+1, 'Quadrant3') divide(col, maxCol, row, maxRow, level+1, 'Quadrant4') }Note that two horizontal and two vertical doors are created to enable the user to pass through to each quadrant. No quadrant is omitted from a possible path.
The Whole program should now appear as:
numRows = 14 numCols = 28 rowHeight = maxy / numRows colWidth = maxx / numCols openDoor = 0 withColors = true Arr = [] colors = ['white','red','green','blue','yellow','purple','black'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal: 0} ) } } function randomIntFromInterval(min, max) { // min and max included console.log(`Random range: ${min} ${max}`) return Math.floor(Math.random() * (max - min + 1) + min) } function divide(minCol, maxCol, minRow, maxRow, level, quadrant) { console.log(`Quadrant: ${quadrant}; Divider is: ${colors[level]}; Area is: ${minCol}, ${maxCol}, ${minRow}, ${maxRow}, ${level}`) if ( maxCol-minCol<2 || maxRow-minRow<2 ) { if ( maxCol-minCol<2) console.log(`This quadrant ${quadrant} does not have required column size ${minCol} and ${maxCol}`) if ( maxRow-minRow<2) console.log(`This quadrant ${quadrant} does not have required row size ${minRow} and ${maxRow}`) return } let col = randomIntFromInterval(minCol+1, maxCol-1) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1, maxRow-1) console.log(`My row is: ${row} is between ${minRow} and ${maxRow}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level // open some doors door = randomIntFromInterval(minCol, col-1) Arr[row][door].horizontal=openDoor door = randomIntFromInterval(col, maxCol-1) Arr[row][door].horizontal=openDoor door = randomIntFromInterval(minRow, row-1) Arr[door][col].vertical=openDoor door = randomIntFromInterval(row, maxRow-1) Arr[door][col].vertical=openDoor // Draw a text number at the intersection of row and col t1 = text(col*colWidth, row*rowHeight,level,12) if (withColors) t1.textColor(colors[level]) // Do the recursion here for all four quadrants if ( level > 5 ) return divide(minCol, col, minRow, row, level+1, 'Quadrant1') divide(minCol, col, row, maxRow, level+1, 'Quadrant2') divide(col, maxCol, minRow, row, level+1, 'Quadrant3') divide(col, maxCol, row, maxRow, level+1, 'Quadrant4') } divide(0, numCols, 0, numRows, 1, 'All') // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight ) if (withColors) line1.lineColor(colors[Arr[i][j].vertical]) } if (Arr[i][j].horizontal) { line1 = line( x, y, x+colWidth, y ) if (withColors) line1.lineColor(colors[Arr[i][j].horizontal]) } } }Now we will turn off the colors and just show black lines by changing the following line at the beginning of the program:
// Draw a text number at the intersection of row and col if (withNumbers) { t1 = text(col*colWidth, row*rowHeight,level,12) if (withColors) t1.textColor(colors[level]) }As you can see, the above if() statement will determine if the numbers should be shown (or not) based on the value of the Boolean variable.
Some of the areas created may appear small. We can try to get the computer to create more "squarish" areas and less "very thin" or "very tall" areas by adding an "offset" to further restrict the range of spaces where a division can occur. Add the following near the beginning of the program:
levelDivisionOffset = [4,3,2,1,0]
Update the divide() function to use the following changed lines:
offset = levelDivisionOffset[level] ? levelDivisionOffset[level] : 0 let col = randomIntFromInterval(minCol+1+offset, maxCol-1-offset) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1+offset, maxRow-1-offset)The final version of the program should now appear as:
numRows = 14 numCols = 28 rowHeight = maxy / numRows colWidth = maxx / numCols openDoor = 0 withNumbers = false withColors = false levelDivisionOffset = [4,3,2,1,0] Arr = [] colors = ['white','red','green','blue','yellow','purple','black'] rectangle(0,0, numCols*colWidth-1, numRows*rowHeight-1) for (i=0; i<numRows; i++) { Arr.push( [] ) for (j=0; j<numCols; j++) { Arr[i].push( {vertical:0, horizontal: 0} ) } } function randomIntFromInterval(min, max) { // min and max included console.log(`Random range: ${min} ${max}`) return Math.floor(Math.random() * (max - min + 1) + min) } function divide(minCol, maxCol, minRow, maxRow, level, quadrant) { console.log(`Quadrant: ${quadrant}; Divider is: ${colors[level]}; Area is: ${minCol}, ${maxCol}, ${minRow}, ${maxRow}, ${level}`) if ( maxCol-minCol<2 || maxRow-minRow<2 ) { if ( maxCol-minCol<2) console.log(`This quadrant ${quadrant} does not have required column size ${minCol} and ${maxCol}`) if ( maxRow-minRow<2) console.log(`This quadrant ${quadrant} does not have required row size ${minRow} and ${maxRow}`) return } offset = levelDivisionOffset[level] ? levelDivisionOffset[level] : 0 let col = randomIntFromInterval(minCol+1+offset, maxCol-1-offset) console.log(`My column is: ${col} is between ${minCol} and ${maxCol}`) for (i=minRow; i<maxRow; i++) Arr[i][col].vertical=level let row = randomIntFromInterval(minRow+1+offset, maxRow-1-offset) console.log(`My row is: ${row} is between ${minRow} and ${maxRow}`) for (i=minCol; i<maxCol; i++) Arr[row][i].horizontal=level // open some doors door = randomIntFromInterval(minCol, col-1) Arr[row][door].horizontal=openDoor door = randomIntFromInterval(col, maxCol-1) Arr[row][door].horizontal=openDoor door = randomIntFromInterval(minRow, row-1) Arr[door][col].vertical=openDoor door = randomIntFromInterval(row, maxRow-1) Arr[door][col].vertical=openDoor // Draw a text number at the intersection of row and col if (withNumbers) { t1 = text(col*colWidth, row*rowHeight,level,12) if (withColors) t1.textColor(colors[level]) } // Do the recursion here for all four quadrants if ( level > 3 ) return divide(minCol, col, minRow, row, level+1, 'Quadrant1') divide(minCol, col, row, maxRow, level+1, 'Quadrant2') divide(col, maxCol, minRow, row, level+1, 'Quadrant3') divide(col, maxCol, row, maxRow, level+1, 'Quadrant4') } divide(0, numCols, 0, numRows, 1, 'All') // Render for (i=0; i<numRows; i++) { for (j=0; j<numCols; j++) { x = colWidth * j y = rowHeight * i if (Arr[i][j].vertical) { line1 = line( x, y, x, y+rowHeight ) if (withColors) line1.lineColor(colors[Arr[i][j].vertical]) } if (Arr[i][j].horizontal) { line1 = line( x, y, x+colWidth, y ) if (withColors) line1.lineColor(colors[Arr[i][j].horizontal]) } } }