Simon (juego)

El juego Simon es originariamente un juego electrónico creado en 1978 basado en el juego Simon says («Simón dice»), en el cual uno de los participantes dice «Simón dice» y una acción, y el resto de participantes deben realizar dicha acción.

El juego electrónico Simon tenía forma de disco y estaba dividido en cuatro cuadrantes, cada uno con un botón de un color (verde, rojo, azul y amarillo). Estos botones de colores se iluminan de forma aleatoria, a la vez que emiten un sonido propio de cada uno de ellos. Una vez finalizada la secuencia aleatoria, el usuario debe reproducir dicha secuencia en el orden correcto pulsando los botones para ello. El usuario deberá emplear su memoria visual y auditiva para llevar a cabo el juego correctamente, así como su capacidad de atención. Si responde correctamente a la secuencia se reproducirá una nueva pero de mayor longitud, y así sucesivamente. La dificultad del juego vendrá determinada por la longitud de la secuencia, así como por la velocidad a la que se presenta la misma.

El juego ha evolucionado de manera que existen versiones con efectos visuales y sonoros mejorados, o con colores nuevos añadidos a mayores de los cuatro originales.

El audio es una parte muy importante del juego. Puede aumentarse la dificultad eliminándolo o disminuir la dificultad empleando sonidos más familiares (por ejemplo animales).

Actualmente existen versiones del juego en formato digital (videojuegos) en diversas plataformas: web, pc, dispositivos móviles, etc.

Nuestro juego Simon dispondrá de las siguientes variables de entrada al jugador:

  • Audio: sí o no. Esta opción activará o desactivará el audio del juego, lo cual cambiará la dificultad del juego.
  • Velocidad: 1, 2, 3,… Esta opción permitirá al jugador variar la velocidad a la que se presenta la secuencia en el juego, lo cual aumentará su dificultad.
  • Número de botones: 4-x (siendo x un número aún por determinar). Esta opción hará variar el número de botones presentes en el juego; a mayor número mayor será la dificultad.
  • Movimiento de los botones: sí o no. Esta opción permitirá indicar si deseamos que los botones se mantengan siempre en la misma posición (versión clásica) o si deseamos que vayan rotando, variando así su posición original.

Respecto a las variables de salida que mostrarán la información del juego al jugador:

  • Aciertos: mostrará el número de aciertos totales acumulados por parte del jugador.
  • Errores: mostrará el número de errores totales acumulados por parte del jugador.
  • Tiempo medio de respuesta: mostrará el tiempo medio que tarda el jugador en responder a cada elemento de la secuencia.
  • Nivel actual: mostrará el nivel en el que se encuentra en ese momento el jugador.
  • Nivel final: mostrará el nivel alcanzado por el jugador al final de la partida.

Collections

En la programación orientada a objetos, a menudo trabajaremos con grupos de objetos. Los arrays carecen de la flexibilidad que necesitamos para el rápido desarrollo de aplicaciones. Su tamaño no pueden ser cambiado. Afortunadamente, en .NET Framework posee un conjunto de interfaces y clases para trabajar con grupos de objetos de manera más fácil. Estas están incluidas en System.Collections, que contiene tipos no genéricos que más o menos han sido reemplazados por los tipos genéricos incluidos en System.Collections.Generic.

Una colección es un objeto que agrupa otros objetos. Provee métodos para almacenar, recuperar y manipular sus elementos.

Las clases más importantes de System.Collections.Generic son List, HashSet, Queue y Dictionary.

List, HashSetQueue son similares, son usadas para almacenar objetos del mismo tipo. Dictionary es bueno para almacenar key/value pairs.

La clase List

Una List es similar a un array pero con más flexibilidad. En un array debemos especificar su tamaño, que no podrá ser cambiado, y en el caso de una List especificar su tamaño es opcional. Según se van añadiendo nuevos elementos a una List, su tamaño aumentará automáticamente si ya no hay espacio disponible.

List es una clase genérica, como tal necesitas decirle al compilador que tipo de objeto quieres almacenar. Así es como creas una lista de strings:

List<string> animals = new List<string>();

Si deseamos especificar un tamaño inicial de 10:

List<string> animals = new List<string>(10);

En ambos casos la capacidad aumentará automáticamente si se necesitan almacenar nuevos elementos y ya se ha superado la capacidad existente. No obstante, si sabemos cuantos elementos serán almacenados en la List sería una buena idea asignar una capacidad inicial correspondiente, así evitaremos perder tiempo en aumentar el tamaño de la List.

Para añadir un elemento a la List se llamará al método Add. Para saber cuantos elementos contiene la List se llamará a la propiedad Count.

Para recuperar un elemento de una List usaremos la propiedad Item. Para ello le pasaremos un índice a la variable List como si fuera un array, tal que así:

myList[0]

El primer elemento estará en la posición 0, el siguiente en la 1 y así sucesivamente.

Finalmente, para recorrer todos los elementos de una List usaremos un bucle foreach.

foreach (T element in myList)
{
// do something with element
}

Ahora se mostrará un lista con algunos de los métodos más importantes en List.

public void Add(T item)

Añade un objeto a la List. El objeto podría ser null y será puesto al final de la lista.

public void Clear()

Elimina todos los objetos de la List y establece la propiedad Count a 0.

public bool Contains(T item)

Pregunta si un elemento está en la List y devuelve true si está. Si no está devuelve false.

public T Find(Predicate<T> match)

Inspecciona la List y devuelve el primer elemento que coincide con la condición especificada.

public void Insert(int index, T item)

Añade un elemento en la posición indicada por el índice.

public bool Remove(T item)

Elimina el elemento especificado de la List. Devolverá true si el elemento fue eliminado satisfactoriamente o false en caso contrario.

public void RemoveAt(int index)

Elimina el elemento especificado por el índice. Si este es 0 elimina el primer elemento de la lista.

public void Sort()

Ordena la List usando un comparador por defecto.

public T[] ToArray()

Devuelve los elementos como un array.

A continuación se muestra un ejemplo del uso de la clase List donde se almacenan strings y se recorre usando foreach. En la consola de Unity se muestra el resultado correspondiente.

ListExample

La clase HashSet

Un set es una estructura de datos que puede almacenar valores sin ningún orden en particular y no permite duplicados. Un hash set es un conjunto que está implementado usando una hash table. El término hash se refiere a la función usada para computar un índice de un elemento para que ese elemento pueda ser recuperado rápidamente.

La clase HashSet representa un hash set. HashSet posee los métodos AddClear, que funcionan del mismo modo que en List, al igual que la propiedad Count que devuelve el número de elementos en el HashSet. Sin embargo, a diferencia de ListHashSet no permite duplicados. Además, no podemos añadir o eliminar un elemento en un índice específico. No existe siquiera una propiedad Item para recuperar un elemento en una posición concreta.

Por otra parte, HashSet provee métodos que son útiles para trabajar con conjuntos, como IsSubsetOfIsSupersetOf.

Ahora se mostrará un lista con algunos de los métodos más importantes en HashSet.

public bool Add(T item)

Añade un objeto nuevo HashSet. Si el elemento añadido ya está en el HashSet, no será añadido de nuevo y el método devolverá false.

public void Clear()

Elimina todos los objetos de la HashSet y establece la propiedad Count a 0.

public bool Contains(T item)

Pregunta si un elemento está en la HashSet y devuelve true si está. Si no está devuelve false.

public bool IsSubsetOf(IEnumerable other)

Determina si el HashSet es un subconjunto de la colección especificada.

public bool IsSupersetOf(IEnumerable other)

Determina si el HashSet es un superconjunto de la colección especificada.

A continuación se muestra un ejemplo del uso de la clase HashSet donde se almacenan strings. En la consola de Unity se muestra el resultado correspondiente.

HashSetExample

La clase Queue

Una Queue es una colección como ListHashSet. Lo que hace destacar a Queue es el hecho de que podemos recuperar un elemento y eliminarlo al mismo tiempo usando el método Dequeue. Para recuperar un elemento sin eliminarlo se usará el método Peek.

Cuando añadimos un elemento a una Queue usando el método Enqueue, el elemento es añadido al final de la cola. Cuando usamos DequeuePeek, se obtiene un elemento del principio de la cola. Por tanto, Queue es un sistema first-in-first-out(FIFO), el primero que entra es el primero que sale de la cola.

Ahora se mostrará un lista con algunos de los métodos más importantes en Queue.

public void Enqueue(T item)

Añade un elemento nuevo al final de la Queue. El elemento añadido puede ser null.

public void Clear()

Elimina todos los elementos de la Queue y establece la propiedad Count a 0.

public bool Contains(T item)

Determina si un elemento está en la Queue y devuelve true de ser así. De otro modo devolverá false.

public T Dequeue()

Devuelve el elemento del principio de la Queue y lo elimina de la Queue.

public T Peek()

Devuelve el elemento del principio de la Queue sin eliminarlo de la Queue.

A continuación se muestra un ejemplo del uso de la clase Queue donde se almacenan strings. En la consola de Unity se muestra el resultado correspondiente.

QueueExample

La clase Dictionary

La clase Dictionary es un modelo para la creación de contenedores que toman key/value pairs. El Dictionary es adecuado para almacenar elementos que consisten en una clave y un valor, como un ISBN y un objeto Book o un país y una capital.

Para construir un Dictionary pasamos el tipo de la clave y el tipo del valor a su constructor. Por ejemplo, el siguiente fragmento de código crea un Dictionary que toma un string como clave y un objeto Book como valor.

Dictionary books = new Dictionary(string, Book);

Al igual que otras colecciones, tenemos un método Add para añadir un par clave/valor a un Dictionary y un método Clear para eliminar todos sus elementos.

Para recuperar un valor usamos la propiedad Item. Por ejemplo, si un Dictionary contiene un par país/capital, usamos esta sintaxis para recuperar un valor:

string selectedCountry = countryDictionary[countryName];

A continuación se muestra un ejemplo del uso de la clase Dictionary donde se almacenan pares país/capital. En la consola de Unity se muestra el resultado correspondiente.

DictionaryExample