Reputation: 65
I was working on a small JavaScript project to make a tile based game (not homework, don't worry!), however I ran into a problem with my 'tile' class.
Each 'tile' has an X and a Y property, for its X and Y position on a grid. The grid is stored as a 2 dimensional array of these tiles. The tiles are constructed like so:
class tile {
constructor(x,y) {
this.x = x;
this.y = y;
console.log(`Genned Tile: ${x} , ${y}`);
}
}
There's also a small logging message contained
So then, I wrote a small loop to fill an array with 'tile' objects:
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
tiles[x,y] = new tile(x,y);
}
}
width and height are both set to 5. This should fill slots 0-4.
However, when displaying the tiles, the X coord is wrong! I'll attach a snippet to show you what I mean
// tile class
class tile {
constructor(x,y) {
this.x = x;
this.y = y;
console.log(`Genned Tile: ${x} , ${y}`);
}
}
var width = 5;
var height = 5;
var tiles = new Array(width,height);
// populates array
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
tiles[x,y] = new tile(x,y);
}
}
// displays each item in the array
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
let tile = tiles[x,y];
console.log(`Checked Tile: ${tile.x} , ${tile.y}`);
}
}
The Y coord looks correct, however the X coord remains at 4! The logging message seems to tell me that it's putting the correct number in the constructor, so I'm unsure why the X coord is changing like this. I did some research and found out that the 'x' and 'y' numbers SHOULD be passed by value (they are primitives), so any changes to 'x' and 'y' in the loop shouldn't affect my class, right?
Any help would be greatly appreciated.
Thanks for reading! :)
Upvotes: 2
Views: 36
Reputation: 1075159
Each of these is incorrect for JavaScript:
var tiles = new Array(width,height);
// ...
tiles[x,y] = new tile(x,y)
That sort of notation is valid in other languages, but not JavaScript (or Java or similar).
In JavaScript, there are no multidimensional arrays. Instead, there are arrays of arrays. You create an array:
var tiles = [];
and then put arrays in it:
tiles[x] = [];
and then put tiles in that:
tiles[x][y] = new tile(x, y);
Live example, see the ***
lines:
// tile class
class tile {
constructor(x,y) {
this.x = x;
this.y = y;
console.log(`Genned Tile: ${x} , ${y}`);
}
}
var width = 5;
var height = 5;
var tiles = []; // ***
// populates array
for (var x = 0; x < width; x++) {
tiles[x] = []; // ***
for (var y = 0; y < height; y++) {
tiles[x][y] = new tile(x,y); // ***
}
}
// displays each item in the array
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
let tile = tiles[x][y]; // ***
console.log(`Checked Tile: ${tile.x} , ${tile.y}`);
}
}
.as-console-wrapper {
max-height: 100% !important;
}
Side note: The overwhelming convention in JavaScript is that constructor functions (functions you call with new
) start with an upper case character. So Tile
rather than tile
.
You may be wondering, if these are incorrect:
var tiles = new Array(width,height);
// ...
tiles[x,y] = new tile(x,y)
...why don't they cause a syntax (or other) error?
The reason is that they're both valid, they just don't do what you intended them to do (and what they would do in some other languages).
This:
var tiles = new Array(width,height);
creates an array with two entries in it (the values of width
and height
):
// Example 1:
const width = 5;
const height = 5;
const tiles = new Array(width,height);
console.log(tiles); // [5, 5]
// Example 2:
const array2 = new Array("10"); // <== Note that the "10" is a string
console.log(array2); // ["10"]
A better way to write it (if you'd wanted to do that) would be:
var tiles = [width, height];
There's almost never any reason to call the Array
constructor in JavaScript, and it's a bit of a confusing function: If you call it with one numeric argument, it creates an empty array using that argument's value as the array length (which sounds weird, but JavaScript's arrays can be sparse, so having a length of [say] 10 but no entries is a valid state for a JavaScript array). If you pass it more than one argument ("Example 1"), or one argument that isn't a number ("Example 2"), it treats its arguments as the initial values to put in the array, which is why new Array(width, height)
creates an array with those two values in it.
This one is trickier:
tiles[x,y] = new tile(x,y)
JavaScript has an unusual operator: The comma operator. It evaluates its left-hand operand, throws away that result, evaluates its right-hand operand, and takes the right-hand result as its result. So tile[x,y]
is effectively just tile[y]
, because although x
is evaluated, its result is thrown away, and only y
is used to look up the entry in the array. Example:
const a = 2;
const b = 3;
const c = (a, b);
console.log(c);
// => 3;
function one() {
console.log("one ran");
return 1;
}
function two() {
console.log("two ran");
return 2;
}
const d = (one(), two());
// => one ran
// => two ran
// => 2
Upvotes: 6