Javascript minesweeper game, can't increment the right cell - javascript

I'm writing a simple minesweeper game in Javascript. I have a 2-dimensional array (called "mineInput") to hold the locations of all the mines. And I have a separate array "result" which records the number of mines adjacent to each cell.
I have 2 nested for loops to iterate over each row and each column in "result" and check every sell in 'mineInput". If there is a mine, I increment the mine count with result[i][j]++;. However I noticed weird behavior where the entire column is incremented instead of just one cell.
this:
[ [ 0, 0, 0 ],
[ 0, 0, 0 ],
[ 0, 0, 0 ] ]
followed by: result[i][j]++;
becomes:
[ [ 0, 1, 0 ],
[ 0, 1, 0 ],
[ 0, 1, 0 ] ]
instead of:
[ [ 0, 0, 0 ],
[ 0, 1, 0 ],
[ 0, 0, 0 ] ]
Here is the full code (pls excuse the obscene number of console logs).
https://repl.it/BIYH/2
Any idea what's wrong?

The issue is early in your code where you initialise your arrays
var result = [];
var newRow = [];
for (var i = 0; i < rowCount; i++) {
newRow.push(0);
}
for (var i = 0; i < rowCount; i++) {
result.push(newRow);
}
You have created only one newRow array and added it to your result array 3 times. So you could show this like:
newRow == [0,0,0]
result == [newRow, newRow, newRow]
When you increment you add to one cell in the newRow array which gives
newRow == [0,1,0]
result == [newRow, newRow, newRow] therefore
result = [[0,1,0],[0,1,0],[0,1,0]]
you can fix this like this:
var result = [];
for (var i = 0; i < rowCount; i++) {
// create a new array for each row
var newRow = [];
for (var i = 0; i < rowCount; i++) {
newRow.push(0);
}
result.push(newRow);
}

I guess the problem is in the following code:
var result = [];
var newRow = [];
for (var i = 0; i < rowCount; i++) {
newRow.push(0);
}
for (var i = 0; i < rowCount; i++) {
result.push(newRow);
}
You add the same array over and over again to the array result. Instead, you want to create a new array for each row:
var result = [];
for (var i = 0; i < rowCount; i++) {
var newRow = [];
for (var j = 0; j < rowCount; j++) {
newRow.push(0);
}
result.push(newRow);
}
An array is an object in javascript, and objects are always passed by reference.

Related

How does this nested loop get to this output?

I have struggled to understand the output of this nested loop for a long time. I really want to understand what it does.
I would expect it to output: [ [ 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]
But the actual output is: [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]
After the first inner loop row contains two 0's and should be pushed to the newArray in the outer loop. It looks like this isn't happenening and I can't figure out why. The first element should be [0, 0], right?.
I really hope someone can see what I mean here and explain what's happening! Thank you!
function zeroArray(m, n) {
// Creates a 2-D array with m rows and n columns of zeroes
let newArray = [];
let row = [];
for (let i = 0; i < m; i++) {
// Adds the m-th row into newArray
for (let j = 0; j < n; j++) {
// Pushes n zeroes into the current row to create the columns
row.push(0);
}
// Pushes the current row, which now has n zeroes in it, to the array
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
You're passing row to all the iterations of the loop. To achieve what you want, row must be unique through each iteration of the loop, so you need to move it inside the first loop.
To better understand the issue, read more about values and by references in JavaScript: https://www.javascripttutorial.net/javascript-pass-by-value/#:~:text=JavaScript%20pass%2Dby%2Dvalue%20or%20pass%2Dby%2Dreference&text=It%20means%20that%20JavaScript%20copies,variables%20outside%20of%20the%20function.
function zeroArray(m, n) {
// Creates a 2-D array with m rows and n columns of zeroes
let newArray = [];
for (let i = 0; i < m; i++) {
let row = [];
// Adds the m-th row into newArray
for (let j = 0; j < n; j++) {
// Pushes n zeroes into the current row to create the columns
row.push(0);
}
// Pushes the current row, which now has n zeroes in it, to the array
newArray.push(row);
// Update n to get desired pattern
n += 2
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
That's because JavaScript objects (and arrays), are just a reference in memory. so you are creating a single array of arrays that share the same address in memory, because they share the same address, when you update it (Array.prototype.push), you are updating all of them. The solution is to create a new row in the first loop:
function zeroArray(m, n) {
const newArray = [];
for (let i = 0; i < m; i++) {
// If this isn't the first run, take the last value of row
const prevRow = i > 0 ? newArray[i-1] : [];
const row = [...prevRow]; // By using the spread operator(...), you can copy an array
for (let j = 0; j < n; j++) {
// Pushes n zeroes into the current row to create the columns
row.push(0);
}
// Pushes the current row, which now has n zeroes in it, to the array
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
Important note
This isn't a natural way of writing JavaScript, you can achive the same with:
const zeroArray = (m, n) => Array.from({ length : m }).map((value, index) => {
return Array.from({ length : (index + 1) * n }).map(() => 0);
});

2D Array loop behaving strangely (FCC)

I'm doing a learning exercise and am trying to understand the following code. I thought I had a handle on arrays and loops, but this one has got me very confused.
The below code:
function zeroArray(m, n)
{
let newArray = [];
let row = [];
for (let i = 0; i < m; i++)
{
for (let j = 0; j < n; j++)
{
row.push(0);
}
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
Returns
[ [ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ] ]
However I would have expected it to return
[ [ 0, 0, ],
[ 0, 0, 0, 0, ],
[ 0, 0, 0, 0, 0, 0 ] ]
Given that in each i loop, we are pushing (0) to row[] twice, before pushing row[] into newArray.
This isn't happening though, and in my VSCode debugger it looks as though in each i loop, every existing index of newArray is being updated with the latest version of the row[] array.
Why is this?
1) Start outer loop with i = 1 upto i <= m, so the loop count will be m
for (let i = 1; i <= m; i++) {
2) You should create a new row every time the inner loop start and push row into newArray after the inner loop ends
3) Set inner loop condition as j < n * i
for (let j = 0; j < n * i; j++) {
function zeroArray(m, n) {
let newArray = [];
// const row = [] // (-)
for (let i = 1; i <= m; i++) {
const row = []; // (+)
for (let j = 0; j < n * i; j++) { // (+)
row.push(0);
}
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
You need to make a copy of the array when pushing to newArray:
function zeroArray(m, n) {
let newArray = [];
let row = [];
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
row.push(0);
}
newArray.push(row.slice());
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(JSON.stringify(matrix));
Matrix m x n should be m rows and n cols.
So for 3, 2 you expect
[
[0, 0],
[0, 0],
[0, 0],
]
Just declare row inside the first loop:
function zeroArray(m, n) {
const newArray = [];
for (let i = 0; i < m; i++) {
const row = [];
for (let j = 0; j < n; j++) {
row.push(0);
}
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);

Pushing entries into an array in a nested loop [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 3 years ago.
My code:
function zeroArray() {
let newArray = [];
let row = [];
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 2; j++) {
row.push(0);
}
newArray.push(row);
}
return newArray
}
console.log(zeroArray())
From my perspective, its look like the result will be :
[[ 0, 0 ],[ 0, 0, 0, 0 ],[ 0, 0, 0, 0, 0, 0 ]]
but when the code run in the console it shows this, why is that?
[ [ 0, 0, 0, 0, 0, 0 ],[ 0, 0, 0, 0, 0, 0 ],[ 0, 0, 0, 0, 0, 0 ] ]
function zeroArray() {
let newArray = [];
let row = [];
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 2; j++) {
row.push(0);
}
newArray.push(row); // <== Problematic line
}
return newArray;
}
The problem is when you push row array into newArray, it doesn't actually push the values into it; it pushes the pointer to that array, which means after updating row array, if you push it again, it will push the same value to newArray.
Posted the illustration for detailed explanation:
The solution is as some other people noted, re-creating the array each time instead of using the same variable. For example, the solution could be:
function zeroArray() {
const newArray = [];
for (let i = 0; i < 3; i++) {
const row = [];
for (let j = 0; j < 2; j++) {
row.push(0);
}
newArray.push(row); // <== Problematic line
}
return newArray;
}
Looks like an unexpected instance of mutating an object. In this case, you're pushing the same row multiple times, then updating it (resulting in that it updates the three instances of it that end up in newArray). If you instead use something like newArray.push(row.slice()), the output will be as you expect.

Given MxN Matrix, count number 0s whose row and column consists of only one ZERO

For Example:
Input:
//MxN matrix
matrix =
[
[ 0, 0, 1 ],
[ 1, 1, 0 ],
[ 0, 1, 1 ]
]
Output:
1 (Because we only have (1,2) index having 0 whose row and column is having only one 0)
I have tried following:
I am getting all zero elements from Matrix.
Then storing them into HashMap as following:
Indexes which has 0s : [(0,0), (0,1), (1,2), (2,0)]
Hashmap["Row 0"] = 2;
HashMap["Row 1"] = 1;
HashMap["Row 2"] = 1;
HashMap["Col 0"] = 2;
HashMap["Col 1"] = 1;
HashMap["Col 2"] = 1;
The 1s in Hash map are (Row 1, Row 2 and Col 1, Col 2)
I have to get (1,2)
Unable to code for this approach and is there any better approach.
Your approach can be optimized to use two arrays instead of a hash map (should be faster):
var matrix = [
[ 0, 0, 1, ],
[ 1, 1, 0, ],
[ 0, 1, 1, ],
];
// count zeroes on rows and columns
var row0 = new Array(matrix.length).fill(0);
var col0 = new Array(matrix[0].length).fill(0);
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix[i].length; j++) {
if (!matrix[i][j]) {
row0[i]++;
col0[j]++;
}
}
}
// count single zeroes on their respective row and column
var count = 0;
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix[i].length; j++) {
if (!matrix[i][j] && row0[i] == 1 && col0[j] == 1) {
console.log(i, j);
count++;
}
}
}
console.log(count);

Dynamically create index in two dimensional array

Having some trouble with this script. It iterates through a two dimensional array and adds each corresponding index together. So basically arr[0][1] + arr[0][2] + arr[0][3] ... arr[1][1] + arr[1][2] + arr[1][3] ...etc.
This first one works fine. So my logic is ok. My problem here is that I can't create the indices dynamically. I don't think a push will work since I'm summing values here.
var cat_stats_week_radar = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
for (var i = 0; i < cat_stats_week.length; i++) {
for (var j = 0; j < cat_stats_week[0].length; j++) {
cat_stats_week_radar[0][j] += +(cat_stats_week[i][j]);
}
}
This one doesn't work, I don't get an error, just a bunch of NaN values.
var cat_stats_week_radar = [[]];
for (var i = 0; i < cat_stats_week.length; i++) {
for (var j = 0; j < cat_stats_week[0].length; j++) {
cat_stats_week_radar[0][j] += +(cat_stats_week[i][j]);
}
}
Here are the arrays I'm working with.
Array to add:
var cat_stats_week = [
[0,0,0,0,0,0,0,1,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,1,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,1,0],
[0,0,1,0,0,0,0,0,0,0,0,0,0,0]
];
Resulting array:
var cat_stats_week_radar = [[0, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0, 2, 0]];
You need to initialize it with the right number of zeroes:
var cat_stats_week_radar = [[]];
for (var i = 0; i < cat_stats_week[0].length; i++) {
cat_stats_week_radar[0].push(0);
}
And with Underscore.js:
_.map(_.zip.apply(null, cat_stats_week), function(a) {
return _.reduce(a, function(a, b) {
return a + b
})
});

Categories

Resources