27/9/10

Cómo fabricar un gato tonto en Silverlight

El primer juego en publicar es un Gato (Tic tac toe) tonto, es decir, uno juega contra la computadora, pero la computadora tira donde caiga, sin una estrategia.
La verdad el diseño no es mi fuerte, además siempre me matan las ganas de programar más que de hacerlo bonito (lo siento sé que para el usuario, la interfaz es la aplicación, pero esto es para recorar como lo hice, no para dar gusto a usuarios).
Empezaré con la creación de la interfaz de usuario en XAML de manera que me quede algo como esto:



El XAML es el siguiente:


        
            
            
        
        
            





Ahora a explicar que hace y como lo hace. Vamos a necesitar un arreglo que guarde todas las tiradas, es decir un arreglo de 3 X 3. También vamos a necesitar una variable que nos indique cuántos tiros se han hecho para ver si ya se terminó el juego sin que nadie haya ganado.

Lista de variables a utilizar:

int[,] arrayGato = new int[3, 3];// el arreglo que guarda lo que sucede en cada tirada
        int tiradas = 0; //indica si ya se tiró 9 veces y no hay ganador
        int jugados = 0; //para estadísticas indica cuántos juegos se han jugado
        int ganadosUser = 0;  //para estadísticas indica cuántos juegos ha ganado el usuario
        int ganadosPC = 0;  // para estadísticas indica cuantos juegos ha ganado la compu

Ahora es necesario crear una función que inicialice el arreglo o borre las tiradas después de cada juego:

private void iniciaArray()
        { 
            for(int i = 0; i< 3;i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    arrayGato[i, j] = 0;
                }
            }
        } 
El arreglo se va a llenar con enteros en cada tirada, cuando tire el usuario se va a colocar el valor de 1 (uno) en la celda que haya seleccionado el usuario. Cuando tire la computadora, la celda va a contener el valor de 5, esto se hace para saber quien ganó, recordemos que en el juego del Gato o Tic-tac-toe gana el que tenga 3 celdas en línea, ya sea horizontal, vertical o diagonal, entonces al sumar las tres celdas, nos debe dar el valor de 3 o el valor de 5 dependiendo quien ganó. Entonces hagamos la función que nos devuelve si alguien ganó:
/// 
        /// La función nos devuelve verdadero si ganó la computadora o el usuario, si ganó la computadora la suma de las tres celdas
        /// debe ser igual a 15, si el usuario fue el ganador, la suma de las 3 celdas nos debe dar el valor de 3
        /// 
        /// 
        private bool gano()
        { 
            int ver, hor;
            bool resultado = false;
            for(int i =0; i<3;i++)
            {
                ver = 0;hor = 0;
                for(int j= 0; j<3;j++)//Este for comprueba si alguien ganó en línea horizontal o vertical
                {
                    hor += arrayGato[i,j];
                    ver += arrayGato[j,i];
                }
                if ((hor == 3) || (hor == 15) || (ver == 3) || (ver == 15))
                {
                    resultado = true;
                    break;
                }else{
                    ver = 0;hor = 0;
                }
            }
            //este If comprueba si alguien ganó en alguna diagonal
            if ((3 == arrayGato[0,0]+arrayGato[1,1]+arrayGato[2,2])||(15 == arrayGato[0,0]+arrayGato[1,1]+arrayGato[2,2])
              ||(3 == arrayGato[0,2]+arrayGato[1,1]+arrayGato[2,0])||(15 == arrayGato[0,2]+arrayGato[1,1]+arrayGato[2,0]))
            {
                resultado = true;
            }
            return resultado;
        }
Recordemos que cada celda es un botón, entonces cuando el usuario selecciona una celda, en realidad está presionando un botón por lo cual a todos los botones les vamos a asignar el mismo método que le indica a la computadora que el usuario acaba de tirar. Tambien cada botón va a tener un Tag distinto el de la izquierda superior su tag es 00, el tag de en medio arriba es 01, el tag de lado superior derecho es 02. El tag del boton de enmedio a la izquierda es 10, el de enmedio exáctamente es 11 y el de enmedio a la derecha es 12 y así sucesivamente con los de abajo. Cada tirada debemos cambiar el Content de cada botón dependiendo quien tiró. En el ejemplo el usuario tira las X's mientras que la computadora tira O's. A continuación muestro el método que todos los botones deben tener:
private void button1_Click(object sender, RoutedEventArgs e)
        {
            string cadena, col, ren;
            cadena = ((Button)sender).Tag.ToString();
            col = cadena.Substring(1,1);
            ren = cadena.Substring(0,1);
            tiraUsuario(int.Parse(ren), int.Parse(col));
            ((Button)sender).IsEnabled = false;
            ((Button)sender).Content = "X";
        }
El método obtiene como cadena el Tag del botón y lo divide en 2, el primer valor le corresponde al renglón y el segundo a la columna, luego manda llamar al método tiraUsuario que recibe 2 parámetros: renglón y columna.
private void tiraUsuario(int ren, int col)
        {
            arrayGato[ren, col] = 1;
            tiradas += 1;
            if (gano())
            {
                MessageBox.Show("ganó Usuario");
                ganadosUser += 1;
                jugados += 1;
                lblJuegosJugados.Content = "Juegos jugados: " + jugados.ToString();
                lblJuegosUsuario.Content = "Juegos ganados por el usuario: " + ganadosUser.ToString();
            }
            else {
                if (tiradas < 9)
                {
                    tiraPC();
                    tiradas += 1;
                    if(gano())
                    { 
                        MessageBox.Show("ganó PC");
                        ganadosPC += 1;
                        jugados += 1;
                        lblJuegosJugados.Content = "Juegos jugados: " + jugados.ToString();
                        lblJuegosPC.Content = "Juegos ganados por la computadora: " + ganadosPC.ToString();
                    }
                }
            }
        }
El método anterior pone el valor de 1 (uno) a la celda del array donde tiró el usuario, luego pregunta si ganó y en caso de que no haya ganado entonces manda a llamar al método tiraPC y pregunta si después de tiraPC ganó la computadora. Veamos el método tiraPC ya que este método se va a modificar en la siguiente entrega de este blog para hacer un Gato inteligente.
private void tiraPC()
        {
            Random ran = new Random();
            int r = ran.Next(3);
            int c = ran.Next(3);
            while (arrayGato[r, c] != 0)
            {
                 r = ran.Next(3);
                 c = ran.Next(3);
            }
            arrayGato[r, c] = 5;
            deshabilitaBoton(r,c);
        }
tiraPC coloca la tirada de la computadora al azar, únicamente pregunta por una celda desocupada y ahí hace el tiro, como dije antes, en el siguiente post modificaremos este gato para hacerlo inteligente. Ahora veamos la función que deshabilita el botón para que el usuario no pueda dar clic en una celda que ya ha tirado la computadora:
private void deshabilitaBoton(int r, int c)
        {
            string cadena = r.ToString() + c.ToString();
            foreach (UIElement btn in this.canvas1.Children)
            {
                if (0 == cadena.CompareTo(((Button)btn).Tag.ToString()))
                {
                    ((Button)btn).Content = "O";
                    ((Button)btn).IsEnabled = false;
                }
            }
        }
El método deshabilitaBoton recibe el renglón y columna donde tiró la computadora, luego los valores los convierte a cadena y los compara con los Tag's de los botones para saber que botón deshabilitar. Ya para terminar nos falta un botón que nos va a permitír reiniciar el juego cada que se termine, este método inicializa el arreglo, borra los Content de los botones y los habilita.
private void btnIniciar_Click(object sender, RoutedEventArgs e)
        {
            tiradas = 0;
            iniciaArray();
            foreach (UIElement btn in this.canvas1.Children)
            {
                if (btn is Button)
                {
                    ((Button)btn).Content ="";
                    ((Button)btn).IsEnabled = true;
                }
            }   
            if (rBtnCompu.IsChecked == true) 
            {
                tiraPC();
                tiradas += 1;
            }
        }
    }

Bueno con esto se termina un gato tonto sin embargo trataré de dotarlo de un poco de inteligencia en el siguiente post.

se acabo.

La liga para descargar el código por si no estás perdido debido a mi pésima redacción.
URL:
http://www.mediafire.com/?q5z95b09chob2pq

No hay comentarios: