viernes, 14 de febrero de 2014

El Juego de la Vida de Conway (Conway's Life) en JAVA


Aquí les traigo parte de la teoría del juego de la vida y su respectivo código fuente de la aplicación programado en java, con interfaz gráfica, espero les sirva el documento.

Concepto y descripción de autómatas celulares

John Von Neumann investigó la cuestión del origen de la vida y trató de diseñar una máquina capaz de reproducirse. La idea en el diseño de auto-reproducción llevó a Von Neumann a inventar un sistema denominado: Autómatas Celulares, capaces de construir cualquier autómata a partir de un conjunto apropiado de instrucciones codificadas.
Los Autómata Celulares se consideran sistemas dinámicos extendidos, que consisten de un número considerable de componentes simples idénticos con conectividad local, y son definidos como un sistemas que evoluciona en tiempo y espacio discretos, compuesto de una colección de celdas discretas y deterministas, ordenadas en fila, en forma de matriz o en tres dimensiones, que actualizan sus estados a lo largo del tiempo en base a los estados que tenían las celdas vecinas en el momento inmediato anterior, en otras palabras, el estado siguiente de una celda es determinado por el estado actual de ella y de sus celdas vecinas, donde cada celda se comporta como un autómata de estado finito. Un autómata finito es un modelo de sistema con entradas y salidas discretas, consiste en un conjunto finito de estados y un conjunto de transiciones entre esos estados. La entrada y el estado actuales del autómata determinan su conducta en el instante siguiente.

Un Autómata celular consiste de dos componentes: el primero es un espacio celular, una red de n celdas de estado finito, cada una con un patrón idéntico de conexiones locales con otras celdas, junto con condiciones de límite, si se trata de una red finita. El segundo componente consiste en reglas de transición que actualizan, o bien definen los estados de cada celda, donde éstos estados junto con el de las celdas conectadas a ellas dan lugar a lo que es una vecindad.


El Juego de La Vida de Conway (Conway’s Life)

John Horton Conway nació en 1937, comenzó su carrera de Matemáticas en la Universidad de Cambrige. A finales de 1960 Conway, motivado por el trabajo de Von Neumann, siguiendo la idea de construir una máquina capaz de construir copias de sí misma y haciendo uso del concepto de vecindad de un autómata definido por Moore, diseñó y dió a conocer el autómata celular más famoso: El juego de la Vida (The Game of the Life), también llamado El Juego de Conway (Conway’s Life), un juego de sentido solitario, es decir, para un solo jugador. Éste juego es un autómata bidimensional donde cada célula puede estar en uno de los dos estados 0 o 1, (muerto o vivo). A partir de un estado inicial el autómata va a evolucionar en base a unas funciones de trancisión, además una célula estará en un estado concreto determinado unicamente por el estado anterior de las celulas vecinas, así como el de la propia célula.


Conway definió el siguiente conjunto de reglas:
  • SOLEDAD, si una célula viva esta sola o tiene un solo vecino muere.
  • SOBREPOBLACIÓN, si una célula viva tiene más de tres vecinos muere.
  • ESTABILIDAD, de lo contrario la célula se queda igual.

DISEÑO FORMAL DE AUTOMATA CELULAR DEL JUEGO DE LA VIDA

Conjunto de Estados
Q
(Muerto o Vivo)
Alfabeto
(0, 1)
Transición
Ҏ
Muerto (0) o Vivo (1)
Estado Inicial
qo
Estático
Conjunto de estados finales
F
Dinámico
Espacio de celulas
n x m
Número de Filas (n)
Número de Columnas (m)
Reglas de transición

  • Soledad
  • Sobrepoblación
  • Estabilidad

  • Si una célula viva esta sola o tiene un solo vecino muere.
  • Si una célula viva tiene más de tres vecinos muere
  • De lo contrario la célula se queda igual.


CODIFICACIÓN DE LOS ESTADOS:

public void procesar() {
        for (int i = 1; i < fil - 1; i++) {
            for (int j = 1; j < col - 1; j++) {
                int sum = m[i - 1][j - 1] + m[i][j - 1] + m[i + 1][j - 1] + m[i + 1][j] + m[i + 1][j + 1] + m[i][j + 1] + m[i - 1][j + 1] + m[i - 1][j];
                if (sum == 3) {
                    mt[i][j] = 1;
                } else if (sum != 2) {
                    mt[i][j] = 0;
                }
            }
        }
        this.copiaMatriz();
    }


CODIFICACIÓN DE ENTORNO Y DE EL PROGRAMA EN GENERAL:

Main.java:

/**
 * @author Andrea Dorado
 */

public class Main {
    public static void main(String[] args) {
        Ventana mjf = new Ventana();
        mjf.setSize(900, 650);
        mjf.setVisible(true);
    }
}


Ventana.java:

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

/**
 * @author Andrea Dorado
 */
public class Ventana extends JFrame implements ActionListener {

    JMenuBar menuBar;
    JMenu mnFile;
    JMenuItem mniExit;
    Lienzo pnlGraphic;
    JPanel pnlEast, pnlEastTop, pnlEastBottom;
    JToolBar toolBar;
    JButton btnEjecutar;
    ButtonGroup btnGroup;
    Timer timer;

    public Ventana() {
        super("INF - 154 Lenguajes Formales y Autómatas (El Juego de la Vida)");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        menuBar = new JMenuBar();
        mnFile = new JMenu("Archivo");
        mniExit = new JMenuItem("Salir");
        pnlEast = new JPanel();
        pnlEastTop = new JPanel();
        pnlEastBottom = new JPanel();
        pnlGraphic = new Lienzo();
        toolBar = new JToolBar();
        btnEjecutar = new JButton("Ejecutar");
        btnGroup = new ButtonGroup();
        pnlEast.setLayout(new BoxLayout(pnlEast, BoxLayout.Y_AXIS));
        pnlEastTop.setLayout(new BoxLayout(pnlEastTop, BoxLayout.Y_AXIS));
        pnlEastBottom.setLayout(new BoxLayout(pnlEastBottom, BoxLayout.Y_AXIS));
        pnlEastBottom.setAlignmentX(Component.CENTER_ALIGNMENT);
        pnlEastTop.setAlignmentX(Component.CENTER_ALIGNMENT);
        menuBar.add(mnFile);
        mnFile.add(mniExit);
        pnlEast.add(pnlEastTop);
        pnlEast.add(pnlEastBottom);
        toolBar.add(btnEjecutar);
        toolBar.add(Box.createRigidArea(new Dimension(20, 0)));
        setJMenuBar(menuBar);
        this.add("North", toolBar);
        this.add("East", pnlEast);
        this.add("Center", pnlGraphic);
        mniExit.addActionListener(this);
        btnEjecutar.addActionListener(this);
        timer = new Timer(1000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                pnlGraphic.repaint();
            }
        });
       
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == mniExit) {
            System.exit(0);
        }
        if (e.getSource() == btnEjecutar) {
            timer.start();
        }
    }
}


Lienzo.java:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

/**
 * @author Andcrea Dorado
 */
public class Lienzo extends JPanel {

    int fil, col;
    int[][] m = new int[100][100];
    int[][] mt = new int[100][100];

    public Lienzo() {
        fil = 35;
        col = 50;
        m[3][2] = m[3][3] = m[3][4] = m[3][5] = m[3][6] = m[3][7] = m[3][8] = m[3][9] = m[3][11] = m[3][12] = m[3][17] = m[3][18] = m[3][20] = m[3][21] = m[3][22] = m[3][23] = m[3][24] = m[3][25] = m[3][26] = m[3][27] = m[3][35] = m[3][37] = m[3][38] = m[3][39] = m[3][40] = m[3][45] = 1;
        m[4][2] = m[4][3] = m[4][4] = m[4][5] = m[4][6] = m[4][7] = m[4][8] = m[4][9] = m[4][11] = m[4][12] = m[4][17] = m[4][18] = m[4][20] = m[4][21] = m[4][22] = m[4][23] = m[4][24] = m[4][25] = m[4][26] = m[4][27] = m[4][34] = m[4][35] = m[4][37] = m[4][40] = m[4][44] = m[4][45] = 1;
        m[5][5] = m[5][6] = m[5][11]=  m[5][12]=  m[5][13]= m[5][17]=m[5][18]=m[5][20]=m[5][21]=m[5][33]=m[5][35]=m[5][37]=m[5][43]=m[5][45]=1;
        m[6][5]=m[6][6]=m[6][11]=m[6][12]=m[6][13]=m[6][14]=m[6][17]=m[6][18]=m[6][20]=m[6][21]=m[6][22]=m[6][23]=m[6][32]=m[6][35]=m[6][37]=m[6][38]=m[6][39]=m[6][40]=m[6][42]=m[6][43]=m[6][44]=m[6][45]=1;
        m[7][5]=m[7][6]=m[7][11]=m[7][12]=m[7][14]=m[7][15]=m[7][17]=m[7][18]=m[7][20]=m[7][21]=m[7][22]=m[7][23]=m[7][27]=m[7][28]=m[7][29]=m[7][30]=m[7][35]=m[7][40]=m[7][45]=1;
        m[8][5]=m[8][6]=m[8][11]=m[8][12]=m[8][15]=m[8][16]=m[8][17]=m[8][18]=m[8][20]=m[8][21]=m[8][27]=m[8][28]=m[8][29]=m[8][30]=m[8][35]=m[8][40]=m[8][45]=1;
        m[9][2]=m[9][3]=m[9][4]=m[9][5]=m[9][6]=m[9][7]=m[9][8]=m[9][9]=m[9][11]=m[9][12]=m[9][16]=m[9][17]=m[9][18]=m[9][20]=m[9][21]=m[9][35]=m[9][37]=m[9][40]=m[9][45]=1;
        m[10][2]=m[10][3]=m[10][4]=m[10][5]=m[10][6]=m[10][7]=m[10][8]=m[10][9]=m[10][11]=m[10][12]=m[10][17]=m[10][18]=m[10][20]=m[10][21]=m[10][35]=m[10][37]=m[10][38]=m[10][39]=m[10][40]=m[10][45]=1;
        m[20][2]=m[20][3]=m[21][2]=m[21][3]=1;
        m[20][7]=m[21][7]=m[22][7]=m[19][8]=m[18][9]=m[18][10]=m[23][8]=m[24][9]=m[24][10]=1;
        m[21][11]=m[19][12]=m[20][13]=m[21][13]=m[22][13]=m[21][14]=m[23][12]=1;
       
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        int mi = 0;
        int mj = 0;

        Color colorActual = new Color(0, 0, 255);
        for (int j = 1; j < this.getHeight(); j += this.getHeight() / fil) {

            for (int i = 1; i < this.getWidth(); i += this.getWidth() / col) {
                if (m[mj][mi] == 1) {
                    g.setColor(colorActual);
                    g.fillRect(i, j, this.getWidth() / col, this.getHeight() / fil);
                }
                mi++;
            }
            mj++;
            mi = 0;
        }
        this.drawLine(g2d, Color.black);
        this.procesar();
    }

    public void drawLine(Graphics2D g2d, Color color) {
        g2d.setColor(color);
        for (int i = 0; i < getWidth(); i += this.getWidth() / 50) {
            g2d.drawLine(i, 0, i, getHeight());
        }
        for (int i = 0; i < getHeight(); i += this.getHeight() / 35) {
            g2d.drawLine(0, i, getWidth(), i);
        }
    }

    public void procesar() {
        for (int i = 1; i < fil - 1; i++) {
            for (int j = 1; j < col - 1; j++) {
                int sum = m[i - 1][j - 1] + m[i][j - 1] + m[i + 1][j - 1] + m[i + 1][j] + m[i + 1][j + 1] + m[i][j + 1] + m[i - 1][j + 1] + m[i - 1][j];
                if (sum == 3) {
                    mt[i][j] = 1;
                } else if (sum != 2) {
                    mt[i][j] = 0;
                }
            }
        }
        this.copiaMatriz();
    }

    public void copiaMatriz() {
        for (int i = 1; i < fil - 1; i++) {
            for (int j = 1; j < col - 1; j++) {
                m[i][j] = mt[i][j];
            }
        }
    }
}


Si te gustó esta publicación no olvides compartirlo. Espero sus comentarios.



2 comentarios: