/* Conway s Game Of Life (in Spanish) Juego de la Vida v. 0.1 implementacion de Henrik Mitsch (henx@bigfoot.com) probablemente online en http://henx.home.dhs. org/juegodelavida.html */ import java.applet.*; import java.awt.*; import java.awt.event.*; public class JuegoDeLaVida extends Applet implements Runnable, ActionListener, ItemListener { private CelulasEspacio mundo; // campo del juego private boolean trabajando; // variable por la gestion del hilo private Thread hilo; private int gentiempo; // tiempo para crear siguiente generacion private String pez="pez"; // Item para forma private String linea10="linea de 10 Celulas"; // Item para forma private String henx="nombre del autor"; private Choice seleccion; // Choice para Items private Button siguiente, vaciar, aleatorio, comenzar, terminar; // controles 1
private Panel botones; // Panel para controles public void init() { // funcion que esta llamado primero int tamanocelula; // tamano en pixles para la celula int numcol; // cantidad de columnas int numlin; // cantidad de lineas String param; // variable temporal para guardar el parametro del fichero HTML // configurar fondo setbackground (new Color(0x999999)); // leer parametros del fichero HTML param = getparameter("tamanocelula"); if (param==null) tamanocelula = 10; else tamanocelula = Integer.valueOf(param). intvalue(); param = getparameter("numcol"); if (param==null) numcol = 30; else numcol = Integer.valueOf(param).intValue(); param = getparameter("numlin"); if (param==null) 2
numlin = 30; else numlin = Integer.valueOf(param).intValue(); param = getparameter("gentiempo"); if (param==null) gentiempo = 200; else gentiempo = Integer.valueOf(param).intValue(); // formar Choice con formas seleccion = new Choice(); seleccion.additem(pez); seleccion.additem(linea10); seleccion.additem(henx); seleccion.additemlistener(this); // para recibir eventos // formar panel de control // cada boton recibe un ActionListener para coger eventos botones=new Panel(); botones.setlayout(new GridLayout(2,3)); botones.add(siguiente=new Button("Siguiente")); siguiente.addactionlistener(this); botones.add(vaciar=new Button("Vaciar")); vaciar.addactionlistener(this); botones.add(aleatorio=new Button("Aleatorio")); aleatorio.addactionlistener(this); 3
botones.add(comenzar=new Button("Comenzar")); comenzar.addactionlistener(this); botones.add(terminar=new Button("Terminar")); terminar.addactionlistener(this); botones.add(seleccion); // anadir choice de formas al final // formar juego (controles y campo de juego) setlayout(new BorderLayout()); add("north", botones); mundo = new CelulasEspacio(tamanoCelula, numcol, numlin); add("center", mundo); trabajando=false; // iniciar variable // anadir KeyListener para coger eventos del teclado // cada boton recibe un KeyListener siguiente.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); vaciar.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); 4
aleatorio.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); comenzar.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); terminar.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); // anadir KeyListener al Choice seleccion.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); // al final hay que anadir un Listener al campo del juego mundo.addkeylistener(new KeyAdapter() { public void keypressed(keyevent evento) { funcioncomunteclado(evento); ); 5
// tratar eventos del Teclado // aumentar o disminur velocidad de generacion private void funcioncomunteclado(keyevent evento) { int param = evento.getkeycode(); if (param == KeyEvent.VK_UP) gentiempo=gentiemp if (param == KeyEvent.VK_DOWN) { gentiempo=gentiempo-50; if (gentiempo<0) gentiempo=0; showstatus("retraso es "+gentiempo+" ms"); public void run() { // funcion que se llama cuando un hilo empieza a trabajar while (hilo!=null) { // mientras existe el hilo mundo.siguiente(); // calcular siguiente generacion mundo.repaint(); // dibujar generacion try { hilo.sleep(gentiempo); // descanzar hilo (tiempo en ms) catch (InterruptedException e) {; public void actionperformed(actionevent e) { // 6
metodo que se llama cuando acurra un evento del interfaz ActionListener (botones) String param=e.getactioncommand(); if (param.equals("siguiente")) { // siguiente mundo.siguiente(); mundo.repaint(); else if (param.equals("vaciar")) { // vaciar mundo.vaciar(); mundo.repaint(); else if (param.equals("aleatorio")) { // aleatorio mundo.llenaraleatorio(); mundo.repaint(); else if (param.equals("comenzar")&&!trabajando) { // comenzar hilo = new Thread(this); hilo.start(); // llama a funcion run() trabajando=true; else if (param.equals("terminar")&&trabajando) { // terminar hilo.stop(); trabajando=false; 7
public void itemstatechanged(itemevent e) { // este metodo esta llamado del ItemListener (Choice - formas) Object param=e.getitem(); if (param.equals(pez)) { // forma pez int forma[] = { 0,1, 0,3, 1,0, 2,0, 3,0, 3,3, 4,0, 4,1, 4,2 ; dibujarforma(5, 4, forma); else if (param.equals(linea10)) { // forma linea de 10 celulas int forma[] = { 0,0, 1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,0, 9,0; dibujarforma(10, 1, forma); else if (param.equals(henx)) { // forma de mi nombre int forma[] = {0,0, 0,1, 0,2, 0,3, 0,4, 1,2, 2,2, 3,2, 4,0, 4,1, 4,2, 4,3, 4,4, 7,0, 7,1, 7,2, 7,3, 7,4, 8,0, 9,0, 8,2, 8,4, 9,4, 12,0, 12,1, 12,2, 12,3, 12,4, 13,1, 14,2, 15,3, 16,0, 16,1, 16,2, 16,3, 16,4, 8
19,0, 20,1, 21,2, 22,3, 23,4, 19,4, 20,3, 22,1, 23,0; dibujarforma(23,5,forma); public String getappletinfo() { // return " Juego de la Vida v. 0.1 Henrik Mitsch (henx@bigfoot.com) no Copyright 2000"; public void dibujarforma(int formawidth, int formaheight, int forma[]) { if (!mundo.dibujarforma(formawidth, formaheight, forma)) showstatus("forma no cabe."); else { showstatus(""); mundo.repaint(); /* ************** Class CelulasEspacio ************ ******* */ class CelulasEspacio extends Canvas { 9
public int generacion; // variable para guardar la edad del mundo private int populacion; // para guardar el numero de celulas vivas private int tamanocelula; // tamono de una celula private int numcol; // numero de columnas private int numlin; // numero de lineas private boolean[][] celulas; // sirve para guardar el status actual de las celulas private int[][] celulasbuffer; // sirve para calcular el numero de vecions para calcular la siguiente generacion private Image fueradepantallaimagen; // sirve para accelerar el metodo paint() private Dimension fueradepantallatamano; // accelerar paint() private Graphics fueradepantallagrafica; // accelerar paint() private int numcelulas; // sirve para rellenar el campo con celulas aleatorias public CelulasEspacio(int tamanocelula, int numcol, 10
int numlin) { // constructor de la clase celulas = new boolean[numcol][numlin]; celulasbuffer = new int[numcol][numlin]; this.tamanocelula = tamanocelula; // transferir las variables del input a las variables de esta clase this.numcol = numcol; this.numlin = numlin; this.numcelulas = numcol*numlin; setbounds(0, 0, tamanocelula*numcol-1, tamanocelula numlin-1); // resize component vaciar(); // borrar todas celulas // anadir MousListener para coger eventos del raton // mouseclicked es una "Clase Anonima" para no tener // implementar el interfaz MouseListener this.addmouselistener(new MouseAdapter() { public void mouseclicked(mouseevent evento) { eventomouseclicked(evento); ); public void eventomouseclicked(mouseevent evento) { // poner la celula al reves (invertir) int x = evento.getx(); // coger coordinatas int y = evento.gety(); try { 11
celulas[x/tamanocelula][y/tamanocelula] =!celulas[ x/tamanocelula][y/tamanocelula]; // invertir celula catch (Exception e) { // catch excepcion en caso de que el usuario // hace un click alrededor del campo del juego repaint(); public final synchronized void update(graphics g) { // funcion llamado por repaint() /* funciona mucho mas rapido con este algoritmo que con paint(g). algoritmo encontrado en un FAQ de java (http://metalab.unc.edu/javafaq/javafaq.html). */ Dimension d = getsize(); if ((fueradepantallaimagen == null) (d.width!= fueradepantallatamano.width) (d.height!= fueradepantallatamano.height)) { fueradepantallaimagen = createimage(d.width, d. height); fueradepantallatamano = d; fueradepantallagrafica = fueradepantallaimagen. getgraphics(); fueradepantallagrafica.clearrect(0,0, d.width, d. 12
height); paint(fueradepantallagrafica); g.drawimage(fueradepantallaimagen, 0, 0, null); public void paint(graphics g) { // dibujar el mundo // dibujar fondo g.setcolor(color.gray); g.fillrect(0, 0, tamanocelula*numcol-1, tamanocelula* numlin-1); // dibujar red (grid) g.setcolor(getbackground()); for (int x=1; x<numcol; x++) { g.drawline(x*tamanocelula-1, 0, x*tamanocelula-1, tamanocelula*numlin-1); for (int y=1; y<numlin; y++) { g.drawline(0, y*tamanocelula-1, tamanocelula* numcol-1, y*tamanocelula-1); // dibujar celulas vivas g.setcolor(color.green); for (int y=0; y<numlin; y++) for (int x=0; x<numcol; x++) if (celulas[x][y]) g.fillrect(x*tamanocelula, y*tamanocelula, 13
tamanocelula-1, tamanocelula-1); // escribir generacion y populacion g.setcolor(color.white); contarpopulacion(); g.drawstring("generacion: "+generacion+" Populacion: "+populacion, 1, numlin*tamanocelula-2); public void vaciar() { // borrar mundo generacion = 0; populacion = 0; for (int x=0; x<numcol; x++) for (int y=0; y<numlin; y++) celulas[x][y] = false; public void llenaraleatorio() { // llenar mundo con celulas aleatorias int x; // coordinatas de la celula int y; int cantidad; // numero de celulas que van a vivir en este mundo vaciar(); // borrar mundo generacion++; // crear primera generacion do { 14
cantidad = (int) (Math.random()*numCelulas); while (cantidad<numcelulas*0.3 cantidad> numcelulas*0.7); /* el while asegura que no haya ni demasiadas pocas ni demasiadas celulas vivas (entre 30% y 70%). */ for (int i=0; i<=cantidad; i++) { x = (int) (Math.random()*numCol); // generar coordinatas y = (int) (Math.random()*numLin); // aleatorias celulas[x][y] = true; // poner la celula viva public void siguiente() { // crear la siguiente generacion int x; // variables da ayuda int y; generacion++; // aumentar generacion // borrar el buffer for (x=0; x<numcol; x++) for (y=0; y<numlin; y++) celulasbuffer[x][y] = 0; // contar vecinos de celulas lejos de la esquina 15
for (x=1; x<numcol-1; x++) { for (y=1; y<numlin-1; y++) { if (celulas[x][y]) { celulasbuffer[x-1][y-1]++; celulasbuffer[x][y-1]++; celulasbuffer[x+1][y-1]++; celulasbuffer[x-1][y]++; celulasbuffer[x+1][y]++; celulasbuffer[x-1][y+1]++; celulasbuffer[x][y+1]++; celulasbuffer[x+1][y+1]++; // contar vecinos de celulas en las esquina x=1; y=0; // empezar en (1,0) int dx=1; int dy=0; while (true) { if (celulas[x][y]) { if (x>0) { if (y>0) celulasbuffer[x-1][y-1]++; if (y<numlin-1) celulasbuffer[x-1][y+1]++; celulasbuffer[x-1][y]++; if (x<numcol-1) { 16
if (y<numlin-1) celulasbuffer[x+1][y+1]++; if (y>0) celulasbuffer[x+1][y-1]++; celulasbuffer[x+1][y]++; if (y>0) celulasbuffer[x][y-1]++; if (y<numlin-1) celulasbuffer[x][y+1]++; // girar en el sentio del reloj en colision con esquina if (x==numcol-1 && y==0) { dx=0; dy=1; else if (x==numcol-1 && y==numlin-1) { dx=-1; dy=0; else if (x==0 && y==numlin-1) { dx=0; dy=-1; else if (x==0 && y==0) { // estamos listo break; 17
x=x+dx; y=y+dy; // algoritmo Juego de la Vida for (x=0; x<numcol; x++) { for (y=0; y<numlin; y++) { switch (celulasbuffer[x][y]) { case 2: break; // no cambio case 3: celulas[x][y] = true; break; // nace vida default: celulas[x][y] = false; break; // muere la celula contarpopulacion(); public void contarpopulacion() { // contar la populacion populacion=0; for (int x=0; x<numcol; x++) for (int y=0; y<numlin; y++) if (celulas[x][y]) 18
populacion++; public boolean dibujarforma(int formawidth, int formaheight, int forma[]) { // sirve para dibujar las formas de la seleccion (Choice) int x0; // variables da ayuda int y0; // para encontrar el centro del campo (offset) if (formawidth>numcol formaheight>numlin) return false; // forma no cabe x0 = (numcol-formawidth)/2; // calcular centro y0 = (numlin-formaheight)/2; vaciar(); for (int i=0; i<forma.length; i=i+2) // meter forma celulas[x0+forma[i]][y0+forma[i+1]] = true; return true; 19