domingo, septiembre 25, 2011

El juego de la vida de Conway (parte 2):


En la parte 1 de este tema, comentaba que Alan Turing siguiendo su propia intuición descubrió y demostró matemáticamente la AUTOORGANIZACIÓN.

Posiblemente las células de los seres vivos evolucionen de forma similar. No tienen una comunicación clara con el resto de células, y tampoco hay nada que controle todas la células, pero cada una de ellas termina teniendo una función diferenciada.

Turing abrió el camino, pero luego otros se dedicaron a "diseñar" sus propios "autómatas celulares". En 1970 John Horton Conway publicó su autómata en Scientific American en la sección dedicada a juegos matemáticos.

Hoy en día es el autómata celular más conocido y se llama "JUEGO DE LA VIDA". Las reglas son muy sencillas:

Es un juego en el que tenemos un tablero dónde inicialmente colocamos una serie de células vivas.

Generación a generación las células del tablero irán naciendo o muriendo siguiente estas reglas:

1.-Si una célula viva tiene a su alrededor menos de 2 células vivas se muere por "soledad".
2.-Si una célula viva tiene a su alrededor más de 3 células vivas se muere por "superpoblación".
3.-En una celda que esté rodeada por exactamente 3 células vivas surgirá vida en forma de una célula viva.

Este es el programa que he hecho en VB.NET.

Muestra un tablero de 20 x 20, dónde podemos marcar las celdas con células vivas.
Hay tres botones:
  1. Haciendo clic en "Una hora más" aplicamos las reglas para pasar a ver cómo queda la siguiente generación de células.
  2. Pinchando "Lanzar hasta el final" vemos como evolucionan las células hasta el infinito.
  3. Para terminar la simulación clic en "FIN".
En el próximo post publicaré en algún sitio el ejecutable (se aceptan sugerencias), y algunas de las figuras más conocidas que se crean, y que reciben un nombre que describe su comportamiento.

El código fuente:




Option Explicit On
Option Strict On

Imports System.Drawing.Drawing2D
Imports System.Math 'para truncate()
Imports System.Threading.Thread 'para usar sleep()

Public Class Form1

Dim oPen As Pen
Dim oGrafico As Graphics
Dim cuadro(20, 20) As Boolean

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.BackColor = Color.Gray
Dim i, j As Integer
For i = 1 To 20
For j = 1 To 20
cuadro(i, j) = False
Next
Next
End Sub

Private Sub Form1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
Dim punto As Point
Dim cuadroX As Integer
Dim cuadroY As Integer
If e.Location.X > 30 And e.Location.X < 630 And e.Location.Y > 30 And e.Location.Y < 630 Then
cuadroX = CInt(Truncate(e.Location.X / 30))
cuadroY = CInt(Truncate(e.Location.Y / 30))
cuadro(cuadroX, cuadroY) = True
punto.X = cuadroX * 30
punto.Y = cuadroY * 30
'Dibujamos un círculo negro...
oGrafico.FillEllipse(New SolidBrush(Color.Black), New Rectangle(punto, New Size(30, 30)))
End If
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

Dim x, y As Integer
oGrafico = Me.CreateGraphics
oPen = New Pen(Color.White, 1)

For x = 1 To 21
'Ponemos 21 columnas:
Dim pt1 As New Point(30 * x, 30)
Dim pt2 As New Point(30 * x, 630)
oGrafico.DrawLine(oPen, pt1, pt2)

Next
For y = 1 To 21
'Ponemos 21 filas:
Dim pt1 As New Point(30, 30 * y)
Dim pt2 As New Point(630, 30 * y)
oGrafico.DrawLine(oPen, pt1, pt2)
Next
dibujarCelulas()
End Sub

Private Sub btnUnaHoraMas_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUnaHoraMas.Click
nuevaGeneracion()
End Sub

Private Sub btnLanzarHastaElFinal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLanzarHastaElFinal.Click
Timer1.Enabled = True
End Sub

Private Sub nuevaGeneracion()
Dim i, j, numVecinos As Integer
Dim cuadroNuevo(20, 20) As Boolean
For i = 1 To 20
For j = 1 To 20
cuadroNuevo(i, j) = cuadro(i, j)
numVecinos = vecinos(i, j)
If cuadro(i, j) Then 'si la célula está viva...
If numVecinos <> 2 And numVecinos <> 3 Then
cuadroNuevo(i, j) = False
End If
Else 'si la célula está muerta...
If numVecinos = 3 Then cuadroNuevo(i, j) = True
End If
Next
Next
cuadro = cuadroNuevo
dibujarCelulas()
End Sub

Private Sub dibujarCelulas()
Dim punto As Point
'dibujar la nueva situación:
For i = 1 To 20
For j = 1 To 20
punto.X = i * 30
punto.Y = j * 30
If cuadro(i, j) Then
'Dibujamos círculo negro
oGrafico.FillEllipse(New SolidBrush(Color.Black), New Rectangle(punto, New Size(30, 30)))
Else 'Dibujamos círculo gris que es como borra ya que el fondo es gris.
oGrafico.FillEllipse(New SolidBrush(Color.Gray), New Rectangle(punto, New Size(30, 30)))
End If
Next
Next
End Sub

Private Function vecinos(ByVal i As Integer, ByVal j As Integer) As Integer
Dim numero As Integer = 0
If i > 1 And j > 1 Then
If cuadro(i - 1, j - 1) Then numero = numero + 1
End If
If i > 1 Then
If cuadro(i - 1, j) Then numero = numero + 1
End If
If i > 1 And j < 20 Then
If cuadro(i - 1, j + 1) Then numero = numero + 1
End If
If j > 1 Then
If cuadro(i, j - 1) Then numero = numero + 1
End If
If j < 20 Then
If cuadro(i, j + 1) Then numero = numero + 1
End If
If i < 20 And j > 1 Then
If cuadro(i + 1, j - 1) Then numero = numero + 1
End If
If i < 20 Then
If cuadro(i + 1, j) Then numero = numero + 1
End If
If i < 20 And j < 20 Then
If cuadro(i + 1, j + 1) Then numero = numero + 1
End If
Return numero
End Function

Private Sub btnFin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFin.Click
Timer1.Enabled = False
Application.Exit()
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
nuevaGeneracion()
End Sub
End Class

3 comentarios:

Anónimo dijo...

Oye.. no me podrás mandar ese programa¿? o dejarme un link de descarga, me parece interesate y no se como hacerlo.. si es posible mandarlo asi en codigo de visual.. para ver si puedo cambiar los colores

Aitor Iriarte dijo...

A ver si esta noche lo subo a algún sitio. Te dejaré aquí el enlace.
Saludos.

Aitor Iriarte dijo...

Perdona el retraso.
Lo he subido aquí.
Cambia la extensión del fichero de .zipi a .zip.
Está la solución completa. Necesitarás el framework 4 para ejecutarlo.
Saludos.