Related
I have been practicing some exercises, and among them I am now trying to create a code for finding a path inside a maze matrix created in js.
Now, this code works, it finds the correct path, and I even p[rint it to be sure its the correct one, but I am having one issue. I am not sure what to do in case my path cannot arrive to the destination.
For example, these are 2 of my samples, the correct path is marked with 1 and the "walls" with a 0:
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 2],
[0, 1, 1, 1, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]
But, if I cut one path, preventing my fidner to arrive to the destination, I am unable to find a way to break the recursivity.
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0, 0, 2],
[0, 1, 1, 1, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]
In short, I can return the correct path, but I am not sure , in case It cannot find a way to the "exit", to return "Invalid path", or "There is no path to the destination"
Bellow is the complete code:
class mazeSolver {
constructor() {
this.myMaze = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 2],
[0, 1, 1, 1, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
this.traverse = function (column, row) {
if (this.myMaze[column][row] === 2) {
console.log("You found the exit at: " + column + "-" + row);
console.log("Path: ")
for (let i = 0; i < this.myMaze.length; i++) {
console.log(this.myMaze[i])
}
}
else if (this.myMaze[column][row] === 1) {
this.myMaze[column][row] = 8;
console.log("You passed by " + row + "-" + column);
if (column < this.myMaze.length - 1) {
this.traverse(column + 1, row);
}
if (row < this.myMaze[column].length - 1) {
this.traverse(column, row + 1);
}
if (column > 0) {
this.traverse(column - 1, row);
}
if (row > 0) {
this.traverse(column, row - 1);
}
}
};
}
}
I appreciate any input.
Thanks!
Some comments on your code:
Use console.log inside the traverse method for debugging only, not for something important as reporting the path that was found. That should actually be left to the caller to do.
If the recursive call finds the target, no other recursive call should be made. Instead that success should immediately be returned to the caller, who should do the same...
The path could be collected during backtracking. This path could be the return value in case of success (and undefined otherwise).
Do not initialise a hardcoded matrix in the constructor. Instead pass the matrix as argument to the constructor.
Make traverse a prototype method, instead of defining it on the instance.
In a matrix, we usually consider the first dimension as rows, and the second dimension as columns. You did it the other way round.
It is easier to protect your traversal against out-of-range access by the use of the ?. operator.
Here is the updated code:
class MazeSolver {
constructor(matrix) {
this.myMaze = matrix;
}
traverse(column, row) {
if (this.myMaze[row]?.[column] === 2) {
return [[column, row]]; // Return path. Caller can extend it
} else if (this.myMaze[row]?.[column] === 1) {
this.myMaze[row][column] = 8;
console.log("You passed by " + column + "," + row);
const path = this.traverse(column + 1, row)
?? this.traverse(column, row + 1)
?? this.traverse(column - 1, row)
?? this.traverse(column, row - 1);
if (path) path.unshift([column, row]); // Extend the path found
return path;
}
}
}
// Maze without solution:
const solver = new MazeSolver([
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 2],
[0, 1, 1, 1, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]);
const path = solver.traverse(0, 3);
if (path) {
console.log("found a path (column, row):")
console.log(JSON.stringify(path));
} else {
console.log("No path found");
}
your solution doesn't work for some cases, take this example
this.myMaze = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 2],
[0, 1, 1, 1, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
];
result:
You passed by 3-0
You passed by 3-1
You passed by 4-1
You passed by 5-1
You passed by 5-2
You passed by 5-3
You passed by 6-3
You passed by 7-3
You passed by 8-3
You passed by 9-3
maze.js:39
if (this.myMaze[row][column] === 2) {
^
TypeError: Cannot read property '3' of undefined
at mazeSolver.traverse (maze.js:39:33)
at mazeSolver.traverse (maze.js:50:26)
at mazeSolver.traverse (maze.js:50:26)
at mazeSolver.traverse (maze.js:50:26)
at mazeSolver.traverse (maze.js:50:26)
at mazeSolver.traverse (maze.js:50:26)
at mazeSolver.traverse (maze.js:53:26)
at mazeSolver.traverse (maze.js:53:26)
at mazeSolver.traverse (maze.js:50:26)
at mazeSolver.traverse (maze.js:50:26)
first thing I can tell about your algorithm is it's an eager algorithm, meaning
that you chose the first available path.
Second thing about recursion is you must have an exit condition that will be true at some point, you don't have it your case, you are not even exiting the function at any point.
third you are switching between column and row, column is the vertical array, row is the horizontal array.
here is a code that is an eager solution, that will at least avoid the error above
class mazeSolver {
constructor() {
this.solution_found=false;
this.myMaze = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 1, 1, 2],
[0, 1, 1, 1, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
this.traverse = function (row, column) {
if (this.myMaze[row][column] === 2) {
this.solution_found=true;
console.log("You found the exit at: " + row + "-" + column);
console.log("Path: ")
for (let i = 0; i < this.myMaze.length; i++) {
console.log(this.myMaze[i])
}
}
else if (this.myMaze[row][column] === 1) {
this.myMaze[row][column] = 8;
console.log("You passed by " + row + "-" + column);
if (column < this.myMaze.length - 1) {
if(row +1> this.myMaze.length - 1)
return
this.traverse(row + 1, column);
}
if (row < this.myMaze[row].length - 1) {
if(column+1 > this.myMaze.length - 1)
return
this.traverse(row, column + 1);
}
if (row > 0) {
if(row-1 < 0){
return
}
this.traverse(row - 1, column);
}
if (column > 0) {
if(column-1 < 0){
return
}
this.traverse(row, column - 1);
}
}
};
}
}
maze = new mazeSolver();
maze.traverse(3, 0)
if(!maze.solution_found){
console.log('solution not found')
}
to develop an algorithm that will find the path 100% if the path exists, try doing some research on search algorithms, mainly path finding, e.g., A* heuristic or Dijkstra's Algorithm.
I have the following array table:
var ticket1 = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
I want to insert values in the above array. How do I do that?
I have tried this:
ticket1[0, 0] = 20;
ticket[1, 0] = 30;
ticket[2, 0] = 40;
Expected result:
[20, 0, 0, 0, 0, 0, 0, 0, 0],
[30, 0, 0, 0, 0, 0, 0, 0, 0],
[40, 0, 0, 0, 0, 0, 0, 0, 0]
Actual result:
[20, 30, 40, 0, 0, 0, 0, 0, 0]
Consider the following example.
$(function() {
var ticket1 = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
ticket1[0][0] = 20;
ticket1[1][0] = 30;
ticket1[2][0] = 40;
$.each(ticket1, function(k, v) {
$("<p>").html(v.join(", ")).appendTo("div");
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div></div>
Reference: https://www.w3schools.com/js/js_arrays.asp
When using a Matrix, or an Array of Arrays, you still access each Array Index. So ticket1[0] will access the first element, which is an Array of Integers, so ticket1[0][0] accesses the first index of the first array.
You can make a more complex function to update / change elements in the Matrix.
Array.prototype.mPush = function(x, y, e) {
this[x][y] = e;
return this;
}
$(function() {
var ticket1 = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
];
ticket1.mPush(0, 0, 20);
ticket1.mPush(1, 0, 30);
ticket1[2][0] = 40;
$.each(ticket1, function(k, v) {
$("<p>").html(v.join(", ")).appendTo("div");
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div></div>
function add(var){
ticket.push(var)
}
Eg:
ticket.push(2)
ticket1[0][0] = 20;
posted by ozer and twisty
I would like to quad my board game, I must create coordinates, but i don't know how to do. I need your help !! Thanks
var mapArray = [
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0]
];
function drawMap() {
var col = [];
var table = document.createElement("table");
for (var i = 0; i < mapArray.length; i++) {
for (var j = 0; j < mapArray[i].length; j++) {
if (parseInt(mapArray[i][j]) == 0) {
$('#canvas').append('<div class="grass"></div>');
}
if (parseInt(mapArray[i][j]) == 1) {
$('#canvas').append('<div class="wall"></div>');
}}}}
$('document').ready(function() {
drawMap();
});
It sounds like you need to read up on some canvas manipulation using JavaScript. Example on how to draw lines and what not. But here you go.
I have the below function which draws the grid
function drawGrid(w, h, canvas, ctx, spacing) {
canvas.width = w;
canvas.height = h;
ctx.beginPath();
ctx.strokeStyle = 'rgb(0, 0, 0, 0.35)';
ctx.lineWidth = 1;
for (var x=0; x<=w; x+=spacing) {
ctx.moveTo(x, 0);
ctx.lineTo(x, h);
}
for (var y=0;y<=h;y+=spacing) {
ctx.moveTo(0, y);
ctx.lineTo(w, y);
}
ctx.stroke();
};
Now to explain the above: I pass the width of the canvas, the height of the canvas, the canvas element, the context of the canvas and then the spacing of the grid (example: 16px) I then do a for loop to create the lines and the. I draw them.
The next part of your question is returning the cell the mouse is in. It can be done by the following code - which is two functions for simplicity
function getMousePos(canvas, evt){
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function getGridLocation(posX, posY, gridsize)
{
var cellRow = Math.floor(posY / gridsize);
var cellColumn = Math.floor(posX / gridsize);
return {
row: cellRow,
column: cellColumn
};
}
So above is first to get the mouse co-ordinates and then I use the second function which gets passed the mouse coordinates and then divides them by each cell of the grid and floors the number.
Below is how to get mouse position per cell.
gridCanvas.addEventListener('click', function(evt) {
var mousePos = getMousePos(gridCanvas, evt);
var gridLocation = getGridLocation(mousePos.x, mousePos.y, 64);
//alert("Row: " + gridLocation.row + " Column: " + gridLocation.column);
}, false);
You can do something like this:
const board = [
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
];
const markup = board.map(row => row.map(col => `<span class="field ${col === 0 ? "grass" : "wall"}"></span>` ).join("")).join("<span class='clear'></span>");
document.getElementById("container").innerHTML = markup;
.field {
float: left;
height: 20px;
width: 20px;
border: 1px solid #000;
}
.clear {
clear: both;
float: left;
}
.grass {
background: green;
}
.wall {
background: black;
}
<div id="container">
var gameMap = [ [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1],
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1],
[1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1],
[1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] ]
var can = document.getElementById('gc')
var c = can.getContext('2d')
var di = null
var start = [0,0]
var end = [5,5]
document.addEventListener('keydown',keydown)
document.addEventListener('keyup',keyup)
function update() {
c.clearRect(0,0,can.width,can.height)
switch(di) {
case 'left':
start[0] -= 1
end[0] -= 1
break;
case 'up':
start[1] -= 1
end[1] -= 1
break;
case 'right':
start[0] += 1
end[0] += 1
break;
case 'down':
start[1] += 1
end[1] += 1
break;
}
if(start[0]<0) {
start[0] = 0;
}if(start[1]<0) {
start[1] = 0
}if(end[0]>20) {
end[0] = 20
}if(end[1]>20) {
end[1] = 20
}
can.style.border = '1px black solid'
map()
requestAnimationFrame(update)
}
requestAnimationFrame(update)
function keydown(evt) {
switch(evt.keyCode) {
case 37:
di = 'left'
break;
case 38:
di = 'up'
break;
case 39:
di = 'right'
break;
case 40:
di = 'down'
break;
}
}
function keyup() {
di = null
}
function map() {
var mapx = 0
var mapy = 0
for(var i = start[1]; i<end[1]; i++) {
for(var j = start[0]; j<end[0]; j++) {
switch(gameMap[i][j]) {
case 1:
c.fillRect(mapx,mapy,30,30)
break;
case 0:
break;
}
mapx+=30
}
mapy+=30
mapx = 0
}
}
<!doctype html>
<html>
<canvas id='gc' width=200 height=200></canvas>
</html>
We have a tile map
We have a start and an end
And a draw map function.
When the 'di' (direction) goes above the array, the screen will become white.
So I tried to prevent it by making sure that the start[0], start[1], end[0], end[1] does not exceed the array.
However, the drawing was reduced (try to go out of the array in the snippet)
Why is this so?
You need some adjustmets if the pane goes out of range.
The adjustment bases on the pane width or height and the data array size.
I suggest to call requestAnimationFrame first on run time and then after an event.
Mabe you combine map and update actually it is not clear, what they are for, especially because both handles canvas operations.
function update() {
can.style.border = '1px black solid';
map();
}
function keydown(evt) {
di = { 37: 'left', 38: 'up', 39: 'right', 40: 'down' }[evt.keyCode];
switch (di) {
case 'left':
start[0]--;
end[0]--;
break;
case 'up':
start[1]--;
end[1]--;
break;
case 'right':
start[0]++;
end[0]++;
break;
case 'down':
start[1]++;
end[1]++;
break;
}
if (start[0] < 0) {
start[0] = 0;
end[0] = paneWidth;
}
if (start[1] < 0) {
start[1] = 0;
end[1] = paneHeight;
}
if (end[0] > gameMap[0].length) {
start[0] = gameMap[0].length - paneWidth;
end[0] = gameMap[0].length;
}
if (end[1] > gameMap.length) {
start[1] = gameMap.length - paneHeight;
end[1] = gameMap.length;
}
requestAnimationFrame(update);
}
function keyup() {
di = null;
}
function map() {
var mapx = 0,
mapy = 0;
c.clearRect(0, 0, can.width, can.height);
for (var i = start[1]; i < end[1]; i++) {
for (var j = start[0]; j < end[0]; j++) {
switch (gameMap[i][j]) {
case 1:
c.fillRect(mapx, mapy, 30, 30);
break;
case 0:
break;
}
mapx += 30;
}
mapy += 30;
mapx = 0;
}
}
var gameMap = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1],
[1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
],
can = document.getElementById('gc'),
c = can.getContext('2d'),
di = null,
paneWidth = 6,
paneHeight = 6,
start = [0, 0],
end = [paneWidth, paneHeight];
document.addEventListener('keydown', keydown);
document.addEventListener('keyup', keyup);
requestAnimationFrame(update);
<canvas id="gc" width="180" height="180"></canvas>
You have 8 constraints to enforce and are only enforcing 4.
Eg. your code ensures that start[0] >= 0 but it doesn't ensure start[0] < 20.
I'm trying to make Conway's Game of Life in javascript. I made a function to count neighbors, and a function that produces the next generation of cells. However, I tried a test input, and the result isn't coming out right, and I can't find where the error is. Please help.
Here's the code:
(code attached)
/* Draws grid */
for (var i = 0; i < 15; i++) {
for (var j = 0; j < 15; j++) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "#FFFFFF";
ctx.strokeStyle = "grey";
ctx.strokeRect(10 * j, 10 * i, 10, 10);
}
}
/* draws live cells */
function drawSquares(a) {
for (var i = 0; i < 15; i++) {
for (var j = 0; j < 15; j++) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "#000000";
if (a[i][j] === 1) {
ctx.fillRect(10 * j, 10 * i, 10, 10);
}
}
}
}/* Counts neighbors */
function neighborCount(a, i, j, height, width){
var lifes = 0;
var neighbors = [
[-1, 1],
[0, 1],
[1, 1],
[-1, 0],
[1, 0],
[-1, -1],
[0, -1],
[1, -1]
];
/* loops through a cell's neighbors */
for (var z = 0; z < 8; z++){
/*checks if the neighbor isn't off the grid*/
if ((i + neighbors[z][0]) >=0 && (i + neighbors[z][0]) < height && (j + neighbors[z][1]) >=0 && (j + neighbors[z][1]) < width){
/*checks if it's alive*/
if (a[i + neighbors[z][0]][j + neighbors[z][1]] === 1){
lifes++;
}
}
}
return lifes;
}
/* game of life */
function life(a) {
var n = a; /*new generation of life */
var lifes = 0; /*neighbor counter*/
var height = a.length;
var width = a[0].length;
/*loops through all cells*/
for (var i = 0; i < height; i++){
for (var j = 0; j < width; j++){
lifes = neighborCount(a, i, j, height, width);
/* kills alive cells */
if(a[i][j] === 1 && (lifes < 2 || lifes > 3)){
n[i][j] = 0;
}
/* brings dead cells to life */
else if (a[i][j] === 0 && lifes ===3){
n[i][j] = 1;
}
}
}
drawSquares(n);
return(n);
}
/* test input */
var a = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
/* expected result:
var a = [
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]; */
life(a);
<canvas id="myCanvas" width="150" height="150"></canvas>