matrices en JavaScript tienen peculiaridades propias que no se puede estar esperando si viene de otros idiomas. Dos importantes para su caso de uso son:
- No puede declarar directamente matrices multidimensionales en JavaScript.
- Hay poco beneficio de eficiencia (y ninguna seguridad añadida) cuando configura el tamaño de la matriz en la creación.
A diferencia de otros idiomas, JavaScript no asignará un bloque de memoria para la matriz completa. (No sabe qué tipo de objetos va a poner en cada celda, y, por lo tanto, cuánta memoria total necesitará) En su lugar, todo el argumento size
para Array()
hace por usted se establece la matriz length
propiedad.
Para el, caso general matriz 2D, me gustaría sugerir:
crear la matriz "de arriba", por ejemplo .:
var i // the first-order index in a
, j // the second order index in a
, a = []
elementos de la matriz de inicialización, según sea necesario. Esto se llama lazy initialization, y, en este caso, solo implica la prueba de que a[i]
existe antes de intentar asignar algo a a[i][j]
, p. Ej.:
if (!a[i]) a[i] = []
En Inglés la declaración anterior se lee: "Si el i-ésimo elemento de a
es 'Falsy', asignar una matriz vacía al elemento i-ésimo."
Por último, asigne el valor real de la matriz multideminsional:
a[i][j] = 'whatever'
Para su caso, conocer los valores antes de tiempo, por lo que puede inicializar cada elemento de antemano. (Si usted no está anulando la mayor parte de los elementos, sin embargo, una implementación perezoso puede ser mejor; ver más abajo.)
var x, x_length = 100
, y, y_length = 100
, map = []
// Don't be lazy
for (x = 0; x < x_length; x++) {
map[x] = []
for (y = 0; y < y_length; y++) {
map[x][y] = 'grass.gif|ongrass.gif|collision.gif|above.gif'
}
}
Como otros han dicho, una matriz con 100 elementos numerados de índices ha cero a noventa y nueve, por lo que una comparación menor que la más adecuada aquí.
Como referencia, aquí hay una implementación que usa la inicialización diferida. He ido con una interfaz de función en lugar de acceder directamente a la matriz; es más largo y más complejo, pero también más completo.
El patrón de inicialización que he usado aquí se llama immediately invoked function expression. Si no lo ha visto antes, es uno de los patrones de JavaScript más útiles y vale la pena tomarse un tiempo para comprenderlo.
var map = (function (x_length, y_length, v_default, undefined) {
// Unless v_default is overwritten, use ...
v_default = v_default || 'grass.gif|ongrass.gif|collision.gif|above.gif'
// Private backing array; will contain only values for a[x][y]
// that were explicitly set.
var a = []
// Private helper function.
// - Returns `true` if `x` is between `0` and `x_length - 1`
// and `y` is between `0` and `y_length - 1`.
// - Returns `false` otherwise.
function valid (x, y) {
return (x >= 0
&& x < x_length
&& y >= 0
&& y < y_length)
}
// Private helper function.
// - Returns `true` if a[x][y] has been set().
// - Returns `false` otherwise.
function exists (x, y) {
return !!a[x] && !!a[x][y]
}
// Private getter
// - Returns the value of a[x][y] if it has been set().
// - Returns `undefined` if the point (x,y) is invalid.
// - Returns `v_default` otherwise.
function get (x, y) {
if (!valid(x, y)) return undefined
else if (exists(x, y)) return a[x][y]
else return v_default
}
// Private setter
// - Returns the value set on success.
// - Returns `undefined` on failure
function set (x, y, v) {
if (valid(x, y)) {
// We're being lazy
if (!a[x]) a[x] = []
a[x][y] = v
return a[x][y]
}
return undefined
}
// Return an interface function.
// - Pass the function three arguments, (x, y, v), to set a[x][y] = v
// - Pass the function two arguments, (x, y), to get a[x][y]
return function (x, y, v) {
if (arguments.length > 2) {
return set(x, y, v)
} else {
return get(x, y)
}
}
})(100, 100)
Cuando me encontré con lo anterior en el nodo, las siguientes pruebas impresas valores razonables:
// Invalid invocations
console.log('map() : %s', map())
console.log('map( 0) : %s', map(0))
console.log('map(-1, 0) : %s', map(-1,0))
console.log('map( 0, -1) : %s', map(0, -1))
console.log('map(-1, -1) : %s', map(-1, -1))
// Valid invocations
console.log('map( 0, 0) : %s', map(0, 0))
console.log('map(99, 99) : %s', map(99, 99))
console.log('map( 1, 1) : %s', map(1,1))
console.log('map( 1, 1, "foo") : %s', map(1,1, 'foo'))
console.log('map( 1, 1) : %s', map(1,1))
* Por qué sucede esto * Debido 'world_map_array [i]' 'es undefined' en algún momento?. Si una matriz tiene longitud, digamos, '3', entonces los índices son' 0', '1',' 2'. Además, si nunca asignó un valor a un índice, será 'undefined'. –
¿cómo arreglaría esto? – user1406186
lo que estoy tratando de hacer es crear una matriz bidimensional para representar un mapa de teselas. p.ej. '[0,0] [1,0] [2,0] [0,1] [1,1] [2,1] [0,2] [1,1] [2,2] ' – user1406186