323 lines
8.0 KiB
Markdown
323 lines
8.0 KiB
Markdown
---
|
|
title: "Arreglos: Fundamentos"
|
|
---
|
|
|
|
Los arreglos (*arrays*) son una manera sistematizada de almacenar múltiples variables del mismo tipo.
|
|
|
|
En combinación con ciclos `while` o `for`, nos permiten programar rutinas que actúan sobre diversos valores a la vez.
|
|
|
|
[[Ciclos while y for]](/notas/ciclos.html)
|
|
|
|
# Planteamiento del problema
|
|
|
|
## Una variable
|
|
|
|
Partimos de este ejemplo de código de animación básica con acumuladores, en el que un punto se mueve hacia la derecha y al llegar al borde vuelve a empezar su camino en la izquierda.
|
|
|
|
[[Animación básica con acumuladores]](/notas/animacion-basica.html)
|
|
|
|
```java
|
|
// 1) variable para almacenar la posición horizontal del punto
|
|
float px;
|
|
|
|
void setup(){
|
|
size(400, 400);
|
|
strokeWeight(10);
|
|
stroke(255);
|
|
|
|
px = 0; // 2) valor inicial de posición
|
|
}
|
|
|
|
void draw(){
|
|
background(0);
|
|
// 3) dibuja el punto con pos. horizontal: px
|
|
// y posición vertical: 200
|
|
point(px, 200);
|
|
|
|
// 4) incrementa la posición horizontal
|
|
px = px + 2;
|
|
// 5) y si llega al borde derecho, reinicia
|
|
if(px > width){
|
|
px = 0;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Múltiples variables, sin arreglos
|
|
|
|
Supongamos que queremos tener más puntos moviéndose de la misma manera, pero empezando en diferentes posiciones.
|
|
|
|
Previo a utilizar arreglos, lo que haríamos sería crear una variable por cada punto y repetir por cada una los 5 pasos del ejemplo previo.
|
|
|
|
Un ejemplo con tres puntos se vería así:
|
|
|
|
```java
|
|
// 1) variables para almacenar las posiciones horizontales de los puntos
|
|
float px1, px2, px3;
|
|
|
|
void setup(){
|
|
size(400, 400);
|
|
strokeWeight(10);
|
|
stroke(255);
|
|
|
|
// 2) valor inicial de posición
|
|
px1 = 0;
|
|
px2 = 50;
|
|
px3 = 200;
|
|
}
|
|
|
|
void draw(){
|
|
background(0);
|
|
// 3) dibuja los puntos con pos. horizontal: px
|
|
// y posición vertical: 200
|
|
point(px1, 200);
|
|
point(px2, 200);
|
|
point(px3, 200);
|
|
|
|
// 4) incrementa las posiciones horizontales
|
|
px1 = px1 + 2;
|
|
px2 = px2 + 2;
|
|
px3 = px3 + 2;
|
|
|
|
// 5) y si alguna llega al borde derecho, reinicia
|
|
if(px1 > width){
|
|
px1 = 0;
|
|
}
|
|
if(px2 > width){
|
|
px2 = 0;
|
|
}
|
|
if(px3 > width){
|
|
px3 = 0;
|
|
}
|
|
}
|
|
```
|
|
|
|
Tal vez con tres puntos todavía es manejable, pero imagina cómo se vería el código con 5, 10, o 100 puntos.
|
|
|
|
Los arreglos nos permitirán tener un código con una extensión al primero, aunque tengamos miles de puntos.
|
|
|
|
## Con arreglos
|
|
|
|
El mismo programa, con arreglos, podría quedar de la siguiente forma:
|
|
|
|
```java
|
|
// 1) arreglo para almacenar las posiciones horizontales de los puntos
|
|
float[] px;
|
|
|
|
void setup(){
|
|
size(400, 400);
|
|
strokeWeight(10);
|
|
stroke(255);
|
|
|
|
// 2) crea e inicializa arreglo con 3 puntos:
|
|
px = new float[3];
|
|
px[0] = 0;
|
|
px[1] = 50;
|
|
px[2] = 200;
|
|
}
|
|
|
|
void draw(){
|
|
background(0);
|
|
|
|
// por cada elemento del arreglo...
|
|
for (int i=0; i<px.length; i++) {
|
|
// 3) dibuja los puntos con pos. horizontal: px[i]
|
|
// y posición vertical: 200
|
|
point(px[i], 200);
|
|
|
|
// 4) incrementa la posición horizontal
|
|
px[i] = px[i] + 2;
|
|
|
|
// 5) y si alguna llega al borde derecho, reinicia
|
|
if (px[i] > width) {
|
|
px[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
# Notación
|
|
|
|
Los símbolos que nos van a indicar que estamos usando arreglos son los corchetes `[ ]`.
|
|
|
|
## Declaración
|
|
|
|
Declaramos un arreglo con su tipo de dato y los corchetes:
|
|
|
|
```java
|
|
float[] posiciones; // declara arreglo
|
|
```
|
|
|
|
## Creación
|
|
|
|
A diferencia de otras variables básicas, antes de poder usar un arreglo necesitamos crearlo.
|
|
|
|
Al crearlo, indicamos el número de elementos que contendrá:
|
|
|
|
```java
|
|
posiciones = new float[100]; // crea arreglo de 100 elementos
|
|
```
|
|
## Atributo `.length`
|
|
|
|
Los arreglos tienen un atributo `.length` que nos indica el número de elementos que contiene.
|
|
|
|
```java
|
|
println( posiciones.length ); // imprime tamaño del arreglo
|
|
```
|
|
|
|
## Asignación y lectura
|
|
|
|
Cada elemento del arreglo tiene un **índice** numérico con el cual lo podemos ubicar. Podemos visualizarlo también como una *dirección*.
|
|
|
|
Los elementos están numerados a partir de 0, y llegan hasta `.length - 1`.
|
|
|
|
Por ejemplo, un arreglo de 5 elementos tendrá los índices 0, 1, 2, 3, 4.
|
|
|
|
Accederemos a cada índice con los corchetes `[ ]`:
|
|
|
|
```java
|
|
posiciones[0] = 200; // asigna 200 a la primera posición del arreglo
|
|
posiciones[1] = 10; // asigna 10 a la segunda posición del arreglo
|
|
```
|
|
|
|
Esa notación la podemos utilizar en lugar de cualquier variable.
|
|
|
|
Por ejemplo, aquí la tercera posición del arreglo se comporta como acumulador, leyendo el valor del elemento, sumándole 5, y guardando el resultado en la misma posición:
|
|
|
|
```java
|
|
posiciones[2] = posiciones[2] + 5;
|
|
```
|
|
|
|
Cuando queremos utilizar un índice fuera del rango del arreglo, recibiremos un error `ArrayIndexOutOfBoundsException`.
|
|
|
|
## Declaración, creación y asignación
|
|
|
|
Alternativamente, podemos declarar y crear un arreglo directamente con una lista de elementos:
|
|
|
|
```java
|
|
float[] posiciones = { 200, 100, 50, 20 }; // declara y crea arreglo
|
|
```
|
|
|
|
El arreglo tendrá el tamaño correspondiente a la cantidad de elementos dados.
|
|
|
|
## Ciclos `for`
|
|
|
|
Una de las principales ventajas de los arreglos es que como podemos acceder a sus elementos a través de un valor numérico (el *índice*), podemos hacer que ese sea una variable que se incrementa de uno en uno (un *contador*).
|
|
|
|
La notación más utilizada es con una variable de tipo `int` llamada `i` que funciona como índice, y que recorre cada posición del arreglo con un ciclo `for` de la siguiente forma:
|
|
|
|
```java
|
|
for( int i=0; i<posiciones.length; i++){
|
|
// realiza acciones con posiciones[i]
|
|
}
|
|
```
|
|
|
|
Lo que escribiremos dentro del ciclo `for` requiere un trabajo previo de identificar qué acciones son las que tomamos por cada elemento del arreglo, qué tienen en común, para entonces abstraerlas en términos de `i`.
|
|
|
|
### Inicializaciones
|
|
|
|
Este ejemplo inicializa todos los valores del arreglo en 0:
|
|
|
|
```java
|
|
for( int i=0; i<posiciones.length; i++){
|
|
posiciones[i] = 0;
|
|
}
|
|
```
|
|
|
|
Y este asigna un valor aleatorio distinto a cada elemento:
|
|
|
|
```java
|
|
for( int i=0; i<posiciones.length; i++){
|
|
posiciones[i] = random(width);
|
|
}
|
|
```
|
|
|
|
Aquí le asignamos un valor dado por un acumulador:
|
|
|
|
```java
|
|
float x = 0;
|
|
for( int i=0; i<posiciones.length; i++){
|
|
posiciones[i] = x;
|
|
x = x + 10;
|
|
}
|
|
```
|
|
|
|
### Lectura
|
|
|
|
Este ejemplo dibuja tantos puntos como elementos del arreglo, usando el valor leído como posición horizontal:
|
|
|
|
```java
|
|
for( int i=0; i<posiciones.length; i++){
|
|
point( posiciones[i], 200 );
|
|
}
|
|
```
|
|
|
|
### Incrementos, condicionales
|
|
|
|
Este ciclo fue extraído del ejemplo de arriba. Aquí cada elemento del arreglo se incrementa y cuando supera un límite es reiniciado a 0
|
|
|
|
```java
|
|
for( int i=0; i<posiciones.length; i++){
|
|
posiciones[i] = posiciones[i] + 10;
|
|
if( posiciones[i] > width ){
|
|
posiciones[i] = 0;
|
|
}
|
|
}
|
|
```
|
|
|
|
# Multiplicidades
|
|
|
|
Podemos crear tantos arreglos como queramos. Si todos tienen el mismo tamaño, los podemos utilizar para referirse a diferentes características de una misma entidad.
|
|
|
|
Por ejemplo, los puntos del ejemplo de arriba pueden tener diferente posición vertical además de diferente posición horizontal. Este *sketch* inicializa 100 de ellos con posición aleatoria y los mueve en la misma dirección, reiniciándolos al llegar al final:
|
|
|
|
```java
|
|
// 1) arreglos para almacenar posiciones x,y de los puntos
|
|
float[] px;
|
|
float[] py;
|
|
|
|
|
|
void setup() {
|
|
size(400, 400);
|
|
strokeWeight(10);
|
|
stroke(255);
|
|
|
|
// 2) crea e inicializa arreglos con 100 elementos:
|
|
px = new float[100];
|
|
py = new float[100];
|
|
|
|
for (int i=0; i<px.length; i++) {
|
|
px[i] = random(width);
|
|
py[i] = random(height);
|
|
}
|
|
}
|
|
|
|
void draw() {
|
|
background(0);
|
|
|
|
// por cada elemento del arreglo...
|
|
for (int i=0; i<px.length; i++) {
|
|
// 3) dibuja los puntos con pos. horizontal: px[i]
|
|
// y posición vertical py[i]
|
|
point(px[i], py[i]);
|
|
|
|
// 4) incrementa la posición horizontal
|
|
px[i] = px[i] + 2;
|
|
|
|
// 5) y si alguna llega al borde derecho, reinicia
|
|
if (px[i] > width) {
|
|
px[i] = 0;
|
|
}
|
|
|
|
}// cierra ciclo for
|
|
|
|
}
|
|
|
|
```
|
|
|
|
¿Cómo harías que los puntos se muevan en el eje vertical en vez del horizontal?
|
|
|
|
¿Cómo harías que al llegar al borde derecho, los puntos cambien su posición vertical a una nueva posición aleatoria?
|
|
|
|
¿Cómo harías que cada punto tuviera una velocidad distinta?
|