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

24/9/10

Agregar formato a código de programación en un post dentro de Blogger

Después de tres post y cuando estaba en la creación del cuarto me di cuenta que mis códigos escritos en csharp (C#) y en XAML no eran legibles y de poco me iban a servir más adelante cuando necesitara de ellos, por lo que me vi en la necesidad de buscar un script que me permitiera darle formato al código de manera fácil y rápida.

La solución fue simple pero lenta porque no encontraba una que pudiera ayudarme con una gran variedad de lenguajes (espero en este Blog escribir en varios lenguajes de programación), además necesitaba que la solución aplicara para Blogger y no tuviera que instalar nada en el servidor, finalmente la solución es la siguiente:

1. Entrar a Blogger con tu cuenta.
2. ir a la sección de Diseño
3. Seleccionar la opción de Edición de HTML
4. Activar la opción: Expandir plantillas de artilugios.
5. Visitar la página:  http://syntaxhighlighter.googlecode.com/svn/trunk/Styles/SyntaxHighlighter.css   y copiar todo el texto.
6. En el código de la plantilla de tu blog buscar la siguiente cadena: ]]--></b:skin>
7. Pegar el texto de la página antes de la cadena ]]]--></b:skin>
8. Luego buscar la cadena: </head> y antes de la cadena pegar lo siguiente:

<!-- Add-in CSS for syntax highlighting -->
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shCore.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCpp.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCss.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushDelphi.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJava.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPhp.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPython.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushRuby.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushSql.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushVb.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushXml.js' type='text/javascript'></script>

9. Buscar la cadena: </body> y antes de la cadena pegar el siguiente texto:

<!-- Add-in Script for syntax highlighting -->
<script language='javascript'>
dp.SyntaxHighlighter.BloggerMode();
dp.SyntaxHighlighter.HighlightAll('code');
</script>


10. Guarda la plantilla.

11. Ahora para publicar un post en el blog, se debe editar como HTML y colocar las siguientes etiquetas:

<pre name="code" class="java">


Aquí va el código


</pre>

12. Se puede configurar el lenguaje de programación para lo cual hay que sustituir la palabra java por alguna de las siguientes:
  • C++  se escribe cpp, c, c++
  • C#  se escribe    c#, c-sharp, csharp
  • CSS  se escribe  css
  • Delphi se escribe delphi, pascal
  • Java    se escribe       java
  • Java Script se escribe js, jscript, javascript
  • PHP se escribe  php
  • Python se escribe py, python
  • Ruby se escribe rb, ruby, rails, ror
  • Sql se escribe sql
  • VB se escribe vb, vb.net
  • XML/HTML se escribe xml, html, xhtml, xslt

Listo es todo.

12/9/10

Comunicar controles de usuario en silverlight

Quiero que quede huella de cómo comunicar 2 Controles de usuario (User control) en un proyecto en Silverlight utilizando Visual Studio 2010 y C#

Primero quiero tener un control de usuario que lea una cadena de texto, esta cadena de texto debe enviarse a un segundo control de usuario que la muestre en un Textbox.

Tal vez no tenga un uso práctico pero es sencillo para que quede clara la forma de enviar objetos entre controles de usuario.

Empecemos agregando 2 controles de tipo Border en el MainPage contendrán los controles de usuario

---Código XAML del MainPage----
< UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" >

    < Grid x:Name="LayoutRoot" Background="White" >
        < Border BorderBrush="Silver" BorderThickness="1" Height="152" HorizontalAlignment="Left" Name="border1" VerticalAlignment="Top" Width="400" / >
        < Border BorderBrush="Silver" BorderThickness="1" Height="150" HorizontalAlignment="Left" Margin="0,150,0,0" Name="border2" VerticalAlignment="Top" Width="400" />
    < / Grid >
< / UserControl >
---Fin del Código XAML del MainPage----

Ahora creemos el primer control de usuario que contendrá un TextBox donde escribiremos la cadena que se enviará sl control de usuario 2. También le pondremos un botón para enviar la cadena al segundo control de usuario después de escribirla.
 

---Código XAML del Control de usuario 1----
< UserControl x:Class="SilverlightApplication2.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" >
   
    < Grid x:Name="LayoutRoot" Background="White" >
        < TextBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="txtbxCadena" VerticalAlignment="Top" Width="120" / >
        < Button Content="Enviar" Height="23" HorizontalAlignment="Left" Margin="34,41,0,0" Name="btnEnviar" VerticalAlignment="Top" Width="75" Click="btnEnviar_Click" / >
    < / Grid >
< / UserControl >
---Fin del Código XAML del Control de usuario 1----
 

Ahora crearemos un segundo control de usuario que contendrá un TextBlock que mostrará la cadena recibida por el primero control de usuario.

--- Código XAML del Control de usuario 2----

< UserControl x:Class="SilverlightApplication2.UserControl2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" >
   
    < Grid x:Name="LayoutRoot" Background="White" >
        < TextBlock Height="22" HorizontalAlignment="Left" Margin="12,12,0,0" Name="txtblockCadenaRec" Text="Aun no me llega nada" VerticalAlignment="Top" Width="293" / >
    < / Grid >
< / UserControl >
---Fin del Código XAML del Control de usuario 2----

Hasta aquí tenemos los XAML de los 2 controles de usuario y del MainPage, ahora a programar.

Primero en el Control de usuario 1 (donde tenemos el textBox y el Botón) debemos crear un delegado encargado de disparar un evento y debemos declarar el evento que se debe disparar.


----Código C# del primer control de usuario----
public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
        }
        public delegate void delegadoEnviaCadena(string cadena); /*
es el delegado que se encarga de disparar el evento. Le decimos que el evento se llama delegadoEnviaCadena y recibe una cadena*/
        public event delegadoEnviaCadena enviaCadena;/*Es el evento que se va a disparar. Declaramos el evento del delegado, el evento se llama enviaCadena sin embargo el código de este evento no está en este control de usuario, este evento se desarrolla en el MainPage*/

        private void btnEnviar_Click(object sender, RoutedEventArgs e)
        {
            enviaCadena(txtbxCadena.Text); /*El evento enviaCadena se dispara enviándole el texto escrito, pero el código de lo que hace está en el MainPage.xaml.cs*/
        }  
    }
----Fin del código C# del primer control de usuario-----

 

Con el código anterior declaramos un delegado y un evento que se va a disparar cuando se da clic sobre el botón y envía la cadena.
 

Ahora falta escribir el código del evento que se dispara cuando hacen clic en el botón.

-----Código C# del MainPage-------
public partial class MainPage : UserControl
    {
        UserControl1 uc1; //declaramos el control de usuario 1
        UserControl2 uc2; //declaramos el control de usuario 2
        public MainPage()
        {
            InitializeComponent();
            uc1 = new UserControl1(); //creamos el control de usuario 1
            border1.Child = uc1;     //se lo asignamos al border 1
            uc2 = new UserControl2();  //creamos el control de usuario 2
            border2.Child = uc2;       //se lo asignamos al border 2
            this.uc1.enviaCadena += new UserControl1.delegadoEnviaCadena(recibeMainYEnviaCtrolUser2); /*Le asigna al evento enviaCadena el método recibeMainYEnviaCtrolUser2 con los mismos parámetros*/
        }

        void recibeMainYEnviaCtrolUser2(string cadena)
        {
            uc2.recibeCadena(cadena);  /*le envía la cadena al control de usuario 2 que debe tener un método que reciba los parámetros que deseamos enviarle*/
        }
    }

-----Fin del código C# del MainPage-------

 

Finalmente en el Control de usuario 2 debemos declarar el método que reciba el parámetro que nos envían del primer control de usuario.

----Código C# del segundo control de usuario-----


public partial class UserControl2 : UserControl
    {
        public UserControl2()
        {
            InitializeComponent();
        }

        public void recibeCadena(String cadena)/* el método que recibe el parámetro que nos envían del primer control de usuario*/
        {
            txtblockCadenaRec.Text = cadena;
        }

    }

----Fin del código C# del segundo control de usuario-----

 

En este ejemplo se envía una cadena, pero se puede enviar cualquier objeto, únicamente hay que cambiar la palabra string por el tipo del objeto y listo.