lunes, 22 de julio de 2013

15-Puzzle: Estructura y programación

La segunda entrada de este blog pretende explicar cómo se realiza el mini-juego llamado 15-Puzzle. Este juego consiste de 15 piezas enumeradas del 1 al 15 que son dispuestas aleatoriamente en un tablero de 16 espacios. Por lo tanto, siempre queda un espacio libre por medio del cual se puede realizar el movimiento de las fichas con el fin dejarlas organizadas numéricamente. Algunas variaciones de este juego incluyen: un mayor o menor número de fichas o tiene como objetivo organizar las fichas de tal forma que quede armada una imagen.

Inicio del juego


















Fin del juego


















Este pequeño juego será desarrollado por medio de lenguajes que se ejecutan en el lado del cliente: html y javascript. Para facilitar un poco las cosas se hará uso de la biblioteca de JavaScript llamada jQuery. 

Estructura

Es importante que antes de comenzar a escribir código desenfrenadamente, se piense un poco en la estructura del programa que se desea realizar. De esta forma se puede ahorrar mucho tiempo y se pueden evitar algunos errores de lógica básicos desde el principio. Naturalmente, con frecuencia no se puede pensar en absolutamente todos los detalles; sin embargo, esto siempre puede brindar una base sólida para comenzar.

En este primer programa se intentará pensar una estructura basada en la programación orientada a objetos. Así se puede pensar en las diferentes clases (que son los “moldes” de nuestros objetos) que interactuarán en el juego y los métodos que cada una de ellas debe poseer.Este juego está formado básicamente por dos clases: la que representa el juego en general y la que representa cada ficha del juego.

Clase Ficha

Atributos:

·       Valor numérico de la ficha: este atributo ayudará a identificar la ficha (¿es la 1, la 2 o qué número tiene la ficha?).
·       Posición correcta: este atributo puede tomar el valor de falso o verdadero. Es el que indicará si la ficha se encuentra en la posición correcta en el tablero.
·       Posición actual en X: Este atributo indica en qué fila se encuentra actualmente la ficha en el tablero de 4 x 4. Puede tomar un valor de 1 a 4 para indicar cualquiera de las 4 filas.
·       Posición actual en Y: Este atributo indica en qué columna se encuentra actualmente la ficha en el tablero de 4 x 4. Puede tomar un valor de 1 a 4 para indicar cualquiera de las 4 columnas.
·        Posición correcta en X: Este atributo indica en qué fila del tablero de 4 x 4 se debe encontrar la ficha para que su posición sea la correcta. Puede tomar un valor de 1 a 4.
·       Posición correcta en Y: Este atributo indica en qué columna del tablero de 4 x 4 se debe encontrar la ficha para que su posición sea la correcta. Puede tomar un valor de 1 a 4.

Métodos: La clase Ficha no requiere de ningún método especial.

Constructor: El constructor de la clase ficha, que es una función que nos permite inicializar algunos de sus atributos, nos debe dar la posibilidad de inicializar el valor de la ficha, su posición actual en X, su posición actual en Y, su posición correcta en X y su posición correcta en Y. Además, debe garantizar que toda ficha que se cree inicialmente tenga su atributo posición correcta en false.

Clase Juego

Atributos:

·       Cuenta de fichas en la posición incorrecta: Esta variable se usa con el fin de contar el número de fichas que actualmente están en la posición incorrecta. Así, cada vez que se mueve una ficha, se verifica dependiendo de su posición actual si se le debe sumar o restar a la variable aquí descrita.
·       Vector de fichas: Es un vector de dieciséis posiciones donde cada posición consta de un objeto ficha. En este juego el espacio en blanco se asumirá como una ficha más. Es por eso que este vector consta de dieciséis posiciones y no de quince. En la última posición siempre se colocará la “ficha” que simula el espacio.

Métodos:

A continuación se describen los métodos de esta clase que son los que finalmente le dan toda la funcionalidad al juego.

Inicializar juego: Este método permite realizar todas las configuraciones iniciales del juego: distribuir aleatoriamente las posiciones de cada ficha y verificar si esa distribución representa un juego solucionable. Este método crea un vector de 15 posiciones con los números del 1 al 15 desorganizados de forma aleatoria por medio de una función que se explicará más adelante (Random). Después, por medio de otro método descrito más adelante, se comprueba si esta distribución aleatoria se puede usar para crear un juego solucionable (este juego tiene la particularidad de que solo el 50% de todas las distribuciones aleatorias que se pueden generar forman un juego solucionable). Si la distribución representa un juego solucionable, este vector se usa después para asignar las posiciones actuales de cada ficha creada; si no, el vector es desorganizado nuevamente hasta obtener una distribución que represente un juego solucionable. El siguiente paso es recorrer el vector de fichas y colocar una ficha nueva en cada una de sus posiciones. A cada ficha se le asigna su valor, su posición actual (tanto en X como en Y) con ayuda del vector de números desorganizados y su posición correcta (tanto en X como en Y). Para realizar la asignación de posiciones (posiciones actuales y posiciones correctas), se usan las operaciones de división (usando solo la parte entera del resultado) y de módulo. Lo que obtenemos como resultado de este método es un vector de fichas con sus respectivas posiciones actuales (que representan el desorden del juego), sus posiciones correctas (que representan el orden del juego) y los valores de cada ficha. Además, en la posición número 16 del vector se crea una ficha con valor numérico 16, posición correcta (4,4) y posición actual (4,4). Ésta representa el espacio en blanco, lo cual quiere decir que sin importar como hayan quedado ubicadas las demás fichas el espacio en blanco siempre empezará en la posición de la esquina inferior derecha del tablero.

Es solucionable: Este método nos permite ingresar un vector desorganizado con números del 1 al 15 y, usando la lógica de nuestro juego, averiguar si el vector tiene una distribución que representa un juego solucionable o no. Esta función se explicará línea a línea en los comentarios del código. Su lógica general está explicada en el siguiente video: http://www.youtube.com/watch?v=TKXiHdgOHaU

Mover ficha: Este método recibe como parámetro un objeto Ficha. Permite verificar si es posible mover una ficha (porque tiene el espacio blanco como vecino de alguno de sus cuatro lados) o si no es posible. En caso de que sea posible, la función realiza el movimiento de la ficha y devuelve como valor true; si no, sencillamente devuelve false. Para verificar si el movimiento de la ficha es posible, se restan las posiciones en X de la ficha y el espacio en blanco y se almacena el resultado. Después, se realiza la misma operación con las posiciones en Y. Si al sumar los dos resultados el valor absoluto de la suma es igual a 1, el movimiento de la ficha es posible; de lo contrario, no. Esto se debe a que la ficha solo se puede mover cuando se encuentra en la misma fila del espacio en blanco (entonces el resultado de la resta da 0), pero en la columna adyacente (el resultado de la resta da 1 o -1); o viceversa. Si la ficha se puede mover, se intercambian las posiciones actuales del espacio en blanco y de la ficha y además, se llama al método verificar posición para que este aumente o disminuya la cuenta de fichas en la posición incorrecta; si no se puede realizar el movimiento; la función no hace nada y se retorna false.

Verificar posición: Este método recibe como parámetro un objeto Ficha. Se llama cada vez que una se realiza el movimiento de una ficha y tiene la función de modificar la cuenta de fichas en la posición incorrecta según sea necesario. Si la ficha se mueve de una posición correcta a una incorrecta, se le suma a la cuenta de fichas en la posición incorrecta; si se mueve de una posición incorrecta a una correcta, se le resta a la cuenta de fichas en la posición incorrecta; pero si se mueve de una posición incorrecta a otra posición incorrecta la cuenta de fichas en la posición incorrecta queda intacta. Esta función usa las posiciones actuales XY y las posiciones correctas XY de la ficha para saber si coinciden. Además usa el atributo de la ficha llamado posición correcta (que tiene valor de falso o verdadero) para saber en qué estado estaba antes de que la ficha fuera movida.

Verificar juego: Este es el método de la clase Juego que permite saber si el juego está con todas sus fichas organizadas o si no. Este método solo tiene que revisar la cuenta de fichas en la posición incorrecta y si ésta está en cero, el juego está completamente organizado; si no, el juego aún tiene fichas que se encuentran ubicadas incorrectamente.

Dibujar tablero: Los métodos descritos anteriormente a este, son los que manejan el funcionamiento del juego de una forma virtual; sin embargo, se necesita de una interfaz gráfica para poder enviar las órdenes de movimientos y poder visualizar los resultados de cada instrucción dada al juego. Este método es el que se encarga de dibujar el tablero gráficamente y así poder por medio de la interfaz gráfica manejar todos los objetos que representan nuestro juego. Para realizar este trabajo usamos jQuery. Primero dibujamos el tablero del tamaño que se indica por medio del parámetro que recibe este método. Este consiste en dos etiquetas <section> anidadas para construir el borde grueso del tablero. Después se recorre el vector de fichas y se dibuja cada una de acuerdo a su posición actual XY. Esto se hace usando posicionamiento absoluto en la hoja de estilos y adaptando los atributos top y left (se adaptan de acuerdo a la posición actual XY de cada ficha) de cada <div> que representa una ficha. Al final, se obtiene el tablero dibujado con sus respectivas fichas desorganizadas aleatoriamente.

Función Random

Esta función tiene la capacidad de recibir un vector con ciertos valores y devolver un vector cuyos valores aparecen desorganizados aleatoriamente. En el juego esta función fue usada para desordenar el vector creado con los números del 1 al 15. Lo que hace esta función es recorrer todas las posiciones del vector e intercambiar su valor por el valor que tiene el vector en otra posición escogida aleatoriamente. Así, al final se obtiene un vector con los mismos valores pero con un orden diferente al original.

Programación

En esta sección se muestra como se implementa en código JavaScript la lógica del juego que se definió anteriormente. Para reforzar la explicación dada anteriormente el código mostrado tiene comentarios que ayudan a entender el programa. Un profesor de la universidad me dejó la extraña manía de querer programar con palabras en inglés (o al menos intentarlo), espero que esto no sea inconveniente.

Clase Ficha


var Piece = function(value,rigthPosX,rigthPosY,posX,posY)
{
 this.value = value; //Valor numérico de la ficha
 this.isRigthPosition = false; //Variable que indica si la ficha se encuentra en la posición correcta
 this.posX = posX; //Variable que indica la fila actual en la que se encuentra la ficha (tablero 4x4)
 this.posY = posY; //Variable que indica la columna actual en la que se encuentra la ficha (tablero 4x4)
 this.rigthPosX = rigthPosX; //Variable que indica la fila en la que debería esta la ficha para estar en la posición correcta
 this.rigthPosY = rigthPosY; //Variable que indica la columna en la que debería esta la ficha para estar en la posición correcta
}  

Clase Juego


var Game = function()
{
 this.isWrongCount = 0; //Cuenta el número de fichas que se encuentran actualmente en la posición incorrecta
 this.piecesArray = new Array(); //Vector que contiene las 15 fichas y el espacio (simulado como otra ficha)

 //Este método permite hacer las configuraciones iniciales del juego. Ejemplo: repartir las fichas aleatoriamente.
 this.initializeGame = function()
 {
  var randomArray = new Array(); //Variable local que ayuda a generar el orden aleatorio de la posición de las fichas
  //Este for ayuda a llenar el vector con números del 1 al 15 (ordenadamente) 
  for(var i=0;i<15;i++)
   randomArray[i] = i+1;
  // Se usa este do-while para desorganizar el vector randomArray hasta que el nuevo "orden" represente una solución
  // para el juego. El método (función) que nos ayuda a esto es la llamada isSolvable.
  do
  {
   randomArray = Random(randomArray); //Se almacena en la misma variable el vector con un nuevo orden aleatorio
  }
  while(!this.isSolvable(randomArray)); //Se verifica si representa un juego solucionable

  // Este ciclo se usa para recorrer el vector de fichas y crear una nueva ficha en las 
  // primeras 15 posiciones del vector   
  for(var i=0;i<15;i++)
  {
   // Se inicializa una ficha en cada posición del vector. Su valor con (i+1) para representar los números
   // del 1 al 15, su posición correcta usando los valores de i (que está iterando en orden) y las operaciones
   // de división y módulo; y su posición inicial en el juego usando los valores del vector randomArray y nuevamente
   // las operaciones de división y módulo. 
   this.piecesArray[i] = new Piece(i+1,Math.floor(i/4+1),(i%4)+1,Math.floor((randomArray[i]-1)/4)+1,((randomArray[i]-1)%4)+1);

   //Con este condicional se comprueba si la ficha en su posición incial concidencialmente quedó en la posición correcta
   if((this.piecesArray[i].posX != this.piecesArray[i].rigthPosX) || (this.piecesArray[i].posY != this.piecesArray[i].rigthPosY))
    this.isWrongCount++; //Se le suma 1 a la cuenta de fichas en la posición incorrecta
   else
    this.piecesArray[i].isRigthPosition = true; //Simplemente se coloca la variable isRigthPosition de esa ficha en true
  }
  //Finalmente se inicializa el espacio en blanco con valor de ficha 16 y posición inicial y correcta (4,4)
  this.piecesArray[15] = new Piece(16,4,4,4,4);    
 }

 //Esta función nos ayuda a verificar si la distribución del vector aleatorio representa un juego con solución
 this.isSolvable = function(random_array)
 {
  var control_sum = 0; //Se inicializa la variable suma en 0

  // El vector de control nos ayuda a almacenar la cantidad de números menores que se encuentran a la derecha del
  // número que se esta examinando. Así, control_array[i] almacena la cantidad de números menores a la derecha de
  //  test_array[i].
  var control_array = new Array();  
  // En este vector (test_array) quedan finalmente, organizados de izquierda a derecha y de arriba a abajo, 
  // los números del tablero del juego.
  var test_array = new Array();
  // En esta variable se almacena el tamaño del 
  // vector (que es el mismo para cualquiera de los otros vectores)
  var length = random_array.length; 
  //Este primer ciclo sirve para ubicar los números en test_array de acuerdo a la distribución aleatoria
  for(var i=0;i<length;i++) 
   test_array[random_array[i]-1] = i+1;
  //Este ciclo inicializa todas las posiciones del vector de control en 0
  for(var i=0;i<length;i++)
   control_array[i] = 0;
  //En este ciclo se cuenta la cantidad de números menores a la derecha de test_array[i] y se suman en control_array[i]
  for(var i=0;i<length;i++)
  {
   for(var j=i+1;j<length;j++)
   {
    if(test_array[j]<test_array[i])
     control_array[i]++;
   }
   control_sum += control_array[i]; //Se realiza una suma de todas las posiciones de control_array
  } 

  //Si la suma es par, el juego tiene solución; si no, no tiene solución. 
  if(control_sum % 2 == 0)
   return true;
  else
   return false;
 }

 //Esta función es la que dibuja el tablero de juego en html
 this.drawBoard = function(pixel_size)
 {
  //Se le agrega a la etiqueta body un tablero de tamaño pixel_size que esta formado por dos divs anidados
  //la proporción entre los divs esta especificada en el archivo .css usando los ids agregados aquí.
  $("body").append('<section id="game_board" style="height:'+pixel_size+'px;width:'+pixel_size+'px;"><section id="piece_container"></section></section>');
  // Por medio de este ciclo se adicionan las fichas ubicadas segun su posición inicial en filas y en columnas.
  //Se usan porcentajes para ubicarlas a 0, 25, 50 y 75% del borde del tablero. Cada ficha mide el 25% del tablero (archivo .css)
  for(var i=0;i<15;i++)
   $("#piece_container").append('<div class="game_piece" style="top:'+((this.piecesArray[i].posX-1)*25)+'%;left:'+((this.piecesArray[i].posY-1)*25)+'%"><div class="number_container">'+this.piecesArray[i].value+'</div></div>');  
 }

 // Este método verifica si una ficha se encuentra en su posición correcta y modifica la cuenta de fichas 
 // en la posición incorrecta
 this.checkPosition = function(piece)
 {
  //Mira si la posición actual de la ficha coincide con la posición correcta de la misma
  if((piece.posX == piece.rigthPosX) && (piece.posY == piece.rigthPosY)) 
  {
   piece.isRigthPosition = true; // Actualiza el valor de posición correcta de esa ficha
   this.isWrongCount--; // Le resta uno a la cuenta de fichas en la posición incorrecta
  }
  else
  {
   if(piece.isRigthPosition) //Mira cuál era el estado de posición correcta anterior de la ficha.
   {
    //Si entra a este if quiere decir que la ficha se movió de una posición incorrecta a una correcta
    piece.isRigthPosition = false;// Actualiza el valor de posición correcta de esa ficha
    this.isWrongCount++;// Le suma a la cuenta de fichas en la posición incorrecta
   }
  }
 }


 //Este método representa el movimiento de una ficha al espacio en blanco
 this.movePiece = function(piece_number)
 {
  //Se hace una resta entre la posición en fila de la ficha y la del espacio en blanco
  var test_posX = this.piecesArray[piece_number-1].posX - this.piecesArray[15].posX;
  //Se hace una resta entre la posición en columna de la ficha y la del espacio en blanco
  var test_posY = this.piecesArray[piece_number-1].posY - this.piecesArray[15].posY;
  var wasMoved = false; //Se inicializa la variable que se va a retornar
  if(Math.abs(test_posX) + Math.abs(test_posY) == 1) //Se verifica que la suma de los valores absolutos sea igual a 1
  {
   var auxX = this.piecesArray[piece_number-1].posX; //Se almacena momentaneamente la fila de la ficha
   var auxY = this.piecesArray[piece_number-1].posY; //Se almacena momentaneamente la columna de la ficha
   //Se asigna el valor de fila de el espacio en blanco que siempre está en la última posición del vector de fichas
   this.piecesArray[piece_number-1].posX = this.piecesArray[15].posX; 
   //Se asigna el valor de columna de el espacio en blanco que siempre está en la última posición del vector de fichas
   this.piecesArray[piece_number-1].posY = this.piecesArray[15].posY;
   this.piecesArray[15].posX = auxX; //Al espacio en blanco se le asigna el valor en fila que tenía antes la ficha
   this.piecesArray[15].posY = auxY; //Al espacio en blanco se le asigna el valor en columna que tenía antes la ficha
   this.checkPosition(this.piecesArray[piece_number-1]); //Se verifica la ´nueva posición de la ficha
   wasMoved = true; //Se modifica a true el valor de la variable a retornar
  }
  return wasMoved; //Se retorna la variable que indica si se realizó o no movimiento
 }

 // Método que verifica si el juego ya se solucionó
 this.checkGame = function()
 {
  if(this.isWrongCount == 0) //Se verifica el número de fichas en la posición incorrecta
   return true; //Hay 0 fichas en la posición incorrecta
  else
   return false; //Hay alguna ficha en la posición incorrecta
 }
}  

Función Random


//Función hecha para desorganizar un vector de cualquier tamaño
function Random(array)
{
 var length = array.length; //Se obtiene el tamaño del vector
 var aux; //Variable auxiliar que permite el intercambio entre valores internos del vector
 var randomPos; //variable que guarda el número aleatorio generado
 // Se recorre todo el vector
 for(var i=0;i<length;i++)
 {
  aux = array[i]; //Se almacena el valor del vector en la posición actual i
  randomPos = Math.floor(Math.random() * length); //Se genera un número aleatorio entre 0 y el tamaño - 1
  array[i] = array[randomPos]; //Se coloca el valor del vector en la posición random como valor del vector en la posición actual
  array[randomPos] = aux; //Se coloca el valor del vector en la posición actual como valor del vector en la posición random
 }
 return array; //Se devuelve un vector con orden diferente al inicial
}

Programa Principal

Se le llamará programa principal a las líneas de código que crean el juego después de que carga la página y que finalmente declararán la forma en la cual interactúa el usuario con el juego. Ya que se usó la librería de jQuery, estás líneas van entre el manejador del evento que indica que el documento ya está listo.

Abajo se muestra el html que conforma nuestro juego. El único elemento que se agregó al body es una pequeña caja de texto que se usa para comunicarse con el jugador.


<!DOCTYPE html>
<html>
<head>
 <title>Puzzle</title>
 <link rel="stylesheet" type="text/css" href="estilos.css">
 <!-- Esta línea de código se usa para incluir la biblioteca de jQuery -->
 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
 <!-- Esta línea se usa para incluir nuestro programa -->
 <script type="text/javascript" src="game.js"></script>
</head>
<body>
 <h3 id="talking_box">!Cuando quieras!</h3>
</body>
</html>  

El programa principal arranca creando una nueva variable de tipo Juego. Después se usa el método inicializar juego de esta variable. Finalmente hay una llamada al método dibujar tablero para que este aparezca en el body de nuestro html.

Para la parte de interacción únicamente necesitamos declarar lo que ocurrirá cada vez que se haga clic sobre una ficha ubicada en el tablero. Esto se hace con ayuda de jQuery. El primer paso es obtener el número de la ficha cliqueada, luego usar el método mover ficha y verificar si el movimiento se realizó o no. Si el movimiento fue exitoso dentro de nuestro programa, usamos las propiedades de posición actual de la ficha para usarlas como referencia para el movimiento de la ficha en la interfaz gráfica. Este movimiento se realiza por medio de jQuery y su función de animación. Finalmente, cada vez que se hace clic sobre una ficha, también se verifica si el juego ha sido resuelto. En caso de que el juego sea resuelto, se cambia el texto de la caja de diálogo por: “Has resuelto el juego”.

Este es nuestro programa principal


$(document).ready(function(){
 var game = new Game();
 game.initializeGame();
 game.drawBoard(500);
 $(".game_piece").click(function(){ 
  var piece_number = $(this).children().text(); 
  if(game.movePiece(piece_number))
   $(this).animate({'top':((game.piecesArray[piece_number-1].posX-1)*25)+'%','left':((game.piecesArray[piece_number-1].posY-1)*25)+'%'},500);
  if(game.checkGame())
   $("#talking_box").text("Has resuelto el juego");  
 }); 
});

Estilos y CSS

Muchas de las propiedades gráficas del juego como las proporciones, el tamaño de letra, los colores y otros se encuentran el archivo de estilos. Aquí está el código con algunos comentarios.


*
{
 margin: 0; /*Resetea los márgenes de todos los elementos en la página*/
}
body
{
 background-color: #AA7639;
 color:#884900;
 font-size: 46px;
 text-align: center;
 -webkit-user-select: none; /*Para que no se pueda seleccionar el texto interior de las fichas*/
   user-select: none; 
}
#game_board
{
 background-color: #884900;
 border-radius: 5px;
 margin: 20px auto;
 position: relative;
}
#piece_container
{
 background-color: #AA7639;
 font-size: 0;
 height: 96%; /*El alto del div interior que conforma el tablero para dar la sensación de un borde grueso*/
 left: 2%;
 position: absolute;
 top:2%;
 width: 96%; /*El ancho del div interior que conforma el tablero para dar la sensación de un borde grueso*/
}
#talking_box
{
 background-color: #FFF3E6;
 border: 5px solid #884900;
 border-radius: 5px;
 color: #FF8901;
 height:auto;
 margin: 10px auto;
 padding-bottom: 5px;
 width: 500px;
}
.game_piece
{ 
 background-color: #FFF3E6;
 border: 2px groove #737679;
 box-sizing: border-box; /*Propiedad que hace que los bordes cuenten en el tamaño total de cada ficha*/
 display: inline-block;  
 height: 25%; /*Ancho de la ficha: la cuarta parte del tablero  */
 position: absolute;  
 width: 25%;
}
.number_container
{ 
 color: #FF8901;
 cursor: default;
 font-size: 50px;
 height: 50%;
 left: 50%;
 margin: -25% 0 0-25%;
 position: absolute;
 text-align: center;
 top: 50%;
 width: 50%;
}

Anotaciones Finales

Espero que en algo haya ayudado a alguien esta primera entrada a este blog. Después de haber hecho el código anterior fue posible ver que se pueden realizar numerosas mejoras para utilizar menos espacio en almacenamiento de variables y cosas así. Les dejo un link donde se encuentran los archivos y otro donde pueden ver el juego en acción.

Gracias por su tiempo y espero poder hacer una próxima entrada agregándole un temporizador a nuestro juego y un contador de movimientos.

Link para probar el juego funcionando y ver el código: Míralo aquí
Link para descargar los archivos: Descárgalo aquí







viernes, 12 de julio de 2013


Jugando a programar: La iniciativa


La iniciativa de este blog tiene un propósito fundamental: agradecer a toda la gente de la comunidad web el conocimiento que hasta hoy yo he podido adquirir de ellos y con el cual he venido mejorando cada vez más en todos los temas concernientes a la web. Al mismo tiempo, quiero practicar y mejorar mucho más por medio de algunas pasiones que tengo en la vida: jugar, programar y enseñar.

Quiero aclarar que no tengo estudios profesionales en programación y que la mayoría de lo que he aprendido ha sido empíricamente, sin embargo, en cada programa que realizo intento llevar a cabo buenas prácticas de programación. Cualquier comentario que tenga un fin correctivo, es bienvenido desde que sea hecho con respeto.

Cada entrada de este blog tiene como propósito explicar detalladamente la estructura, el código y el programa en general de pequeños juegos para la web. También se pueden encontrar entradas que contienen mejoras de programas anteriores con el fin de optimizar velocidad, recursos de memoria, o simplemente agregar alguna funcionalidad al juego publicado anteriormente. La idea es poder mostrar la utilización de diferentes lenguajes de programación web con la programación de estos pequeños juegos.

Tanto en los juegos como en la programación encontramos diferentes desafíos de diferentes niveles. También encontramos en ambas actividades, una gran dosis de satisfacción y una habilidad creciente cada vez que logramos superarlos. Espero que por medio de este blog podamos aprender fácilmente el juego de la programación mientras programamos algunos pequeños juegos.