If you're seeing this message, it means we're having trouble loading external resources on our website.

Si estás detrás de un filtro de páginas web, por favor asegúrate de que los dominios *.kastatic.org y *.kasandbox.org estén desbloqueados.

Contenido principal

Caminatas aleatorias

Antes de entrar en las complejidades de los vectores y el movimiento basado en la física, pensemos en lo que significa que algo simplemente se mueva por la pantalla. Empecemos con una de las simulaciones de movimiento más conocidas y más sencillas: la caminata aleatoria.
Imagina que estás parado en medio de una viga de equilibrio. Cada diez segundos, lanzas una moneda. Águila, da un paso adelante. Sol, da un paso hacia atrás. Esta es una caminata aleatoria: una ruta definida como una serie de pasos aleatorios. Si te bajas de la viga de equilibrio y estás en el suelo, puedes realizar una caminata aleatoria en dos dimensiones lanzando esa misma moneda dos veces con los siguientes resultados:
Lanzamiento 1Lanzamiento 2Resultado
ÁguilaÁguilaUn paso hacia adelante.
ÁguilaSolUn paso a la derecha.
SolÁguilaUn paso a la izquierda.
SolSolUn paso hacia atrás.
Sí, esto puede parecer un algoritmo particularmente poco sofisticado. Sin embargo, las caminatas aleatorias pueden utilizarse para modelar fenómenos que ocurren en el mundo real, desde movimientos de moléculas en un gas hasta el comportamiento de un apostador que pasa un día en el casino. En cuanto a nosotros, comenzamos este tema estudiando una caminata aleatoria con tres objetivos en mente.

El objeto del caminante aleatorio (Walker)

Primero revisemos un poco de programación orientada a objetos (POO) al construir un objeto Walker. Esta será solo una revisión superficial. Si nunca has trabajado con POO antes, deberías pasar por la sección de JavaScript Orientado a Objetos.
Un objeto en JavaScript es un tipo de datos que tiene tanto propiedades como funcionalidad ligados a él, a través de su prototipo. Estamos buscando diseñar un objeto Walker que realice un seguimiento de sus datos (dónde existe en la pantalla) y que tenga la capacidad de realizar ciertas acciones (como dibujarse o dar un paso).
Para poder crear instancias de Walkers, necesitamos definir un objeto Walker. Usaremos ese objeto como el cortador de galletas, y cada nueva instancia de Walker es una galleta.
Comencemos por definir el tipo de objeto Walker. El Walker solo necesita dos piezas de datos: un número para su posición x y uno para su posición y. Esos los estableceremos en su función constructora, haciéndolos que estén en el centro de la pantalla.
var Walker = function() {
    this.x = width/2;
    this.y = height/2;
};
Además de hacer el seguimiento de su x y y, nuestro objeto Walker también tendrá métodos que podemos llamar sobre él. El primero será un método que le permita al objeto mostrarse como un punto negro. Recuerda que le agregamos métodos a un objeto en JavaScript al adjuntarlos al prototype (prototipo) del objeto.
Walker.prototype.display = function() {
    stroke(0, 0, 0);
    point(this.x, this.y);
};
El segundo método le indica al objeto Walker dar un paso. Ahora, aquí es donde las cosas se ponen un poco más interesantes. ¿Recuerdas ese piso en el que estábamos tomando pasos aleatorios? Bueno, ahora podemos usar nuestra pantalla en esa misma capacidad. Hay cuatro pasos posibles. Un paso a la derecha puede simularse al aumentar x (x++); a la izquierda al disminuir x (x--); hacia adelante al bajar un pixel (y++); y hacia atrás al subir un pixel (y--). ¿Cómo escogemos de estas cuatro opciones? Antes dijimos que podríamos lanzar dos monedas. Sin embargo, en ProcessingJS, cuando queremos escoger aleatoriamente de una lista de opciones, podemos escoger un número aleatorio al usar random().
Walker.prototype.walk = function() {
    var choice = floor(random(4));
};
La línea anterior de código escoge un número de punto flotante aleatorio entre 0 y 4 y lo convierte en un número natural mediante el uso de floor(), con un resultado de 0, 1, 2 o 3. Técnicamente hablando, el número mayor nunca será 4.0, sino más bien 3.999999999 (con tantos 9s como cifras decimales tenga); como floor() regresa el número natural más cercano que sea menor o igual, el resultado más alto que podemos tener es 3. A continuación, damos el paso apropiado (izquierda, derecha, arriba o abajo) dependiendo de qué número aleatorio haya sido escogido.
Walker.prototype.walk = function() {
    var choice = floor(random(4));
    if (choice === 0) {
        this.x++;
    } else if (choice === 1) {
        this.x--;
    } else if (choice === 2) {
        this.y++;
    } else {
        this.y--;
    } 
};
Ya que escribimos la clase, es hora de hacer un objeto Walker verdadero en nuestro programa. Suponiendo que estamos buscando modelar una caminata aleatoria sencilla, declaramos e inicializamos una variable global de tipo Walker, al llamar la función constructora con el operador new (nuevo).
var w = new Walker();
Ahora, para hacer que el caminante haga algo en realidad, definimos la función draw() y le decimos al caminante que dé un paso y se dibuje cada vez que se llama:
draw = function() {
    w.walk();
    w.display();
};
Como no llamamos a background() en la función de dibujo, podemos ver la estela de la caminata aleatoria sobre nuestro lienzo:

Mejorar el caminante aleatorio

Hay un par de mejoras que podríamos hacerle al caminante aleatorio. Por ejemplo, las alternativas de los pasos de este caminante están limitadas a cuatro opciones: arriba, abajo, izquierda y derecha. Pero cualquier pixel en la ventana tiene ocho vecinos posibles, y una novena posibilidad es permanecer en el mismo lugar.
Imagen de la Naturaleza del Código
Figura I.1
Para implementar un objeto Walker que pueda dar un paso a cualquier pixel vecino (o quedarse quieto), podemos escoger un número entre 0 y 8 (nueve opciones posibles). Sin embargo, una forma más eficiente de escribir el código sería simplemente escoger entre tres pasos posibles a lo largo del eje x (-1, 0 o 1) y tres pasos posibles a lo largo del eje y.
Walker.prototype.walk = function() {
  var stepx = floor(random(3))-1;
  var stepy = floor(random(3))-1;
  this.x += stepx;
  this.y += stepy;
};
Llevando esto más lejos, en vez de eso, podríamos utilizar un decimal para x y y y movernos de acuerdo con un valor arbitrario aleatorio entre -1 y 1, si nuestro entorno en realidad pudiera desplegar la diferencia entre "2.2" y "2.4":
Walker.prototype.walk = function() {
  var stepx = random(-1, 1);
  var stepy = random(-1, 1);
  this.x += stepx;
  this.y += stepy;
};
Todas estas variaciones en la caminata aleatoria “tradicional” tienen una cosa en común: en cualquier momento en el tiempo, la probabilidad de que el Walker decida tomar un paso en una dirección dada (o no moverse para nada) es igual a la probabilidad de que el Walker tome cualquier otra opción dada. En otras palabras, si hay cuatro pasos posibles, hay una probabilidad de 1 en 4 (o del 25%) de que el Walker dé cualquier paso dado. Con nueve pasos posibles, es una probabilidad de 1 en 9 (o del 11.1%).
De manera conveniente, así es como trabaja la función random(). Su generador de números aleatorios produce lo que se conoce como una distribución “uniforme” de números. Podemos probar esta distribución con un programa que cuente cada vez que un número aleatorio es elegido y lo grafique como la altura de un rectángulo:
¿Todas las barras son de la misma altura, después de unos minutos de estarse ejecutando? Probablemente no. El tamaño de nuestra muestra (es decir, el número de números aleatorios que hemos escogido) es más bien pequeño y hay algunas discrepancias ocasionales, donde ciertos números son escogidos más a menudo. Con el tiempo, con un buen generador de números aleatorios, esto se emparejaría.
Los números aleatorios que obtenemos de la función random() no son verdaderamente aleatorios; por lo tanto se conocen como “pseudoaleatorios”. Son el resultado de una función matemática que simula la aleatoriedad. Esta función produciría un patrón a través del tiempo, pero ese periodo de tiempo es tan largo para nosotros, ¡que es tan bueno como aleatoriedad pura!
En la siguiente sección, hablaremos acerca de diferentes maneras en que podemos crear caminantes con "tendencias" para caminar en ciertas direcciones. Antes de que te sumerjas en eso, ¡hay un reto que te espera!

Este curso de "Simulaciones Naturales" es un derivado de "La Naturaleza del Código" por Daniel Shiffman, usado bajo una Licencia Creative Commons Reconocimiento-NoComercial 3.0 Unported.

¿Quieres unirte a la conversación?

¿Sabes inglés? Haz clic aquí para ver más discusiones en el sitio en inglés de Khan Academy.