Say I have a 15x15 2d array
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
See the character A? at y:9 and x:4 (index starts with 0).
What I want to do here is to update the array where I select or update the 0s around the A to, say, asterisk (*).
For an example, lets say I want 0s around the A as far as 3 indexes to be updated as *
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, *, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, *, *, *, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, *, *, *, *, *, 0, 0, 0, 0, 0, 0, 0, 0],
[0, *, *, *, 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, 0, 0, *, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
What is the most efficient way to achieve this?
EDIT
What I've tried:
var s_length = 4, coordinate_y_x = [9, 4]
for (let i1 = 0; i1 < s_length; i1++) {
for (let i = 0; i < s_length; i++) {
if (map[coordinate_y_x[0] - i][coordinate_y_x[1]] != undefined) map[coordinate_y_x[0] - i][coordinate_y_x[1]] = 1
if (map[coordinate_y_x[0]][coordinate_y_x[1] - i]!= undefined) map[coordinate_y_x[0]][coordinate_y_x[1] - i] = 1
}
for (let i = s_length; i > 0; i--) {
console.log("loop2");
if (map[coordinate_y_x[0] + i][coordinate_y_x[1]]!= undefined) map[coordinate_y_x[0] + i][coordinate_y_x[1]] = 1
if (map[coordinate_y_x[0]][coordinate_y_x[1] + i]!= undefined) map[coordinate_y_x[0]][coordinate_y_x[1] + i] = 1
}
}
I managed to change what's left, right, top, and bottom from this code with given point and length, but I can't seem to figure out how to do the rest (between directions)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 1, 1, 1, A, 1, 1, 1, 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, 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]
One way is with a somewhat spiral matrix walk, but instead of a "square" walk, yours will be diagonal / "diamond" shape. Additionally, we don't really care about the "connectiveness" of the path, so I'll jump around a bit. That is, when a walk has finished a ring, it isn't important that the next ring start on a neighboring cell of the previous ring's last step.
In your example data, I've marked the cells that the algorithm would visit in order (1st, 2nd, 3rd, etc.)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 15, 7, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 14, 6, 2, 8, 18, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 13, 5, 1, A, 3, 9, 19, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 24, 12, 4, 10, 20, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 23, 11, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Note, I've chosen to always start from the left side of the origin, but that is arbitrary. You could start from the top, right, or bottom side.
So our three loops (in order) will be
The length we want to "expand" by can be thought of as a separate "ring." So loop each ring.
Next, loop each "side" of that ring.
Finally, loop each "step" along that side.
To keep things symmetric, each side will only occupy a single "corner" cell. So for example when looping the 3rd ring, each side would only be 3 steps each. Here I have each side labeled as a, b, c, and d.
* * * b * * *
* * a * b * *
* a * * * b *
a * * X * * c
* d * * * c *
* * d * c * *
* * * d * * *
Otherwise the only tricky part is figuring out how to change directions as you loop each side.
A very simple way to do this is store "deltas," how much we expect each x and y value (where we currently are) to change for each step. We know we'll be moving 1 step each time, so it is just a matter of moving right / down (positive +) or left / up (negative -).
I decided to store these values in an array, but you can probably do some modulo math to switch between them. Looping over a constant is just a little easier to understand. So moving up and to the right would have an x_delta value of 1 and y_delta value of -1, etc.
Finally, you need a "in bounds" check as you are completing your walk. The algo will still try and "visit" these cells, but won't try to write to the array if it doesn't exist. This is one area of the algo you can probably improve.
Put it all together, and you have this:
const data = Array(15)
.fill()
.map(v => Array(15).fill(0));
// Assumes the graph won't contain `undefined` values. Otherwise, do a `length` check on the arrays
function inBounds(data, [y, x]) {
return data?.[y]?.[x] !== undefined;
}
const deltas = [
[ 1, -1], // Up right
[ 1, 1], // Down right
[-1, 1], // Down left
[-1, -1], // Up left
];
function fillFrom({origin: [oy, ox], data, length, value}) {
// Walk in diamond "rings" around our origin
for (let size = 1; size <= length; size++) {
// Start from the left side of our ring
let x = ox - size;
let y = oy;
// Move along 4 sides of the diamond
for (let [xd, yd] of deltas) {
// Move each step along the side
for (let step = 0; step < size; step++) {
if (inBounds(data, [y, x])) {
data[y][x] = value;
}
x += xd;
y += yd;
}
}
}
return data;
}
// Updates data "in place." Would need to deep clone if you wanted to keep things immutable
fillFrom({origin: [9, 4], data, length: 3, value: 1});
data[9][4] = 'A';
console.log(data.map(r => r.join('')).join('\n'));
This question already has answers here:
Weird behavior with objects & console.log [duplicate]
(2 answers)
Unexpected behavior using Array Map on an Array Initialized with Array Fill [duplicate]
(1 answer)
Closed 3 years ago.
I am building a Sudoku game in React, the last function I wrote would make the board.
It makes an empty Board (2D Array filled with zeros), solves the board, then takes some random values out to make it a playable Sudoku.
The problem is that making the 2D Zeros Array is giving me a 2D Array filled with random numbers.
It is crazy I know, but it is making me crazy that I can't figure out what the problem is.
Code snippets that I've used:
let emptyBoard = [
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
];
let emptyBoard = new Array(9).fill(new Array(9).fill(0));
let emptyBoard = [];
for (let i = 0; i < 9; i++) {
emptyBoard.push([]);
for (let j = 0; j < 9; j++) {
emptyBoard[i].push(0);
}
}
The complete function is as follows:
makeBoard() {
let emptyBoard = [
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
];
console.log(emptyBoard);
let { result, cells } = this.solveAndShuffle(emptyBoard);
if (result) {
let shuffledKeys = this.shuffle([ ...Array(81).keys() ]);
for (let key of shuffledKeys) {
const subgrid = Math.floor(key / 9);
const cell = key % 9;
const cellValue = cells[subgrid][cell];
cells[subgrid][cell] = 0;
const solutions = this.cellSolutions(subgrid, cell, cells);
if (solutions.length !== 1 && solutions.length !== 2) {
cells[subgrid][cell] = cellValue;
}
}
const immutable = this.immutableCells(cells);
this.setState({
cells: cells,
immutable: immutable,
wrongCells: new Array(9).fill(new Array(9).fill(false)),
causingError: new Array(9).fill(new Array(9).fill(false)),
solved: false
});
} else {
alert('Something wrong happend while trying to make a board!');
}
}
I even deployed it with the console.log on Github Pages if anyone wants to check it online it is on Sudoku JS, you can call the function by pressing "New".
And the code is hosted on Github
I am thankful for anyone who could provide help ♥
If the problem is that you see randomly filled array in console, then it is just Chrome Dev Tools way to display values. If you open the array, you can see the blue "i" icon that says: "Value below was evaluated just now" - it means that the logged array was logged by reference and it's value was changed since it was logged. Try to check the value with JSON.stringify(). I suppose, it is everything okay with you code :)
First things first, I am trying my hand at a very simple tile map engine for 2d games using HTML5 canvas and Javascript and everything seems to be working okay except that my second drawChar function's drawImage() isn't showing on the canvas. I know the urls are good and I have checked for missing chars, etc. but cant figure it out. Code is below. Any help is appreciated.
P.S. I know that much of this code is not "modern" or "best practice", I am still learning and am just trying learn why this error is occurring. Thanks.
<canvas id="canvas" width="1000" height="500" style="border: 2px solid black; margin: 10px auto;"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var draw=canvas.getContext('2d');
var tileSize=canvas.height/10;
var mapLength=canvas.width/tileSize;
var tilex=0;
var tiley=0;
var tile1= new Image();
var tile2= new Image();
var charImg= new Image();
tile1.src='https://raw.githubusercontent.com/daveboy87/Jscript-TileEngine/master/tile_sky.jpg';
tile2.src='https://raw.githubusercontent.com/daveboy87/Jscript-TileEngine/master/tile_ground.jpg';
charImg.src='https://raw.githubusercontent.com/daveboy87/Jscript-TileEngine/master/player.jpeg';
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1]
];
function drawMap() {
for (var y=0; y<mapLength; y++){
for (var x=0; x<tileSize; x++){
tilex=x*tileSize;
tiley=y*tileSize;
if (parseInt(mapArray[y][x]) == 0) {
draw.drawImage(tile1, tilex, tiley, tileSize, tileSize); }
if (parseInt(mapArray[y][x]) == 1) {
draw.drawImage(tile2, tilex, tiley, tileSize, tileSize); }
}
}
}
function drawChar(){
draw.drawImage(charImg, 300, 200, tileSize, tileSize); }
function nextFrame(){
draw.clearRect(0, 0, canvas.width, canvas.height);
drawMap();
drawChar();
}
setInterval(nextFrame, 1000);
You're checking mapArray[y][x] - but y and x aren't related with the size of mapArray, so you're checking for an element that doesn't exist, and getting a Javascript error, which blocks the program execution.
You should keep the Chrome developer tools open so you can see Javascript errors, which will show you the problem here.
I've got this code from a javascript file that looks like some object but Im not sure.
How can I use this data?
DataStore.prime('standings', { stageId: 36 },
[
[36,13,'Arsenal',1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,,,]
,[36,24,'Aston Villa',2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,,,]
,[36,184,'Burnley',3,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,,,]
]);
What you see here is an array (not an object), which elements are 3 other arrays, which elements are numbers and Strings.
Here it is in a more conventional form :
var myArray = [
[36, 13, 'Arsenal', 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, , , ],
[36, 24, 'Aston Villa', 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, , , ],
[36, 184, 'Burnley', 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, , , ]
];
myArray[0][1]; // 13
myArray[1][2]; // 'Aston Villa'
myArray[2][31]; // undefined
From the script I reckon this is data about some football clubs.
DataStore //some class
.prime //probably the function
(
'standings', //argument 1 which is a string calling a string event
{ stageId: 36 }, //argument 2 an object, must be referencing to a stage event
[
[36,13,'Arsenal',1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,,,]
,[36,24,'Aston Villa',2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,,,]
,[36,184,'Burnley',3,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,,,]
] //Argument 3 Multidimensional Array which looks like some stats for a certain team
);
Is this some highscore table for a game?