I am trying to build an application that generates a random map using square tiles. To do this my plan is to use a 2D array that randomly selects the first tile in a row then, when randomly selecting the second tile, it references the right edge value of the previous tile and filters the possible random tiles it can pick from down to an array of only those that match. This process repeats till the row is complete, then when starting a subsequent row the filter will apply to both the right edge of the previous tile and the bottom edge of the one above.
I have gotten to the point where I can generate an array filled with random tiles but I can't get the filtering process to work. I have tried using a .filter in the random selection function but when it tries to reference the previous index that index is undefined.
The tiles are an array of objects like this:
1 means a connected edge, 0 means no connection. Essentially the tiles just have to match 1's with 1's and 0's with 0's.
[
{
"top": 1,
"right": 0,
"bottom": 1,
"left": 0,
"img": "../public/images/1.png"
},
{
"top": 0,
"right": 1,
"bottom": 0,
"left": 1,
"img": "../public/images/2.png"
}
]
My current code looks like this:
// Setting the number of row and columns and creating the empty array
const rows = 5;
const columns = 5
const map = [];
// Populate the empty array with a 2D array of random tile objects.
function generateMap() {
for (let y = 0; y < rows; y++) {
map[y] = [];
for (let x = 0; x < columns; x++) {
map[y][x] = randomlyPopulateMap(x, y);
}
}
}
function randomlyPopulateMap(x, y) {
const randNum = Math.floor(Math.random() * tiles.length);
const randTile = tiles[randNum];
return randTile;
}
I've tried what feels like a dozen solutions but I'm still new to coding and I'm uncertain if I'm even taking the right approach to this problem. Any guidance is greatly appreciated.
I can imagine randomlyPopulateMap first filtering the tiles based on whether they match left-to-right with the tile to the left and top-to-bottom with the tile above. I'm using the condition that if there is no tile above to restrict then any tile will do. You can decide if the boundary itself imposes any additional restrictions.
function randomlyPopulateMap(x, y) {
const candidates = tiles.filter(tile =>
(x == 0 || tile.left == map[y][x-1].right) &&
(y == 0 || tile.top == map[y-1][x].bottom))
and then choose a random tile from among the remaining candidates.
const randNum = Math.floor(Math.random() * candidates.length);
const randTile = candidates[randNum];
return randTile;
}