<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>El código de Zameb</title>
	<atom:link href="http://zameb.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://zameb.wordpress.com</link>
	<description>&#34;ἕν οἶδα, ὅτι οὐδὲν οἶδα&#34; - Σωκράτης</description>
	<lastBuildDate>Mon, 26 Dec 2011 01:29:32 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='zameb.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/909bf1a85c7d40e5b096604b52012914?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>El código de Zameb</title>
		<link>http://zameb.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://zameb.wordpress.com/osd.xml" title="El código de Zameb" />
	<atom:link rel='hub' href='http://zameb.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Computadora, calcula mi horario</title>
		<link>http://zameb.wordpress.com/2011/02/20/computadora-calcula-mi-horario/</link>
		<comments>http://zameb.wordpress.com/2011/02/20/computadora-calcula-mi-horario/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 12:21:58 +0000</pubDate>
		<dc:creator>zameb</dc:creator>
				<category><![CDATA[CSharp]]></category>
		<category><![CDATA[Diseño]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[IA]]></category>

		<guid isPermaLink="false">http://zameb.wordpress.com/?p=182</guid>
		<description><![CDATA[En esta oportunidad voy a desarrollar la idea de cómo podemos valernos de un algoritmo genético para calcular distintos horarios a partir de una serie de cursos disponibles. Los objetivos son: Obtener uno o más horarios válidos Llevar todos los cursos posibles Cada curso puede dictarse mas de un dia a la semana Cada curso [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=182&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>En esta oportunidad voy a desarrollar la idea de cómo podemos valernos de un algoritmo genético para calcular distintos horarios a partir de una serie de cursos disponibles.</p>
<p>Los objetivos son:</p>
<ul>
<li>Obtener uno o más horarios válidos</li>
<li>Llevar todos los cursos posibles</li>
<li>Cada curso puede dictarse mas de un dia a la semana</li>
<li>Cada curso puede tener varios horarios para escoger</li>
</ul>
<p>Primero vamos a repasar rápidamente lo que es un algoritmo genético.</p>
<p>Un algoritmo genético es aquel en el que los datos se representan por genes. A su vez los genes se organizan en estructuras llamadas genomas, que le dan cierto sentido a los datos. Los genomas interactúan entre sí para buscar la solución a un cierto problema dado.</p>
<p>En este ejemplo vamos a hacer uso de un algoritmo genético y evolutivo. En otras palabras, los genomas irán evolucionando para llegar a la solución buscada.</p>
<p>La parte principal de nuestro algoritmo es la siguiente:</p>
<p><pre class="brush: csharp;">
        public void EjecutarCiclo()
        {
            List&lt;CGenoma&gt; nuevaPoblacion = new List&lt;CGenoma&gt;();
            while (nuevaPoblacion.Count &lt; LongitudPoblacion)
            {
                CGenoma padre = Seleccionar();
                CGenoma madre = Seleccionar();
                CGenoma hijo1;
                CGenoma hijo2;
                RealizarCruce(padre, madre, out hijo1, out hijo2);
                hijo1 = Mutacion(hijo1);
                hijo2 = Mutacion(hijo2);
                nuevaPoblacion.Add(hijo1);
                nuevaPoblacion.Add(hijo2);
            }
            ListaPoblacion = nuevaPoblacion;
            ActualizarFitness();
        }
</pre></p>
<p>Si podemos entender esa pequeña sección de código, lo tendremos casi todo.</p>
<p>El algoritmo se basa en la creación de nuevas poblaciones a partir de los genomas existentes. Para obtener nuevos &#8220;hijos&#8221;, se selecciona un padre, una madre y se realiza el cruce. El padre y la madre deben ser cuidadosamente seleccionados: no es una selección al azar. Una vez que tenemos dos nuevos hijos, se da paso a la mutación (aunque  procuraremos que su efecto sea mínimo). Esto se repite una y otra vez, hasta obtener una solución.</p>
<p>La mala noticia es que no se puede garantizar una solución. La buena es que este algoritmo puede obtener soluciones que normalmente escapan a los cálculos humanos.</p>
<p>Ya hemos visto la parte principal. Pero para poderla utilizar, antes necesitamos una población inicial:</p>
<p><pre class="brush: csharp;">
        public void GenerarPoblacionInicial()
        {
            ListaPoblacion = new List&lt;CGenoma&gt;();
            while (ListaPoblacion.Count &lt; LongitudPoblacion)
            {
                CGenoma genoma = new CGenoma();
                foreach (CCurso curso in Data.ListaCursos)
                {
                    genoma.ListaGenes.Add(new CGen(curso.Id, curso.ObtenerIdHorarioAlAzar()));
                }
                ListaPoblacion.Add(genoma);
            }
            ActualizarFitness();
        }
</pre></p>
<p>Ahora se hace evidente que existe una relación entre nuestros datos y los genes cada genoma. Los genes son muy dependientes de cada problema analizado. Para el presente caso, un gen representa la información: Curso-Horario.</p>
<p>Los genomas son siempre listas de genes. En este caso un genoma tendrá la estructura:</p>
<ul>
<li>genoma: gen1, gen2, gen3&#8230;, genN</li>
</ul>
<p>O, lo que es lo mismo:</p>
<ul>
<li>genoma: Curso1-Horario1, Curso2-Horario2, Curso3-Horario3&#8230;, CursoN-HorarioN</li>
</ul>
<p>La estructura de la clase genoma es la siguiente:</p>
<p><pre class="brush: csharp;">
    public class CGenoma
    {
        public List&lt;CGen&gt; ListaGenes;
        public double Fitness;

        public CGenoma()
        {
            ListaGenes = new List&lt;CGen&gt;();
            Fitness = 0;
        }

        internal void CalculaFitness(int PeorPuntaje, CTestData pData)
        {
            int total = 0;
            Fitness = 1 - ((double)total / (double)PeorPuntaje);
        }

        public void Render(Graphics Canvas, int x, int y, CTestData pData)
        {
        }
    }
</pre></p>
<p>La clase genoma se compone simplemente de una lista de genes, una función para calcular el Fitness y un método para representar al genoma de forma gráfica (dibujar el horario en pantalla, vamos).</p>
<p>Probablemente esto del Fitness sea lo más difícil de entender, y también lo mas delicado, por lo que le dedicaré mayor espacio en la siguiente publicación. Sólo adelanto que el fitness de un genoma es un valor float entre 0 y 1 y sirve para indicar la &#8220;utilidad&#8221; de un genoma. Si el fitness se acerca a 1, el genoma es &#8220;bueno&#8221;, si se acerca a 0, es &#8220;malo&#8221;.</p>
<p>Por ahora veamos que contiene cada gen dentro de nuestro genoma:</p>
<p><pre class="brush: csharp;">
    public class CGen
    {
        public int Curso;
        public int Horario;

        public CGen(int pCurso, int pHorario)
        {
            Curso = pCurso;
            Horario = pHorario;
        }
    }
</pre></p>
<p>Como podemos ver, el gen es bastante simple para este problema.</p>
<p>En la mayoría de implementaciones de algoritmos genéticos que se pueden encontrar por la web, pareciera ser necesario que tanto el gen, como el genoma, sean representaciones de cadenas con ceros y unos. Eso no es necesario y no lo verán en este ejemplo. La ventaja de utilizar ceros y unos es que con ellos es más fácil realizar operaciones genéticas (cruces, mutaciones, selecciones). Pero presentan la desventaja de que hay que codificar y decodificar los genes para poder llegar a los datos.</p>
<p>Próximamente continuaremos con la implementación de este algoritmo.</p>
<p>¡Hasta pronto!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/zameb.wordpress.com/182/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/zameb.wordpress.com/182/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/zameb.wordpress.com/182/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/zameb.wordpress.com/182/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/zameb.wordpress.com/182/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/zameb.wordpress.com/182/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/zameb.wordpress.com/182/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/zameb.wordpress.com/182/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=182&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://zameb.wordpress.com/2011/02/20/computadora-calcula-mi-horario/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/647be5f265c0ce73d186f5443ffcc8bf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">zameb</media:title>
		</media:content>
	</item>
		<item>
		<title>El hormiguero &#8211; Feromonas</title>
		<link>http://zameb.wordpress.com/2010/05/03/el-hormiguero-feromonas/</link>
		<comments>http://zameb.wordpress.com/2010/05/03/el-hormiguero-feromonas/#comments</comments>
		<pubDate>Mon, 03 May 2010 19:50:37 +0000</pubDate>
		<dc:creator>zameb</dc:creator>
				<category><![CDATA[CSharp]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[IA]]></category>
		<category><![CDATA[algoritmo]]></category>
		<category><![CDATA[colisiones]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[feromonas]]></category>
		<category><![CDATA[hormigas]]></category>

		<guid isPermaLink="false">http://zameb.wordpress.com/?p=140</guid>
		<description><![CDATA[Hasta el momento hemos logrado que nuestras hormigas se muevan de manera aleatoria. Ha llegado la hora de que hagan algo que deben hacer las hormigas: formar hileras. Para esto nos vamos a valer del concepto de feromonas. Tal como les contaba en el primer artículo de esta serie, las hormigas se guían por un [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=140&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hasta el momento hemos logrado que nuestras hormigas se muevan de manera aleatoria. Ha llegado la hora de que hagan algo que deben hacer las hormigas: formar hileras.</p>
<p>Para esto nos vamos a valer del concepto de feromonas. Tal como les contaba en el <a href="http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-modelado/">primer artículo de esta serie</a>, las hormigas se guían por un rastro químico que ellas mismas van dejando. Nosotros implementaremos eso mismo. Cada vez que una hormiga dé un paso, provocaremos que deje este rastro. El rastro debe poder incrementar otro rastro que haya sido dejado con anterioridad, para esto utilizaremos una variable que simule la intensidad del rastro.</p>
<p>Cuando una hormiga encuentre un rastro, deberá seguir su dirección, cuando no lo encuentre, seguirá paseando aleatoriamente. Este será, a grandes rasgos, el comportamiento que buscaremos con la clase feromona, la cual muestro a continuación:</p>
<p><pre class="brush: csharp;">
    public class CFeromona
    {
        private float mIntensidad;
        public CCircle Posicion { get; set; }
        public float Direccion;
        public float Intensidad
        {
            get { return mIntensidad; }
            set
            {
                mIntensidad=value;
                if (mIntensidad &gt; 255)
                    mIntensidad = 255;
            }
        }

        public CFeromona()
        {
            Intensidad = 10;
            Posicion = new CCircle();
            Posicion.Radius = 5;
        }

        public void Render(Graphics g)
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.ResetTransform();
            g.TranslateTransform(Posicion.Center.X, Posicion.Center.Y);
            Brush br = new SolidBrush(Color.FromArgb((int)Intensidad, 220, 220, 255));
            g.FillEllipse(br,
                new Rectangle(
                    new Point(-Posicion.Radius, -Posicion.Radius),
                    new Size(Posicion.Radius * 2, Posicion.Radius * 2)));
        }
    }
</pre></p>
<p>Como pueden observar, la posición de una feromona está definida como un círculo. Esto lo hago para facilitar el que una hormiga pueda encontrarla, si fuera un punto, tendríamos que ponernos a esperar todo el día. Por este mismo motivo, he modificado la clase hormiga y ahora es como sigue:</p>
<p><pre class="brush: csharp;">
    public class CHormiga
    {
        public CCircle Posicion { get; set; }
        public float Direccion { get; set; }
        public int Estado { get; set; }
        public int Velocidad { get; set; }

        public CHormiga()
        {
            Estado = 0;
            Posicion = new CCircle();
            Posicion.Radius = 8;
        }

        public void Render(Graphics g)
        {
            Posicion.Render(g);
            Point p = Posicion.Center;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.ResetTransform();
            g.TranslateTransform(p.X, p.Y);
            g.RotateTransform(Direccion);
            Pen pen = new Pen(Color.Black);
            g.FillEllipse(Brushes.Black, new Rectangle(new Point(-2, -10), new Size(4, 6)));
            g.FillEllipse(Brushes.Black, new Rectangle(new Point(-1, -4), new Size(2, 2)));
            g.FillEllipse(Brushes.Black, new Rectangle(new Point(-2, -2), new Size(4, 4)));
            g.DrawLine(pen, 0, 2, -3, 5);
            g.DrawLine(pen, 0, 2, 3, 5);
            pen.Dispose();
        }
    }
</pre></p>
<p>Y bueno, ya se estarán preguntando cómo es esta clase CCirculo. Pues no se preocupen que aquí va:</p>
<p><pre class="brush: csharp;">
    public class CCircle
    {
        public Point Center { get; set; }
        public int Radius { get; set; }

        public void Render(Graphics g)
        {
            g.ResetTransform();
            g.TranslateTransform(Center.X, Center.Y);
            g.DrawEllipse(new Pen(Brushes.Salmon), -Radius / 2, -Radius / 2, Radius, Radius);
        }
    }
</pre></p>
<p>Pero los cambios más radicales están en la clase Controladora. Ya no basta con mover a las hormigas, ahora es necesario actualizar la intensidad de las feromonas para simular su evaporación y también es necesario verificar si cada hormiga se ha topado con un rastro de feromonas.</p>
<p>Esta sería la nueva versión de la clase controladora:</p>
<p><pre class="brush: csharp;">
    class CHormiguero
    {
        private double counter = 0;
        private Point mLimits;

        public ArrayList Hormigas { get; set; }
        public ArrayList Feromonas { get; set; }
        public Point Posicion { get; set; }
        public Point Limits
        {
            get { return mLimits; }
            set
            {
                mLimits = value;
                foreach (CHormiga hormiga in Hormigas)
                {
                    if (hormiga.Posicion.Center.X &gt; mLimits.X)
                    {
                        hormiga.Posicion.Center =
                            new Point(mLimits.X, hormiga.Posicion.Center.Y);
                    }
                    if (hormiga.Posicion.Center.Y &gt; mLimits.Y)
                    {
                        hormiga.Posicion.Center =
                            new Point(hormiga.Posicion.Center.X, mLimits.Y);
                    }
                }
            }
        }

        public CHormiguero(int numHormigas, int width, int height, int velocidad)
        {
            Hormigas = new ArrayList();
            Feromonas = new ArrayList();
            Limits = new Point(width, height);
            Posicion = new Point(width/2, height/2);

            Random rnd = new Random();
            for (int i = 0; i &lt; numHormigas; i++)
            {
                CHormiga hormiga = new CHormiga();
                hormiga.Posicion.Center =
                    new Point(rnd.Next(width), rnd.Next(height));
                hormiga.Direccion = ((float)rnd.NextDouble() * 360) - 180;
                hormiga.Velocidad = rnd.Next(velocidad - 5) + 5;
                Hormigas.Add(hormiga);
            }
        }

        public void Render(Graphics g)
        {
            //g.FillEllipse(Brushes.Gray, Posicion.X - 5, Posicion.Y - 5, 10, 10);
            foreach (CFeromona feromona in Feromonas)
            {
                feromona.Render(g);
            }
            foreach (CHormiga hormiga in Hormigas)
            {
                hormiga.Render(g);
            }
        }

        public void ActualizarFeromonas(float tiempo)
        {
            for (int i = Feromonas.Count - 1; i &gt;= 0; i--)
            {
                CFeromona feromona = (CFeromona)Feromonas[i];
                feromona.Intensidad -= tiempo/2;
                if (feromona.Intensidad &lt; 1)
                {
                    Feromonas.Remove(feromona);
                }
            }
        }

        public void MoverHormigas(float tiempo)
        {
            Random rnd = new Random();
            counter += 1;
            foreach (CHormiga hormiga in Hormigas)
            {
                float d = hormiga.Direccion;
                float radd = (float)((d * Math.PI) / 180);
                int dx = -(int)(Math.Sin(radd) * hormiga.Velocidad * tiempo);
                int dy = (int)(Math.Cos(radd) * hormiga.Velocidad * tiempo);
                Point p = hormiga.Posicion.Center;
                p.X += dx;
                p.Y += dy;
                //Detectar feromonas
                CFeromona bestF = null;
                //Si detecta feromona, ir en esa direccion
                //Si no detecta, tomar un camino al azar y dejar feromona
                if (DetectarFeromona(hormiga, ref bestF))
                {
                    bestF.Intensidad += 10;
                    d = bestF.Direccion;
                }
                else
                {
                    d += ((float)rnd.NextDouble() * 60) - 30;
                    if (Feromonas.Count &lt; 1000)
                    {
                        CFeromona f = new CFeromona();
                        f.Posicion.Center = hormiga.Posicion.Center;
                        f.Direccion = d;
                        Feromonas.Add(f);
                    }
                }
                if ((p.X &gt; 0) &amp;&amp; (p.X &lt; Limits.X) &amp;&amp;
                    (p.Y &gt; 0) &amp;&amp; (p.Y &lt; Limits.Y))
                {
                }
                else
                {
                    if (p.X &lt; 0) p.X = Limits.X;
                    if (p.X &gt; Limits.X) p.X = 0;
                    if (p.Y &lt; 0) p.Y = Limits.Y;
                    if (p.Y &gt; Limits.Y) p.Y = 0;
                }
                hormiga.Posicion.Center = p;
                hormiga.Direccion = d;
            }
        }

        private bool DetectarFeromona(CHormiga hormiga, ref CFeromona bestF)
        {
            bool hit = false;
            foreach (CFeromona feromona in Feromonas)
            {
                {
                    if (CColisiones.Colision(feromona.Posicion, hormiga.Posicion))
                    {
                        if (!hit)
                        {
                            bestF = feromona;
                            hit = true;
                        }
                        else
                        {
                            if (feromona.Intensidad &gt; bestF.Intensidad)
                            {
                                bestF = feromona;
                            }
                        }
                    }
                }
            }
            return hit;
        }
    }
</pre></p>
<p>También se ha creado la siguiente clase que verifica las colisiones de forma bastante sencilla, y esta era una de las razones de hacer que la posición de las hormigas y las feromonas sea definida como un círculo:</p>
<p><pre class="brush: csharp;">
    public static class CColisiones
    {
        public static bool Colision(CCircle c1, CCircle c2)
        {
            double r = c1.Radius + c2.Radius;
            double x = c2.Center.X - c1.Center.X;
            double y = c2.Center.Y - c1.Center.Y;
            return (r * r &gt; (x * x + y * y));
        }
</pre></p>
<p>Y ya tenemos todo listo para utilizarlo en un formulario que tenga su respectivo Timer.</p>
<p>El resultado que yo he obtenido es el siguiente:</p>
<p><a href="http://zameb.files.wordpress.com/2010/05/antrows.jpg"><img class="aligncenter size-full wp-image-144" title="antrows" src="http://zameb.files.wordpress.com/2010/05/antrows.jpg?w=594" alt=""   /></a></p>
<p>El formulario mostrado tiene sólo 15 hormigas, pero lo he probado con 300 y funciona igualmente bien: las hormigas van dejando un rastro que es seguido por las demás y mientras más hormigas lo recorren, este se hace más nítido.</p>
<p>Lo más importante, por ahora, es que se confirma que las hormigas sólo necesitan del rastro de feromonas para funcionar organizadamente.</p>
<p>En un siguiente artículo jugaremos un poco con las probabilidades de seguir o abandonar un determinado rastro y veremos si todo esto es suficiente para encontrar comida y llevarla de vuelta al nido.</p>
<p>No duden en dejarme un comentario si es que tienen alguna duda, pues aquí se han encontrado muchos conceptos diferentes: manejo de gráficos, colisiones, algo de matemática, además del tema central que son las hormigas. Por ese motivo he pasado por alto algunos conceptos, pero eso no significa que no esté dispuesto a comentarlos si que algún lector desea aclarar algún punto.</p>
<p>¡Hasta pronto!</p>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:58px;width:1px;height:1px;overflow:hidden;"><pre class="brush: csharp;">
        public CHormiguero(int numHormigas, int width, int height)
        {
            Hormigas = new ArrayList();
            Velocidad = 10;
            Limits = new Point(width, height);

            Random rnd = new Random();
            for (int i = 0; i &lt; numHormigas; i++)
            {
                CHormiga hormiga = new CHormiga();
                hormiga.Posicion =
                    new Point(rnd.Next(width), rnd.Next(height));
                hormiga.Direccion =
                    ((float)rnd.NextDouble() * 360) - 180;
                Hormigas.Add(hormiga);
            }
        }
</pre></p>
</div>
<br /> Tagged: <a href='http://zameb.wordpress.com/tag/algoritmo/'>algoritmo</a>, <a href='http://zameb.wordpress.com/tag/colisiones/'>colisiones</a>, <a href='http://zameb.wordpress.com/tag/csharp-2/'>csharp</a>, <a href='http://zameb.wordpress.com/tag/dotnet/'>dotNET</a>, <a href='http://zameb.wordpress.com/tag/feromonas/'>feromonas</a>, <a href='http://zameb.wordpress.com/tag/hormigas/'>hormigas</a>, <a href='http://zameb.wordpress.com/tag/ia/'>IA</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/zameb.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/zameb.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/zameb.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/zameb.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/zameb.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/zameb.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/zameb.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/zameb.wordpress.com/140/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=140&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://zameb.wordpress.com/2010/05/03/el-hormiguero-feromonas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/647be5f265c0ce73d186f5443ffcc8bf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">zameb</media:title>
		</media:content>

		<media:content url="http://zameb.files.wordpress.com/2010/05/antrows.jpg" medium="image">
			<media:title type="html">antrows</media:title>
		</media:content>
	</item>
		<item>
		<title>Acceso a los controles de un UserControl</title>
		<link>http://zameb.wordpress.com/2010/04/29/acceso-a-los-controles-de-un-usercontrol/</link>
		<comments>http://zameb.wordpress.com/2010/04/29/acceso-a-los-controles-de-un-usercontrol/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 18:12:56 +0000</pubDate>
		<dc:creator>zameb</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[CSharp]]></category>
		<category><![CDATA[dotNET]]></category>

		<guid isPermaLink="false">http://zameb.wordpress.com/?p=131</guid>
		<description><![CDATA[ASP.NET provee de elementos muy interesantes para construir un sitio web. Sin embargo también hay algunas dificultades que tendremos que sortear tarde o temprano. Una de estas dificultades consiste en que los controles que ponemos dentro de un control de usuario, no pueden ser accesados tan fácilmente como los que están colocados a nivel de [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=131&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>ASP.NET provee de elementos muy interesantes para construir un sitio web. Sin embargo también hay algunas dificultades que tendremos que sortear tarde o temprano.</p>
<p>Una de estas dificultades consiste en que los controles que ponemos dentro de un control de usuario, no pueden ser <em>accesados </em>tan fácilmente como los que están colocados a nivel de página.</p>
<p>Por ejemplo, si tenemos un control de usuario sencillo como el siguiente:</p>
<p><pre class="brush: xml;">
&lt;%@ Control Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;WebUserControl1.ascx.cs&quot; Inherits=&quot;WSMyLittleStore.WebUserControl1&quot; %&gt;

&lt;asp:Label ID=&quot;Label1&quot; runat=&quot;server&quot; Text=&quot;Nombre&quot;&gt;&lt;/asp:Label&gt;
&lt;asp:TextBox ID=&quot;TextBox1&quot; runat=&quot;server&quot;&gt;&lt;/asp:TextBox&gt;
&lt;br /&gt;
&lt;asp:Label ID=&quot;Label2&quot; runat=&quot;server&quot; Text=&quot;Apellido&quot;&gt;&lt;/asp:Label&gt;
&lt;asp:TextBox ID=&quot;TextBox2&quot; runat=&quot;server&quot;&gt;&lt;/asp:TextBox&gt;
</pre></p>
<p>Y un formulario igualmente sencillo como:</p>
<p><pre class="brush: xml;">
&lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
 &lt;div&gt;
 &lt;uc1:WebUserControl1 ID=&quot;WebUserControl11&quot; runat=&quot;server&quot; /&gt;
 &lt;br /&gt;
 &lt;asp:Label ID=&quot;Label1&quot; runat=&quot;server&quot; Text=&quot;Edad&quot;&gt;&lt;/asp:Label&gt;
 &lt;asp:TextBox ID=&quot;TextBox1&quot; runat=&quot;server&quot;&gt;&lt;/asp:TextBox&gt;
 &lt;/div&gt;
 &lt;/form&gt;
</pre></p>
<p>No podremos hacer lo siguiente en el code-behind de la página:</p>
<p><pre class="brush: csharp;">
protected void Page_Load(object sender, EventArgs e)
 {
 TextBox1.Text = &quot;TextBox en el form&quot;; //Correcto!
 WebUserControl1.TextBox1.Text = &quot;TextBox en el UserControl&quot;; //Error!
 WebUserControl1.TextBox2.Text = &quot;TextBox en el UserControl&quot;; //Error!
 }
</pre></p>
<p>Esto se debe a que los controles dentro del UserControl están declarados con el atributo protected.</p>
<p>He utilizado tres maneras de sortear este problema, cada una con sus ventajas e inconvenientes:</p>
<p><strong>1) Crear una propiedad pública dentro del UserControl</strong></p>
<p>En el code-behind del UserControl haríamos lo siguiente:</p>
<p><pre class="brush: csharp;">
public partial class WebUserControl1 : System.Web.UI.UserControl
 {
 public TextBox Texto1
 {
 get { return TextBox1; }
 set { TextBox1 = Texto1; }
 }

 public TextBox Texto2
 {
 get { return TextBox2; }
 set { TextBox1 = Texto2; }
 }

 protected void Page_Load(object sender, EventArgs e)
 {
 }
 }
</pre></p>
<p>Ahora en el code-behind del form podemos utilizar Texto1 y Texto2 para referirnos a las hasta ahora inaccesibles cajas de texto del UserControl:</p>
<p><pre class="brush: csharp;">
protected void Page_Load(object sender, EventArgs e)
 {
 TextBox1.Text = &quot;TextBox en el form&quot;; //Correcto!
 WebUserControl1.Texto1.Text = &quot;TextBox en el UserControl&quot;; //Correcto!!
 WebUserControl1.Texto2.Text = &quot;TextBox en el UserControl&quot;; //Correcto!!
 }
</pre></p>
<p>Esta es la opción más recomendada por la mayoría. Para mi es  totalmente impráctica cuando el UserControl cuenta con muchos controles  que deseamos exponer. Imagínense 40 declaraciones de gets y sets. Simplemente, me parece una pérdida de tiempo y una carga negativa para la mantenibilidad de la aplicación. Sin embargo puede ser útil para utilizarla con unos pocos controles (hasta 3, diría yo).</p>
<p><strong>2) Utilizar FindControl en el code-behind de la página</strong></p>
<p>En este caso nos olvidamos de los gets y sets y trabajamos directamente con el code-behind del form:</p>
<p><pre class="brush: csharp;">
protected void Page_Load(object sender, EventArgs e)
 {
 TextBox Texto1 = (TextBox)WebUserControl1.FindControl(&quot;TextBox1&quot;);
 TextBox Texto2 = (TextBox)WebUserControl1.FindControl(&quot;TextBox2&quot;);
 TextBox1.Text = &quot;TextBox en el form&quot;; //Correcto!
 Texto1.Text = &quot;TextBox en el UserControl&quot;; //Correcto!
 Texto2.Text = &quot;TextBox en el UserControl&quot;; //Correcto!
 }
</pre></p>
<p>Sé que esta alternativa va a resultar tentadora para más de uno. Pero hay que tener en cuenta 2 inconvenientes:</p>
<p>Primero, que estamos introduciendo &#8220;código duro&#8221; en nuestro form, obligándonos a mantener a mano la coincidencia de los nombres de los controles con el string que utilizamos en cada método FindControl.</p>
<p>Segundo y más importante aún, que cualquier error en los nombres no será detectado por el compilador sino que causará errores de ejecución o de lógica en nuestro formulario.</p>
<p><strong>3) Cambiar los atributos a public</strong></p>
<p>En este caso nos fijaremos que nuestro UserControl se compone de 3 ficheros:</p>
<ul>
<li>UserControl.ascx</li>
<li>UserControl.ascx.cs</li>
<li>UserControl.ascx.designer.cs</li>
</ul>
<p>Nosotros abriremos el archivo UserControl.ascx.designer.cs y veremos que ahí se encuentran declarados nuestros controles con el atributo protected. Veremos también que sobre cada declaración hay un mensaje que dice:</p>
<p><pre class="brush: csharp;">
 /// Auto-generated field.
 /// To modify move field declaration from designer file to code-behind file.
</pre></p>
<p>Y bueno, pues podemos hacer caso de eso y cortar la declaración del control para luego pegarla en el code-behind. Una vez en el code-behind, cambiaremos la palabra protected por public y ¡voila!, ya tendremos acceso al control desde el form.</p>
<p>El code-behind del UserControl debería quedar como sigue:</p>
<p><pre class="brush: csharp;">
public partial class WebUserControl1 : System.Web.UI.UserControl
 {
 public global::System.Web.UI.WebControls.TextBox TextBox1;
 public global::System.Web.UI.WebControls.TextBox TextBox2;

 protected void Page_Load(object sender, EventArgs e)
 {

 }
 }
</pre></p>
<p>Ahora en el code-behind de nuestro form podemos escribir:</p>
<p><pre class="brush: csharp;">
protected void Page_Load(object sender, EventArgs e)
 {
 TextBox1.Text = &quot;TextBox en el form&quot;; //Correcto!
 WebUserControl1.TextBox1.Text = &quot;TextBox en el UserControl&quot;; //Correcto!
 WebUserControl1.TextBox2.Text = &quot;TextBox en el UserControl&quot;; //Correcto!
 }
</pre></p>
<p>El principal inconveniente de esta solución es que atenta contra una de las leyes de la POO: que los atributos de una clase no deben ser accesados directamente, sino a través de métodos o propiedades. Pero es que las otras soluciones tampoco parecen sacadas de un libro de &#8220;buenas prácticas&#8221; y me parece que Microsoft nos ha dejado un poco huérfanos con este problema.</p>
<p>Para finalizar, creo que ninguna de las opciones es óptima. Cada una servirá para situaciones particulares y ya depende de cada uno considerar sus ventajas y desventajas. Si alguien conoce otra forma, ¡por favor compartirla con los que leen este blog!</p>
<p>Por lo pronto, yo pienso que Microsoft debería ofrecer una mejor alternativa en las futuras revisiones del UserControl. Por decir algo: que la accesibilidad de cada control pueda ser establecida por medio de una propiedad en tiempo de diseño.</p>
<p>¿Qué opinan ustedes?</p>
<p>¡Hasta pronto!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/zameb.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/zameb.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/zameb.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/zameb.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/zameb.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/zameb.wordpress.com/131/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/zameb.wordpress.com/131/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/zameb.wordpress.com/131/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=131&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://zameb.wordpress.com/2010/04/29/acceso-a-los-controles-de-un-usercontrol/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/647be5f265c0ce73d186f5443ffcc8bf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">zameb</media:title>
		</media:content>
	</item>
		<item>
		<title>El hormiguero – Movimiento</title>
		<link>http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-movimiento/</link>
		<comments>http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-movimiento/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 08:50:25 +0000</pubDate>
		<dc:creator>zameb</dc:creator>
				<category><![CDATA[CSharp]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[IA]]></category>

		<guid isPermaLink="false">http://zameb.wordpress.com/?p=128</guid>
		<description><![CDATA[Para poder hacer que nuestras hormigas se muevan, es conveniente contar con una clase “controladora”. En una clase de este tipo podemos centralizar las operaciones relativas al movimiento, los cambios de estado, las colisiones. Sin una clase controladora nos veríamos obligados a escribir código complicado en el formulario o en la clase Hormiga. La estructura [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=128&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Para poder hacer que nuestras hormigas se muevan, es conveniente contar con una clase “controladora”. En una clase de este tipo podemos centralizar las operaciones relativas al movimiento, los cambios de estado, las colisiones. Sin una clase controladora nos veríamos obligados a escribir código complicado en el formulario o en la clase Hormiga.</p>
<p>La estructura de nuestra clase controladora es la siguiente:</p>
<p><pre class="brush: csharp;">
    class CHormiguero
    {
        private double counter = 0;

        public ArrayList Hormigas { get; set; }
        public Point Posicion { get; set; }
        public Point Limits { get; set; }
        public float Velocidad { get; set; }

        public CHormiguero(int numHormigas, int width, int height)
        {
        }

        public void Render(Graphics g)
        {
            foreach (CHormiga hormiga in Hormigas)
            {
                hormiga.Render(g);
            }
        }

        public void MoverHormigas(float tiempo)
        {
        }
    }
}
</pre></p>
<p>El constructor CHormiguero se encargará de crear cada hormiga, establecer la velocidad y poner límites al hormiguero:</p>
<p><pre class="brush: csharp;">
        public CHormiguero(int numHormigas, int width, int height)
        {
            Hormigas = new ArrayList();
            Velocidad = 10;
            Limits = new Point(width, height);

            Random rnd = new Random();
            for (int i = 0; i &lt; numHormigas; i++)
            {
                CHormiga hormiga = new CHormiga();
                hormiga.Posicion =
                    new Point(rnd.Next(width), rnd.Next(height));
                hormiga.Direccion =
                    ((float)rnd.NextDouble() * 360) - 180;
                Hormigas.Add(hormiga);
            }
        }
</pre></p>
<p>El método MoverHormigas es el más interesante, pues debe calcular dónde dibujar las hormigas. Asimismo, verifica que las hormigas permanezcan dentro de los límites establecidos y, además, introduce una pequeña variación en la dirección que llevan los pequeños bichos:</p>
<p><pre class="brush: csharp;">
        public void MoverHormigas(float tiempo)
        {
            Random rnd = new Random();
            counter += 1;
            foreach (CHormiga hormiga in Hormigas)
            {
                float d = hormiga.Direccion;
                float radd = (float)((d * Math.PI) / 180);
                int dx = -(int)(Math.Sin(radd) * Velocidad * tiempo);
                int dy = (int)(Math.Cos(radd) * Velocidad * tiempo);
                Point p = hormiga.Posicion;
                p.X += dx;
                p.Y += dy;
                d += ((float)rnd.NextDouble() * 60) - 30;
                if ((p.X &gt; 0) &amp;&amp; (p.X &lt; Limits.X) &amp;&amp;
                    (p.Y &gt; 0) &amp;&amp; (p.Y &lt; Limits.Y))
                {
                    hormiga.Posicion = p;
                    hormiga.Direccion = d;
                }
                else
                {
                    hormiga.Direccion =
                        ((float)rnd.NextDouble() * 360) - 180; ;
                }
            }
        }
</pre></p>
<p>Bien, ya está hecho lo más difícil. Ahora tenemos que crear un formulario que haga uso de este pequeño universo.</p>
<p>Crearemos un nuevo formulario y simplemente le agregaremos dos botones y un control Timer.</p>
<p>El código del formulario es bastante simple. Básicamente, los botones sirven para iniciar o detener el timer. El timer se encarga de llamar al método MoverHormigas periódicamente. Lo demás ya nos debería parecer familiar:</p>
<p><pre class="brush: csharp;">
    public partial class frmHormigaZ02 : Form
    {
        CHormiguero hormiguero;

        public frmHormigaZ02()
        {
            InitializeComponent();
        }

        private void frmHormigaZ02_Load(object sender, EventArgs e)
        {
            hormiguero = new CHormiguero(20, this.Width, this.Height);
            this.Invalidate();
        }

        private void cmdIniciar_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            hormiguero.MoverHormigas(1);
            this.Invalidate();
        }

        private void frmHormigaZ02_Paint(object sender,
           PaintEventArgs e)
        {
            if (hormiguero != null)
                hormiguero.Render(e.Graphics);
        }

        private void cmdDetener_Click(object sender, EventArgs e)
        {
            timer1.Stop();
        }
    }
</pre></p>
<p>La simpleza del código anterior se debe a que hemos utilizado una clase controladora. Esa misma clase nos va a permitir introducir nuevos elementos en nuestra simulación, aunque eso será en el próximo artículo. Por ahora podemos entretenernos mirando como se mueven las hormigas y modificando algunos datos como la velocidad, los ángulos y la forma de las hormigas.</p>
<p>¡Hasta pronto!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/zameb.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/zameb.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/zameb.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/zameb.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/zameb.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/zameb.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/zameb.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/zameb.wordpress.com/128/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=128&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-movimiento/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/647be5f265c0ce73d186f5443ffcc8bf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">zameb</media:title>
		</media:content>
	</item>
		<item>
		<title>El hormiguero – Implementación</title>
		<link>http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-implementacion/</link>
		<comments>http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-implementacion/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 08:40:11 +0000</pubDate>
		<dc:creator>zameb</dc:creator>
				<category><![CDATA[CSharp]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[IA]]></category>

		<guid isPermaLink="false">http://zameb.wordpress.com/?p=125</guid>
		<description><![CDATA[Empezaremos por implementar la clase hormiga: Ahora crearemos un formulario que tan sólo tenga un botón. Declararemos un ArrayList que sirva para contener a varias hormigas. Esta sería la estructura de nuestra aplicación: Con el botón será posible agregar algunas hormigas al ArrayList. Editar el código de la siguiente manera: El evento Paint del formulario [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=125&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Empezaremos por implementar la clase hormiga:</p>
<p><pre class="brush: csharp;">
    public class CHormiga
    {
        public Point Posicion { get; set; }
        public float Direccion { get; set; }
        public int Estado { get; set; }

        public CHormiga()
        {
            Estado = 0;
        }

        public void Render(Graphics g)
        {
            Point p = Posicion;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.ResetTransform();
            g.TranslateTransform(p.X, p.Y);
            g.RotateTransform(Direccion);
            Pen pen = new Pen(Color.Black);
            Brush b = Brushes.Black;
            g.FillEllipse(b, new Rectangle(new Point(-2, 0), new Size(4, 6)));
            g.FillEllipse(b, new Rectangle(new Point(-1, 6), new Size(2, 2)));
            g.FillEllipse(b, new Rectangle(new Point(-2, 8), new Size(4, 4)));
            g.DrawLine(pen, 0, 12, -3, 15);
            g.DrawLine(pen, 0, 12, 3, 15);
            pen.Dispose();
        }
    }
</pre></p>
<p>Ahora crearemos un formulario que tan sólo tenga un botón. Declararemos un ArrayList que sirva para contener a varias hormigas. Esta sería la estructura de nuestra aplicación:</p>
<p><pre class="brush: csharp;">
    using System.Collections;

    public partial class frmHormigaZ : Form
    {
        ArrayList hormigas = new ArrayList();

        public frmHormigaZ()
        {
            InitializeComponent();
        }

        private void cmdIniciar_Click(object sender, EventArgs e)
        {
        }

        private void frmHormigaZ_Paint(object sender, PaintEventArgs e)
        {
        }
    }
}
</pre></p>
<p>Con el botón será posible agregar algunas hormigas al ArrayList. Editar el código de la siguiente manera:</p>
<p><pre class="brush: csharp;">
        private void cmdIniciar_Click(object sender, EventArgs e)
        {
            Random rnd = new Random();
            for (int i = 0; i &lt; 30; i++)
            {
                CHormiga hormiga = new CHormiga();
                hormiga.Posicion = 
                    new Point(rnd.Next(this.Width), 
                              rnd.Next(this.Height));
                hormiga.Direccion = 
                    ((float)rnd.NextDouble() * 360) - 180;
                hormigas.Add(hormiga);
            }
            this.Invalidate();
        }
</pre></p>
<p>El evento Paint del formulario será el encargado de mostrarnos a toda la colonia de bichos. Editar el código como se muestra:</p>
<p><pre class="brush: csharp;">
        private void frmHormigaZ_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            foreach (CHormiga hormiga in hormigas)
            {
                hormiga.Render(g);
            }
        }
</pre></p>
<p>Si ejecutamos ahora el proyecto y presionamos el botón, veremos algunas decenas de hormigas inmóviles:</p>
<p><a href="http://zameb.files.wordpress.com/2010/04/form1.jpg"><img src="http://zameb.files.wordpress.com/2010/04/form1.jpg?w=594" alt="" title="form1"   class="aligncenter size-full wp-image-126" /></a></p>
<p>Pues cierto, las hormigas no se mueven. No esperabas que, con tan poco trabajo, las hormigas se movieran, ¿verdad?</p>
<p>Cada hormiga necesita ser controlada dentro de un mini-universo que será una clase más:</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td colspan="2" width="420" valign="top">Clase Hormiguero</td>
</tr>
<tr>
<td width="155" valign="top">Atributo</td>
<td width="265" valign="top">Significado</td>
</tr>
<tr>
<td width="155" valign="top">Posición X,Y</td>
<td width="265" valign="top">Ubicación del nido: un simple agujero</td>
</tr>
<tr>
<td width="155" valign="top">Hormigas</td>
<td width="265" valign="top">Todo el ejército de entusiastas hormigas</td>
</tr>
<tr>
<td width="155" valign="top">Render</td>
<td width="265" valign="top">Dibujar toda la simulación</td>
</tr>
<tr>
<td width="155" valign="top">MoverHormigas</td>
<td width="265" valign="top">Pues eso</td>
</tr>
</tbody>
</table>
<p>Pero los detalles de esta nueva clase los veremos en la siguiente entrada del blog.</p>
<p>¡Hasta pronto!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/zameb.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/zameb.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/zameb.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/zameb.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/zameb.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/zameb.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/zameb.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/zameb.wordpress.com/125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=zameb.wordpress.com&amp;blog=10008085&amp;post=125&amp;subd=zameb&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://zameb.wordpress.com/2010/04/17/el-hormiguero-%e2%80%93-implementacion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/647be5f265c0ce73d186f5443ffcc8bf?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">zameb</media:title>
		</media:content>

		<media:content url="http://zameb.files.wordpress.com/2010/04/form1.jpg" medium="image">
			<media:title type="html">form1</media:title>
		</media:content>
	</item>
	</channel>
</rss>
