[leicht bis mittel-schwer] Game Of Life

CDW

0
Mitarbeiter
Wie kann es nur sein, dass der Klassiker vergessen wurde ;)
Eingereicht von Tarantoga
Die Aufgabe wäre es eine Anwendung zu schreiben, bei der man eine Ausgangskonfiguration von "lebenden" Zellen einstellen kann & dann, anhand von 4 einfachen Regeln, die Folgegenerationen berechnen kann.
Verschiedene Schwierigkeitsgrade wären auch denkbar, z. B. kann man die Ausgabe ganz simpel in der Konsole als eine Folge aus 0en und Xen darstellen, animiert in einem Applet oder animiert im Fenster einer stand-alone Applikation...

Die Regeln gibt's bei Wikipedia:
http://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens
d.h:
Es gibt ein Spielfeld, auf dem Zellen "leben". Nach einiger Zeit ist der Lebenszyklus der Zellen vorbei und die Zeit der nächsten Generation bricht an (simpel gesagt: nächste Runde). Dann wird die neue Zellgeneration so berechnet:
- eine Zelle wird dann geboren, wenn sie genau drei lebende Nachbarn hat
- eine Zelle stirbt, wenn sie weniger als 2 lebende Nachbarn hat
- eine Zelle bleibt weiterhin am leben, wenn sie 2 oder 3 lebende Nachbarn hat
- Zellen mit mehr als 3 lebenden Nachbarn sterben an Überbevölkerung

Einfach:
In der einfachsten Variante reicht es aus, ein Feld von einer vorgegebenen Maximalgröße zu haben und die Startgeneration im Code "fest" einzutragen.
Als Ausgabe darf eine Konsole/Datei genommen werden.

Fortgeschritten:
Fortgeschrittene Variante soll ein (theoretisch) unendliches Spielfeld haben und die Startgeneration aus einer Textdatei einlesen.
Das Format ist auf "benutzerfreundlichkeit" getrippt und arbeitet nur mit ASCIIs:
Leerzeichen für "nichts" und "X" für eine Zelle:
Code:
  X  X
  XXX
    X
damit lassen sich schon Positionen (relativ zu den anderen Zellen) festlegen und ihr müsst euch ein wenig Gedanken machen, wie man das am geschicktesten einliest ;)

Auch hier: Ausgabe über Konsole/Datei reicht aus, allerdings muss man sich überlegen, nicht das gesamte (unendliche) Spielfeld auszugeben, sondern nur den relevanten Ausschnitt mit den Zellen ;).
Der Ausschnitt darf aber eine feste Größe haben (also z.B 80x50 und ähnliches) und den nicht mehr "hineinpassenden" Teil des Feldes weglassen. Es geht hier eigentlich nur darum, nicht einfach stumpf die ersten x Position anzuzeigen (egal ob leer, oder mit Zellen gefüllt), sondern die Ausgabe "intelligent" auf die vorhanden Zellen zu "setzen"
Beispielausgabe auf der Konsole (die als ASCII gespeichert auch als Eingabe für den Startzustand benutzt werden kann)
Code:
                       XX                        XX
                       XX                        XX
                                         XX
                                        X  X
                                         XX

                                    XXX
                                    X X
         XX                         XXX
         XX                         XX
        X  X                       XXX
        X  X XX                    X X
        X    XX                    XXX
          XX XX
                               XX
                     XX       X  X
                     XX        XX
                                                 XX
                                                 XX

    XX                  X
XX    XXXX          XX  XX XXX
XX  XX XXX          XX    XXXX
    X                   XX

"Schwer"
die "schwere" Variante hat zusätzlich zu allen Funktionen eine hübsche grafische Ausgabe (Applet/Fenster/WebSeite usw). Dabei sollte unbedingt bedacht werden, dass es auch so genannte "Glider" gibt:
3227d1277304483-leicht-bis-mittel-game-life-glider2.gif

also "Objekte", die sich von der großen "Zellmasse" losmachen und auf "Reisen" gehen.
Hierzu sollte man sich überlegen, wie man eine halbwegs benutzerfreundliche Anzeige umsetzt (das strickte Wegzoomen geht ja nur bis zur eine gewissen Grenze, das simple Scrollen auf dem Feld kann auch alles andere als einfach sein, wenn die Zellen zu weit auseinander liegen - also wird man sich zumindest eine Kombination überlegen müssen ;)).
Zusätzlich kann man sich einige Gedanken zu seinem verwendeten Algorithmus machen - insbesondere für sehr große Felder. Auf Wunsch kann ich ein 500x500 Feld freigeben, bei dem man nach X Runden eine vordefinierte Ausgabe erhält und die Laufzeit sich sehr deutlich je nach verwendetem Algorithmus unterscheidet.
 
Bei meiner Lösung handelt es sich um eine simple Demonstration mit Hilfe von SDL; in C programmiert. Das Einlesen aus einer Text-Datei macht für mich keinen Sinn, aber vlt. werde ich eine Zoom- und Zeichen-Funktion nach WM und Uni-Prüfungen nachliefern. :wink:

Code:
#include <stdlib.h>
#include <SDL.h>
#include <time.h>
#include "SDL_draw.h"

SDL_Surface *screen;

#define W 160
#define H 120
#define QU 5
#define PERC 90

int quads[W][H];

void init() {
    int i,k;
    for (i=0;i<W;i++) { for (k=0;k<H;k++) { if ((rand() % 100 + 1)>PERC) quads[i][k]=1; else quads[i][k]=0; } }
}

Uint32 update (Uint32 intervall, void *parameter) {
    int i,k,sum,chk[20000][3],count=0;
    for (i=0;i<W;i++) {
        for (k=0;k<H;k++) {
            sum=0;
            if (i>0 && k>0 && quads[i-1][k-1]==1) sum++;
            if (k>0 && quads[i][k-1]==1) sum++;
            if (i<(W-1) && k>0 && quads[i+1][k-1]==1) sum++;
            if (i>0 && k<(H-1) && quads[i-1][k+1]==1) sum++;
            if (k<(H-1) && quads[i][k+1]==1) sum++;
            if (i<(W-1) && k<(H-1) && quads[i+1][k+1]==1) sum++;
            if (i>0 && quads[i-1][k]==1) sum++;
            if (i<(W-1) && quads[i+1][k]==1) sum++;
            if (quads[i][k]==0 && sum==3) {
                chk[count][0]=i;
                chk[count][1]=k;
                chk[count][2]=1;
            }
            if (quads[i][k]==1 && (sum<2 || sum>3)) {
                chk[count][0]=i;
                chk[count][1]=k;
                chk[count][2]=0;
            }
            count++;
        }
    }
    for (i=0;i<count;i++) quads[chk[i][0]][chk[i][1]]=chk[i][2];
    return 50;
}

void draw() {
    int i,k;
    SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
    for (i=0;i<W;i++) { for (k=0;k<H;k++) { if (quads[i][k]==1) Draw_FillRect(screen,i*QU,k*QU,QU,QU,SDL_MapRGB(screen->format,0,0,255)); } }
        SDL_Flip(screen);
}

int main() {
    Uint8 *check; SDL_TimerID timer; SDL_Event event; int quit=0;
    srand(time(NULL));
    if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) == -1) {printf("Can't init SDL:  %s\n", SDL_GetError());exit(1);}
    atexit(SDL_Quit); 
    screen = SDL_SetVideoMode(W*QU, H*QU, 16,SDL_SWSURFACE | SDL_DOUBLEBUF );
    if (screen == NULL) {printf("Can't set video mode: %s\n", SDL_GetError());exit(1);}
    init();
    timer = SDL_AddTimer (0, update, NULL);
    while (!quit) {
        SDL_PollEvent(&event);
        check=SDL_GetKeyState(NULL);
        if (check [SDLK_ESCAPE]) quit=1;
        draw();
    }
    return 0;
}
 
Zuletzt bearbeitet:
Das Einlesen aus einer Text-Datei macht für mich keinen Sinn
Wenn ich das richtig sehe, setzt Du die Zellen am Anfang zufällig auf dem Feld. Damit lassen sich aber keine "Experimente" durchführen, z.B wie sich ein bestimmtes Zellmuster "entwickelt" :)
Und Dir entgeht auch die sehr wichtige Erkenntniss, dass das "Indi" Muster sich zu einer großen Gemeinschaft entwickelt, sich stabilisiert und "Glider" bildet :D
 
Stimmt, es muss sehr faszinierend sein, zu beobachten wie sich "Indi" weiterentwickelt. ^^ :D

Aber wie gesagt, ich werde noch eine Zeichnen-Funktion einbauen, damit ich mit dem Mauszeiger auf dem Arbeitsblatt zeichnen kann. Deswegen meinte ich, dass das Einlesen aus einer Datei für mich aktuell keinen Sinn macht.
 
Habe Conway's Game of Life vor einiger Zeit mal geschrieben. Habe allerdings keine variable Feldgröße und die Startbelegung der Zellen ist bei mir im Quelltext festgelegt, werde mal gucken das ich diese Sachen noch mache.
Habe aber als Spielefläche die Form eines Torus genommen, so kommen sich bewegende Gebilde wieder ins Spielfeld gelaufen.

Code:
#include <stdio.h>
#include<stdlib.h>


int zeile = 15; 
int spalte = 30;
int zustand[15][30];
int tmp[15][30];


void initialisieren(){
    for ( int i = 0; i < zeile; i++){
        for (int j = 0; j < spalte ;j++){
            zustand[i][j] = 0;
        }
    }
    zustand[0][0] = 1;
    zustand[0][1] = 1;
    zustand[0][29] = 1;
    zustand[1][0] = 1;
    zustand[4][11] = 1;
    zustand[5][10] = 1;
    zustand[5][11] = 1;
    zustand[5][12] = 1;
    zustand[6][11] = 1;
    zustand[14][0] = 1;
    for ( int i = 0; i < zeile; i++){
        for (int j = 0; j < spalte ;j++){
            tmp[i][j] = 0;
        }
    }
}

void neuegeneration(){
    for (int laufzeile = 0; laufzeile < zeile; laufzeile++){
        for ( int laufspalte = 0; laufspalte < spalte; laufspalte++){
            int zelllebend = 0;
            for ( int zaehllaufzeile = laufzeile - 1; zaehllaufzeile < (laufzeile + 2); zaehllaufzeile++){
                for ( int zaehllaufspalte = laufspalte - 1; zaehllaufspalte < (laufspalte + 2); zaehllaufspalte++){
                    zelllebend = zelllebend + zustand[(zaehllaufzeile + zeile) % zeile][(zaehllaufspalte + spalte) % spalte];
                }
            }
            if (zustand[laufzeile][laufspalte] == 0 && zelllebend ==3){
                tmp[laufzeile][laufspalte] = 1;
            }
            else{
                if (zustand[laufzeile][laufspalte] == 1 && (zelllebend ==3 || zelllebend ==4)){
                        tmp[laufzeile][laufspalte] = 1;
                }
                else{
                        tmp[laufzeile][laufspalte] = 0;
                }
            }

        }
    }
}

void genuebertrag(){
    for ( int i = 0; i < zeile; i++){
        for (int j = 0; j < spalte ;j++){
            zustand[i][j] = tmp[i][j];
        }
    }
}

void ausgabe(){
    for ( int i = 0; i < zeile; i++){
        for (int j = 0; j < spalte ;j++){
            printf("%d", zustand[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int main(){
    system("cls");  
    initialisieren();
    printf("Ausgangszustand:\n");
    ausgabe();
    for ( int i = 0; true; i++){
        printf("%d.Iteration:\n", i+1);
        neuegeneration();
        genuebertrag();
        ausgabe();
        system("pause");
        system("cls");
    }
}
 
Hier ist schon einmal mein erster Lösungsansatz in Java, ich werde den aber noch überarbeiten und das einlesen von Textdateien für die Startkonfiguration (bis jetzt geht es nur manuell durch Mausklicks auf die Zellen) & einen Stop-Button hinzufügen (bis jetzt muss man zum beenden das Fenster schliessen), auch die Torus Form der Welt muss noch rein... Aber zuerst muss ich meinen WM-Kater auskurieren...:rolleyes:
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class GameOfLifeHaBo extends JFrame
{//GameOfLife-Hauptklasse
    public GameOfLifeHaBo()
    {//GameOfLifeHaBo()
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTable tabelle=new JTable(new SimTabelle());
        final JButton start=new JButton("Simulation starten");
        add(start, BorderLayout.SOUTH);
        tabelle.setDefaultRenderer(Object.class, new SimCellRenderer());
        tabelle.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        tabelle.setRowHeight(10);
        TableColumnModel columnModel=tabelle.getColumnModel();
        for (int i=0; i<40; i++)
        {
            columnModel.getColumn(i).setPreferredWidth(10);
        }    
        tabelle.addMouseListener(new MouseAdapter()
        {//MouseListener für die Zellen
            public void mousePressed(MouseEvent mevt)
            {
                int reihe=tabelle.rowAtPoint(mevt.getPoint());
                int spalte=tabelle.columnAtPoint(mevt.getPoint());
                Object wert=tabelle.getValueAt(reihe, spalte);
                if((Boolean)wert==false)
                {
                    tabelle.setValueAt(true, reihe, spalte);
                }
                else
                {
                    tabelle.setValueAt(false, reihe, spalte);
                }
            }
        });//MouseListener für die Zellen
        JPanel panel=new JPanel();
        panel.add(tabelle);
        panel.setVisible(true);
        add(panel, BorderLayout.CENTER);
        start.addMouseListener(new MouseAdapter()
        {//MouseListener zum starten der Simulation
            public void mousePressed(MouseEvent mevt)
            {//mousePressed()
                int delay=250;
                ActionListener task=new ActionListener()
                {
                    public void actionPerformed(ActionEvent evt)
                    {
                        simulator();
                    }
                };
                new Timer(delay, task).start();
            }//mousePressed()
            private void simulator()
            {//simulator()
                boolean[][] bufferFeld=new boolean[40][40]; 
                //Feld kopieren
                for(int i=0; i<40; i++)
                {//for i
                    for(int j=0; j<40; j++)
                    {//for j
                        bufferFeld[i][j]=(Boolean)tabelle.getValueAt(i, j);
                    }//for j
                }//for i
                
                for(int i=1; i<39; i++)
                {//for i
                    for(int j=1; j<39; j++)
                    {//for j
                        //tote Zelle
                        if((Boolean)tabelle.getValueAt(i, j)==false)
                        {
                            if(nachbarnZaehlen(i, j)==3)
                            {
                                bufferFeld[i][j]=true;
                            }
                        }
                        //lebende Zelle
                        else
                        {
                            if(nachbarnZaehlen(i, j)<2||nachbarnZaehlen(i, j)>3)
                            {
                                bufferFeld[i][j]=false;
                            }
                        }
                    }//for j
                }//for i
                //Feld kopieren
                for(int i=0; i<40; i++)
                {
                    for(int j=0; j<40; j++)
                    {
                        Object wert=(Object)bufferFeld[i][j];
                        tabelle.setValueAt(wert, i, j);
                    }
                }
            }//simulator()
            private int nachbarnZaehlen(int reihe, int spalte)
            {//nachbarnZaehlen
                int n=0;
                for(int i=reihe-1; i<=reihe+1; i++)
                    for(int j=spalte-1; j<=spalte+1; j++)
                        if((i>=0) && (i<40) && 
                           (j>=0) && (j<40) && 
                           ((i!=reihe)||(j!=spalte)) && 
                           (Boolean)tabelle.getValueAt(i, j)
                          )n++;
                return n;
            }//nachbarnZaehlen
        });//MouseListener zum starten der Simulation
    }//GameOfLifeHaBo()
    private class SimCellRenderer extends JLabel implements TableCellRenderer
    {//SimCellRenderer - eigener TableCellRenderer
        private Color black=new Color(0, 0, 0);
        private Color white=new Color(255, 255, 255);
        
        public SimCellRenderer()
        {//SimCellRenderer()
            setOpaque(true);
        }//SimCellRenderer
        public Component getTableCellRendererComponent(JTable tabelle, Object wert, boolean isSelected, boolean hasFocus, int reihe, int spalte)
        {//getTableCellRendererComponent()
            Boolean zellRaum=(Boolean)wert;
            if(zellRaum.booleanValue())
            {
                setBackground(black);
            }
            else
            {
                setBackground(white);
            }
            return this;
        }//getTableCellRendererComponent
    }//SimCellRenderer - eigener TableCellRenderer
    private class SimTabelle extends AbstractTableModel
    {//SimTabelle - eigenes TableModel
        boolean[][] zellFeld=new boolean[40][40];        
        {
            for(int i=0; i<40; i++)
            {
                for(int j=0; j<40; j++)
                {
                    zellFeld[i][j]=new Boolean(false);
                }
            }
        }
        public int getColumnCount()
        {
            return zellFeld[0].length;
        }
        public int getRowCount()
        {
            return zellFeld.length;
        }
        public Object getValueAt(int reihe, int spalte)
        {
            return zellFeld[reihe][spalte];
        }
        public void setValueAt(Object wert, int reihe, int spalte)
        {
            zellFeld[reihe][spalte]=(Boolean)wert;
            fireTableDataChanged();
        }
    }//SimTabelle - eigenes TableModel
    public static void main(String[]args)
    {//main()
        GameOfLifeHaBo fenster=new GameOfLifeHaBo();
        Dimension frameSize=new Dimension(600, 460);
        Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
        int x=(screenSize.width-frameSize.width)/2;
        int y=(screenSize.height-frameSize.height)/2;
        fenster.setLocation(x, y);
        fenster.setSize(600, 460);
        fenster.setVisible(true);
    }//main()
}//GameOfLife-Hauptklasse
 
Zuletzt bearbeitet:
Wie versprochen habe ich den Code noch einmal überarbeitet und folgende Änderungen vorgenommen:

-der Anwendung wurde ein Pause-Button hinzugefügt, mit dem es jederzeit möglich ist die Simulation anzuhalten und z. B. Änderungen an der aktuellen Zellpopulation vorzunehmen

-die Methode nachbarnZaehlen() wurde so verändert, dass Zellen am Rand die Zellen am gegenüberliegenden Rand als Nachbarn haben (Torus-Form). So wird eine unendliche Welt simuliert & ich spare mir den Zoom...:wink:

Auf das einlesen von Textdateien habe ich vorerst doch verzichtet, da es mir wesentlich nutzerfreundlicher erscheint die Startpopulation mit der Maus einzustellen - vielleicht schreibe ich aber noch einmal einen Editor, der das Erstellen der Textdateien etwas komfortabler gestaltet...

Ansonsten bin ich mit dem Code recht zufrieden, obwohl man ihn natürlich noch optimieren könnte - z. B. eine eigene Klasse für den MouseListener erstellen, die alle MouseEvents behandelt oder es wäre sicher auch eleganter anstatt den einfachen Timer zu benutzen, die Animation in einen eigenen Thread auszulagern...

cdw:
Zusätzlich kann man sich einige Gedanken zu seinem verwendeten Algorithmus machen - insbesondere für sehr große Felder. Auf Wunsch kann ich ein 500x500 Feld freigeben, bei dem man nach X Runden eine vordefinierte Ausgabe erhält und die Laufzeit sich sehr deutlich je nach verwendetem Algorithmus unterscheidet.
Wird hiermit gewünscht...:)

Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class GameOfLifeHaBo extends JFrame
{//GameOfLife-Hauptklasse
    public GameOfLifeHaBo()
    {//GameOfLifeHaBo()
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTable tabelle=new JTable(new SimTabelle());
        final JButton start=new JButton("Simulation starten");
        final JButton stop=new JButton("Pause");
        add(start, BorderLayout.SOUTH);
        tabelle.setDefaultRenderer(Object.class, new SimCellRenderer());
        tabelle.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        tabelle.setRowHeight(10);
        TableColumnModel columnModel=tabelle.getColumnModel();
        for (int i=0; i<40; i++)
        {
            columnModel.getColumn(i).setPreferredWidth(10);
        }    
        tabelle.addMouseListener(new MouseAdapter()
        {//MouseListener für die Zellen
            public void mousePressed(MouseEvent mevt)
            {
                int reihe=tabelle.rowAtPoint(mevt.getPoint());
                int spalte=tabelle.columnAtPoint(mevt.getPoint());
                Object wert=tabelle.getValueAt(reihe, spalte);
                if((Boolean)wert==false)
                {
                    tabelle.setValueAt(true, reihe, spalte);
                }
                else
                {
                    tabelle.setValueAt(false, reihe, spalte);
                }
            }
        });//MouseListener für die Zellen
        JPanel panel=new JPanel();
        panel.add(tabelle);
        panel.setVisible(true);
        add(panel, BorderLayout.CENTER);
        start.addMouseListener(new MouseAdapter()
        {//MouseListener zum starten der Simulation
            public void mousePressed(MouseEvent mevt)
            {//mousePressed()
                int delay=250;
                
                start.setVisible(false);
                add(stop, BorderLayout.SOUTH);
                ActionListener task=new ActionListener()
                {//ActionListener task
                    public void actionPerformed(ActionEvent evt)
                    {//actionPerformed()
                        simulator();
                        start.setVisible(false);
                        stop.setVisible(true);
                    }//actionPerformed()
                };//ActionListener task
                final Timer timer=new Timer(delay, task);
                timer.start();
                stop.addMouseListener(new MouseAdapter()
                {//MouseListener zum anhalten der Simulation
                    public void mousePressed(MouseEvent mevt)
                    {//mousePressed()
                        timer.stop();
                        stop.setVisible(false);
                        start.setVisible(true);
                    }//mousePressed()
                });//MouseListener zum anhalten der Simulation
            }//mousePressed()
            private void simulator()
            {//simulator()
                boolean[][] bufferFeld=new boolean[40][40]; 
                //Feld kopieren
                for(int i=0; i<40; i++)
                {//for i
                    for(int j=0; j<40; j++)
                    {//for j
                        bufferFeld[i][j]=(Boolean)tabelle.getValueAt(i, j);
                    }//for j
                }//for i
                
                for(int i=0; i<40; i++)
                {//for i
                    for(int j=0; j<40; j++)
                    {//for j
                        //tote Zelle
                        if((Boolean)tabelle.getValueAt(i, j)==false)
                        {
                            if(nachbarnZaehlen(i, j)==3)
                            {
                                bufferFeld[i][j]=true;
                            }
                        }
                        //lebende Zelle
                        else
                        {
                            if(nachbarnZaehlen(i, j)<2||nachbarnZaehlen(i, j)>3)
                            {
                                bufferFeld[i][j]=false;
                            }
                        }
                    }//for j
                }//for i
                //Feld kopieren
                for(int i=0; i<40; i++)
                {
                    for(int j=0; j<40; j++)
                    {
                        Object wert=(Object)bufferFeld[i][j];
                        tabelle.setValueAt(wert, i, j);
                    }
                }
            }//simulator()
            private int nachbarnZaehlen(int reihe, int spalte)
            {//nachbarnZaehlen
                int n=0;
                
                for(int i=-1; i<=1; i++)
                {
                    for(int j=-1; j<=1; j++)
                    {
                            int reihenIndex=i+reihe;
                            int spaltenIndex=j+spalte;
                            if(reihenIndex==-1){reihenIndex=39;}
                            if(reihenIndex==40){reihenIndex=0;}
                            if(spaltenIndex==-1){spaltenIndex=39;}
                            if(spaltenIndex==40){spaltenIndex=0;}
                            if((i!=0)||(j!=0))
                            if((Boolean)tabelle.getValueAt(reihenIndex, spaltenIndex)==true)
                            {
                                n++;
                            }
            
                    }
                }
                return n;
            }//nachbarnZaehlen
        });//MouseListener zum starten der Simulation
    }//GameOfLifeHaBo()
    private class SimCellRenderer extends JLabel implements TableCellRenderer
    {//SimCellRenderer - eigener TableCellRenderer
        private Color black=new Color(0, 0, 0);
        private Color white=new Color(255, 255, 255);
        
        public SimCellRenderer()
        {//SimCellRenderer()
            setOpaque(true);
        }//SimCellRenderer
        public Component getTableCellRendererComponent(JTable tabelle, Object wert, boolean isSelected, boolean hasFocus, int reihe, int spalte)
        {//getTableCellRendererComponent()
            Boolean zellRaum=(Boolean)wert;
            if(zellRaum.booleanValue())
            {
                setBackground(black);
            }
            else
            {
                setBackground(white);
            }
            return this;
        }//getTableCellRendererComponent
    }//SimCellRenderer - eigener TableCellRenderer
    private class SimTabelle extends AbstractTableModel
    {//SimTabelle - eigenes TableModel
        boolean[][] zellFeld=new boolean[40][40];        
        {
            for(int i=0; i<40; i++)
            {
                for(int j=0; j<40; j++)
                {
                    zellFeld[i][j]=new Boolean(false);
                }
            }
        }
        public int getColumnCount()
        {
            return zellFeld[0].length;
        }
        public int getRowCount()
        {
            return zellFeld.length;
        }
        public Object getValueAt(int reihe, int spalte)
        {
            return zellFeld[reihe][spalte];
        }
        public void setValueAt(Object wert, int reihe, int spalte)
        {
            zellFeld[reihe][spalte]=(Boolean)wert;
            fireTableDataChanged();
        }
    }//SimTabelle - eigenes TableModel
    public static void main(String[]args)
    {//main()
        GameOfLifeHaBo fenster=new GameOfLifeHaBo();
        Dimension frameSize=new Dimension(600, 460);
        Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
        int x=(screenSize.width-frameSize.width)/2;
        int y=(screenSize.height-frameSize.height)/2;
        fenster.setLocation(x, y);
        fenster.setSize(600, 460);
        fenster.setTitle("Game of Life for HaBo");
        fenster.setVisible(true);
    }//main()
}//GameOfLife-Hauptklasse
 
Zuletzt bearbeitet:
Wird hiermit gewünscht...:)
Startzustand:
Code:
 XX
XX
 X
bzw in Koordinaten:
Code:
 (0,-1), (1,-1),(-1,0), (0,0), (0,1)

Output: siehe Anhang - einmal nach 1103 Schritten (ca. 500x500) und einmal nach 2000 Schritten (ca. 1000x1000).
Als grober Orientierungswert: dauert bei mir auf dem Laptop (1.6 GHZ Core2Duo, "endless field" Umsetzung, SingleThread, alle Schritte ohne Animation) jeweils ~3 und ~5 Sekunden (innerhalb einer Python 2.6.5 Testsuit :)).

PS: bei den Outputs könnte es sich am Anfang und am Ende jeweils um eine Leerzeile handeln. Sonst ist der Output auf "minimale" Ausgabengröße zugeschnitten - d.h so groß, wie die "Randzellen" jeweils links/rechts/oben/unten verstreut sind.
 
Hallo,

ich habe das einfache Schema mit den 4 Regeln mal in Ruby programmiert .. jedoch ist mir der Verlauf noch nicht ganz klar ... sei gegeben:

_XXX
_X_X
____

so meine Schleifen laufen nun durchs Array ... das erste X (oben links) hat 2 lebende Nachbarn, also passiert nichts ... nächstes X (darunter) das selbe ... nächstes X wäre das mittlere oben ... dieses X hat 4 lebende Nachbarn, würde also sterben.

So jetzt meine Frage ... setze ich den neuen Zustand mitten im Durchlauf oder speichere ich den Zustand und ändere ihn erst, nachdem die Schleife komplett durchgelaufen ist?
 
So jetzt meine Frage ... setze ich den neuen Zustand mitten im Durchlauf oder speichere ich den Zustand und ändere ihn erst, nachdem die Schleife komplett durchgelaufen ist?
Das zweite. Alle Änderungen werden also nach dem Durchlauf vorgenommen (da man sonst auch total unterschiedliche Ergebnisse/Felder hätte, je nach dem, in welcher Reihenfolge man die Zellen durchläuft)
Sollte dann so aussehen:
Code:
>>> print lifestring(step)
 X
X X
X X
 
Alles klar, dann sollte das jetzt wohl passen:

Code:
class GameOfLife
  include Enumerable
  def initialize(size)
    @size = size
    @feld = Array.new(@size){Array.new(@size,false)}

    # Startpopulation
    @feld[1][2] = true
    @feld[1][3] = true
    @feld[1][4] = true
    @feld[2][2] = true
    @feld[2][4] = true
  end

  def each(&block)
    @feld.each(&block)
  end

  def to_s
    self.inject(string=""){|string,senkrecht|
      senkrecht.each{|waagerecht| (waagerecht)?(string+="X "):(string+="_ ")
      }
      string+="\n"
    }
  end

  def step()
    buffer_array = []
    for x in (0..(@size-1))
      for y in (0..(@size-1))
        counter = 0
        
        counter += 1 if @feld[y-1][x-1] if (x-1 >= 0 && y-1 >= 0)
        counter += 1 if @feld[y-1][x] if (y-1 >= 0)
        counter += 1 if @feld[y-1][x+1] if (x+1 < @size && y-1 >= 0)
        counter += 1 if @feld[y][x-1] if (x-1 >= 0)
        counter += 1 if @feld[y][x+1] if (x+1 < @size)
        counter += 1 if @feld[y+1][x-1] if (x-1 >= 0 && y+1 < @size)
        counter += 1 if @feld[y+1][x] if (y+1 < @size)
        counter += 1 if @feld[y+1][x+1] if (x+1 < @size && y+1 < @size)

        # => Eine tote Zelle mit genau drei lebenden Nachbarn wird in der Folgegeneration neu geboren.
        if ((counter == 3) && (@feld[y][x]==false))
          buffer_array << [y,x,true]
        end

        # => Lebende Zellen mit weniger als zwei lebenden Nachbarn sterben in der Folgegeneration an Einsamkeit.
        if((counter < 2) && (@feld[y][x]==true))
          buffer_array << [y,x,false]
        end

        # => Eine lebende Zelle mit zwei oder drei lebenden Nachbarn bleibt in der Folgegeneration lebend.
        if(((counter == 2) || (counter ==3)) && @feld[y][x]==true)
          buffer_array << [y,x,true]
        end

        # => Lebende Zellen mit mehr als drei lebenden Nachbarn sterben in der Folgegeneration an Überbevölkerung.
        if ((counter > 3) && (@feld[y][x]==true))
          buffer_array << [y,x,false]
        end
      end
    end

    buffer_array.each{|elem_state| @feld[elem_state[0]][elem_state[1]] = elem_state[2]}

  end
end

game = GameOfLife.new(8)
5.times do
  puts game
  game.step()
  puts
end

_ _ _ _ _ _ _ _
_ _ X X X _ _ _
_ _ X _ X _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _

_ _ _ X _ _ _ _
_ _ X _ X _ _ _
_ _ X _ X _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _

_ _ _ X _ _ _ _
_ _ X _ X _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _

_ _ _ X _ _ _ _
_ _ _ X _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _

etwas blöd mit Ruby, weil man die Console nicht löschen kann, wodurch man auch keine Animation hinbekommt
 
Zuletzt bearbeitet:
Einfach permanent ausgeben und den User das Terminal auf Feldgröße zurechtstutzen lassen. Wenn das Terminal keine abgefahrene Ausgabeoptimierung hat, sollte das einer Animation ähnlich dahinflimmern ;)
 
Hey ho,

hier eine einfach Java-Konsolen-Lösung mit quasi-unendlichem Spielfeld. Als Ausganspunkt ist momentan das "Indi" vorprogrammiert.

Code:
import java.util.*;

public class GameOfLife {
	
		private boolean field[][];
		
		public GameOfLife() {
			
		}
		
		public GameOfLife(int size) {
			this.field = new boolean[size][size];
			initField();
			// I
			field[1][1] = true;
			field[2][1] = true;
			field[3][1] = true;
			field[4][1] = true;
			field[5][1] = true;
			field[3][2] = true;
			field[3][3] = true;
			field[3][4] = true;
			field[3][5] = true;
			field[2][5] = true;
			field[1][5] = true;
			field[4][5] = true;
			field[5][5] = true;
			// n
			field[7][2] = true;
			field[7][3] = true;
			field[7][4] = true;
			field[7][5] = true;
			field[8][2] = true;
			field[9][2] = true;
			field[10][3] = true;
			field[10][4] = true;
			field[10][5] = true;
			// d
			field[12][3] = true;
			field[12][4] = true;
			field[12][5] = true;
			field[15][3] = true;
			field[15][4] = true;
			field[15][5] = true;
			field[13][3] = true;
			field[14][3] = true;
			field[13][5] = true;
			field[14][5] = true;
			field[15][2] = true;
			field[15][1] = true;
			// i
			field[17][1] = true;
			field[17][3] = true;
			field[17][4] = true;
			field[17][5] = true;
			printField(0);
			try{
				Thread.sleep(1000);
			}catch(InterruptedException ie) {
				System.out.println("Error: " + ie);
			}
		}
		
		public static void main(String[] args) {
			GameOfLife life = new GameOfLife(35);
			life.startGame();
		}
		
		public void startGame() {
			int step = 0;
			while(true) {
				if(calcNextStep()){
					System.out.println("Final state reached!");
					break;
				}
				step++;
				printField(step);
				try{
					Thread.sleep(100);
				}catch(InterruptedException ie) {
					System.out.println("Error: " + ie);
				}

			}
		}

		private boolean calcNextStep() {
			LinkedList<Change> list = new LinkedList<Change>();
			for(int y = 0; y < field.length; y++) {
				for(int x = 0; x < field.length; x++) {
					// dead cells with exact 3 living neighbors come alive
					if(!field[x][y]) {
						if(getNeighbors(x,y) == 3) {
							list.add(new Change(x,y,true));
						}
					}
					// living cells with less than 2 living neighbors die
					if(field[x][y]) {
						if(getNeighbors(x,y) < 2) {
							list.add(new Change(x,y,false));
						}
					}
					// living cells with 2 or 3 living neighbors stay alive
					if(field[x][y]) {
						if(getNeighbors(x,y) == 2 || getNeighbors(x,y) == 3) {

						}
					}
					// living cells with more than 3 living neighbors die
					if(field[x][y]) {
						if(getNeighbors(x,y) > 3) {
							list.add(new Change(x,y,false));
						}
					}
				}
			}
			Change tmp;
			boolean endGame = true;
			while((tmp = list.poll()) != null) {
				endGame = false;
				field[tmp.getX()][tmp.getY()] = tmp.getVal();
			}
			return endGame;
		}

		private int getNeighbors(int x, int y) {
			int[] pos = new int[2];
			int neighbors = 0;
			for(int i = 1; i <= 8; i++) {
				pos = getDir(x,y,i,field.length);
				if(field[pos[0]][pos[1]]) {
					neighbors++;
				}
			}
			return neighbors;
		}

		private void initField() {
			for(int y = 0; y < field.length; y++) {
				for(int x = 0; x < field.length; x++) {
					field[x][y] = false;
				}
			}
		}

		private void printField(int step) {
			System.out.print("\033[2J");
			System.out.flush();
			String out = "Game of Life -- Step " + step + "\n";
			for(int i = 0; i <= field.length; i++) {
				out += " =";
			}
			out += "\n";
			for(int y = 0; y < field.length; y++) {
				for(int x = 0; x < field.length; x++) {
					out += " ";
					if(field[x][y]) {
						out += "X";
					} else {
						out += "-";
					}
				}
				out += "\n";
			}
			for(int i = 0; i <= field.length; i++) {
				out += " =";
			}
			out += "\n";
			System.out.println(out);
		}

		private int[] getDir(int x, int y, int dir, int length) {
			int coords[] = new int[2];
			coords[0] = 0;
			coords[1] = 0;
			switch(dir) {
				case 1: 
					coords[0] = x;
					coords[1] = y-1;
					if(coords[1] < 0) {
						coords[1] = length-1;
					}
					break;
				case 2:
					coords[0] = x+1;
					coords[1] = y-1;
					if(coords[0] > length-1) {
						coords[0] = 0;
					}
					if(coords[1] < 0) {
						coords[1] = length-1;
					}
					break;
				case 3:
					coords[0] = x+1;
					coords[1] = y;
					if(coords[0] > length-1) {
						coords[0] = 0;
					}
					break;
				case 4:
					coords[0] = x+1;
					coords[1] = y+1;
					if(coords[0] > length-1) {
						coords[0] = 0;
					}
					if(coords[1] > length-1) {
						coords[1] = 0;
					}
					break;
				case 5:
					coords[0] = x;
					coords[1] = y+1;
					if(coords[1] > length-1) {
						coords[1] = 0;
					}
					break;
				case 6:
					coords[0] = x-1;
					coords[1] = y+1;
					if(coords[0] < 0) {
						coords[0] = length-1;
					}
					if(coords[1] > length-1) {
						coords[1] = 0;
					}
					break;
				case 7:
					coords[0] = x-1;
					coords[1] = y;
					if(coords[0] < 0) {
						coords[0] = length-1;
					}
					break;
				case 8:
					coords[0] = x-1;
					coords[1] = y-1;
					if(coords[0] < 0) {
						coords[0] = length-1;
					}
					if(coords[1] < 0) {
						coords[1] = length-1;
					}
					break;
				default:
			}

			return coords;
		}
	
	
	public class Change {
		private int x;
		private int y;
		private boolean value;

		public Change() {

		}

		public Change(int valX, int valY, boolean val) {
			this.x = valX;
			this.y = valY;
			this.value = val;
		}

		public void setVal(boolean val) {
			this.value = val;
		}

		public boolean getVal() {
			return this.value;
		}

		public void setX(int val) {
			this.x = val;
		}

		public int getX() {
			return this.x;
		}

		public void setY(int val) {
			this.y = val;
		}

		public int getY() {
			return this.y;
		}
	}
}

Gruß,
cByte
 
Hallo,

das ist ja mal wirklich ne super Idee für ne Programmieraufgabe :)

Hab da mal versucht nen anderen Ansatz zu wählen, indem ich alle aktiven Zellen
in einer Liste verwalte und entsprechend immer nur die aktiven Zellen und deren Nachbarn
abklappere. Leider wird das ab einer gewissen Anzahl von Zellen aber zu langsam, so dass ich im Moment auch schon wieder an anderen Lösungen bastel.

Dafür hab ich aber immerhin ne einfach Zoom Funktion reingebastelt... :D

Beim Start kann man einfach die Zellen per Maus setzen und dann das Spiel mit der Leertaste starten/stoppen

Ach ja, Code in Python + Pygame (und mit Sicherheit verbesserungsbedürftig ;))

Code:
#!/usr/bin/python

#notwendigen Kram importieren

import pygame
from sys import exit

#einige Variablen vordefinieren
#die seltsamen Werte bei width & height liegen daran dass das für mein Netbook
#die optimale Auflösung ist ;-)
width=800
height=400
cellColor = [0,0,255]
bgcolor = [255,255,255]
#Starte mit einem Zoom Faktor (entspricht Breite und Höhe einer Zelle in Pixel) von 10
zoomFactor = 10
cycle = 0
#Das Spiel startet erst nach Drücken der Leertaste!
running = False
#die Liste, welche später zur Verwaltung der aktiven Zellen genutzt wird
cellList = []


def initGame(width=800, height=400):
    size = width, height
    global screen
    global cellList
    screen = pygame.display.set_mode(size)
    screen.convert()

def toggleCell(pos):
    global cellList
    if checkField(pos):
        cellList.remove(pos)
    else:
        cellList.append(pos)

def checkField(pos):
    try:
        cellList.index(pos)
    except ValueError:
        return 0
    return 1     

def getNeighbors(pos):
    posx, posy = pos
    pattern = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]]
    pattern = [[(x+posx),(y+posy)] for x,y in pattern]
    return pattern

def checkNeighbors(pos):
    neighborhood = getNeighbors(pos)
    tmp = neighborhood[:]
    counter = 0
    for npos in tmp:
        if checkField(npos):
            counter = counter + 1
            neighborhood.remove(npos)
    return counter, neighborhood

def checkNeighborsEmpty(pos):
    neighborhood = getNeighbors(pos)
    counter = 0
    for npos in neighborhood:
        counter = counter + checkField(npos)
    return counter

def checkRules():
    global cycle
    cycle=cycle+1
    global cellList
    print len(cellList)
    tmpCellList = cellList[:]

    for cell in cellList:
        neighbors, tmpEmpty = checkNeighbors(cell)
        if (neighbors < 2 or neighbors > 3):
            tmpCellList.remove(cell)
        for Emptycell in tmpEmpty:
            try:
                tmpCellList.index(Emptycell)
            except ValueError:
                if (checkNeighborsEmpty(Emptycell) == 3): tmpCellList.append(Emptycell)
    cellList = tmpCellList

def zoomOut():
    global zoomFactor
    zoomFactor = zoomFactor -1
    if(zoomFactor < 1):
        zoomFactor = 1
    

def drawCell(pos,color = cellColor):
    global screen
    x,y = pos
    if (x < 0 or y < 0):
        return

    if ((x*zoomFactor >= (screen.get_width()-zoomFactor)) or (y*zoomFactor >= (screen.get_height()-zoomFactor))):
        zoomOut()
    x = x*zoomFactor
    y = y*zoomFactor
    cell_rect = pygame.Rect(([x,y]),([zoomFactor,zoomFactor]))
    screen.fill(color,cell_rect)


def drawAllCells():
    for pos in cellList:
        drawCell(pos)

def redrawScreen():
    screen.fill(bgcolor)
    drawAllCells()
    pygame.display.flip()

def gameLoop():
    while 1:
        redrawScreen()
        for event in pygame.event.get():
            if (event.type == pygame.QUIT):
                print "Quit in Cycle: ", cycle
                sys.exit()
            if (event.type == pygame.KEYDOWN):
                if(event.key==32):
                    global running
                    if(running == False): running = True
                    else: running = False
            if (event.type == pygame.MOUSEBUTTONDOWN):
                x,y = pygame.mouse.get_pos()
                x = x/zoomFactor
                y = y/zoomFactor
                toggleCell([x,y])

        if (running):
            checkRules()

initGame()

gameLoop()
Gruß BadAgent
 
Genial! Sehr interessantes Spiel Hab mal eine Javascript+HTML Lösung gebastelt:

Klick = Zelle setzen
Doppelklick = Zelle entfernen
 
habe meine Version mal überarbeitet und SDL mit reingepackt ... aber der Aufwand SDL zu installieren ist 10x größer als der Nutzen :eek:
Code:
# Autor: Christian Hoff
require "sdl"

class GameOfLife
  include Enumerable

  def initialize(size)
    @size = size
    @feld = Array.new(@size){Array.new(@size,false)}

    # Startpopulation
    @feld[6][9] = true
    @feld[7][7] = true
    @feld[7][8] = true
    @feld[7][9] = true
    @feld[7][10] = true
    @feld[7][11] = true
    @feld[8][6] = true
    @feld[8][7] = true
    @feld[8][9] = true
    @feld[8][11] = true
    @feld[8][12] = true
    @feld[9][7] = true
    @feld[9][9] = true
    @feld[9][11] = true
    @feld[10][9] = true

    # Zusatz
    @screen = nil
    init_sdl()
  end

  def init_sdl()
    SDL.init(SDL::INIT_VIDEO)
    @screen = SDL::setVideoMode(800, 600, 16,SDL::SWSURFACE)
  end

  def each(&block)
    @feld.each(&block)
  end

  def to_s
    self.inject(string=""){|string,senkrecht|
      senkrecht.each{|waagerecht| (waagerecht)?(string+="O "):(string+="  ")
      }
      string+="\n"
    }
  end

  def step()
    buffer_array = []
    for x in (0..(@size-1))
      for y in (0..(@size-1))
        counter = 0
        
        counter += 1 if @feld[y-1][x-1] if (x-1 >= 0 && y-1 >= 0)
        counter += 1 if @feld[y-1][x] if (y-1 >= 0)
        counter += 1 if @feld[y-1][x+1] if (x+1 < @size && y-1 >= 0)
        counter += 1 if @feld[y][x-1] if (x-1 >= 0)
        counter += 1 if @feld[y][x+1] if (x+1 < @size)
        counter += 1 if @feld[y+1][x-1] if (x-1 >= 0 && y+1 < @size)
        counter += 1 if @feld[y+1][x] if (y+1 < @size)
        counter += 1 if @feld[y+1][x+1] if (x+1 < @size && y+1 < @size)

        # => Eine tote Zelle mit genau drei lebenden Nachbarn wird in der Folgegeneration neu geboren.
        if ((counter == 3) && (@feld[y][x]==false))
          buffer_array << [y,x,true]
        end

        # => Lebende Zellen mit weniger als zwei lebenden Nachbarn sterben in der Folgegeneration an Einsamkeit.
        if((counter < 2) && (@feld[y][x]==true))
          buffer_array << [y,x,false]
        end

        # => Eine lebende Zelle mit zwei oder drei lebenden Nachbarn bleibt in der Folgegeneration lebend.
        if(((counter == 2) || (counter ==3)) && @feld[y][x]==true)
          buffer_array << [y,x,true]
        end

        # => Lebende Zellen mit mehr als drei lebenden Nachbarn sterben in der Folgegeneration an Überbevölkerung.
        if ((counter > 3) && (@feld[y][x]==true))
          buffer_array << [y,x,false]
        end
      end
    end

    buffer_array.each{|elem_state| @feld[elem_state[0]][elem_state[1]] = elem_state[2]}

  end

  def run()
    running = true
    rmask = 0xff000000
    gmask = 0x00ff0000
    bmask = 0x0000ff00
    amask = 0x000000ff
    surface = SDL::Surface.new(SDL::HWSURFACE, 800, 600, 16, rmask, gmask, bmask, amask)

    while (running)
      while(event = SDL::Event.poll)
        case event
          when SDL::Event::Quit
            running = false;
        end
      end

      for x in (0..(@size-1))
        for y in (0..(@size-1))
          surface.draw_rect(x*10,y*10,10,10, [255,255,255,255], true) if (@feld[y][x])
        end
      end

      @screen.fillRect(0, 0, 800, 600, 0)
      SDL::Surface.blit(surface,0,0,800,600,@screen,0,0)
      surface.fillRect(0, 0, 800, 600, 0)
      @screen.flip()
      self.step()
      sleep(0.1)
    end
  end

end

game = GameOfLife.new(50)
game.run
 
Hallo,

hier kommt meine Lösung für das Lebensspiel :)

ich habe die Grafikschnittstelle allegro für die grafische ausgabe verwendet.

Code:
//---Lebens-Simulations PROGRAMM---
/**********************************

wenn allegro verwendet wird muss zusätzlich zu "g++ DATEINAME.CPP"
noch " `allegro-config --cflags` `allegro-config --libs` angegeben werden

die Zeile im terminal sieht dan so aus:
" g++ main.cpp `allegro-config --cflags` `allegro-config --libs` "

ein dynamischer zellhaufen der in einer welt von 800 mal 600 pixel vor sich hin
vegetiert.

Die Zellen werden für die Ausgangssituation zufällig auf einem feld von 400 * 300
Pixel verteilt, welches sich in der mitte der "welt" befindet.

**********************************/

#include <allegro.h>    //include-datei für die allegrofunktionen

short cell[800][600];
short temp[800][600];
short x, y, m, a, b, cnt;
long int zykl;

int main()
{
        allegro_init();         //initialisiert allegro
        install_keyboard();     //teilt mit dass die tastatur verwendet wird
        set_color_depth(16);    //stellt die farbtiefe ein -> hier auf 16bit
        set_gfx_mode( GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);          //stellt die bildschirmauflösung auf 800x600 pixel
    set_window_title("Digital Life");
    show_os_cursor(MOUSE_CURSOR_ARROW);

    BITMAP *welt;
    welt = create_bitmap(800, 600);


reset:;

    //Initialisierung der Zellen
    for(int i=0; i < 800; i++)
    {
        for(int j=0; j < 600; j++) cell[i][j] = 0;
    }

    //Verteilung der Lebenden Zellen
    srand( time(NULL) );
    m = 1000 * (rand()%100 + 1);
    a = 0;
    for(int i = 0; i < m; i++)
    {
        x = rand()%400 + 200;
        y = rand()%300 + 150;
        if(cell[x][y]==0) a++;    //Zählt wieviel Zellen verteilt werden
        cell[x][y] = 1;
    }
    b = a;
    zykl = 0;

        while(!key[KEY_ESC])
    {
        while( key[KEY_SPACE] );    //Pause solange Leertaste gedrückt
        if( key[KEY_R] ) goto reset;    //Neustart wenn r gedrückt

        clear_to_color( welt, makecol(173,230,216) );    //Hintergrundfarbe

        textprintf_ex( welt, font, 5, 15, makecol(255,0,0), -1, "Digital Life - Lebenssimulator (C) 2011 Lukas");
        textprintf_ex( welt, font, 5, 35, makecol(255,0,0), -1, "Zellen zu Beginn: %d Zellen momentan: %d", a, b );
        textprintf_ex( welt, font, 5, 45, makecol(255,0,0), -1, "Bisher berechnete Zyklen: %ld", zykl );
        textprintf_ex( welt, font, 5, 55, makecol(255,0,0), -1, "Unterbrechen: LEERTASTE,   Neustart: R,   Beenden: ESC");

        b = 0;        //Zähler für aktuelle Zellenanzahl zurücksetzen
        zykl++;        //Zykluszähler erhöhen

        //Regeln für fortbestand/tod/entstehung der zellen
        for(int i = 1; i < 799; i++)
        {
            for(int j = 1; j < 599; j++)
            {
                cnt = 0;
                if( cell[i-1][j-1] == 1 ) cnt++;
                if( cell[i-1][j] == 1 ) cnt++;
                if( cell[i-1][j+1] == 1 ) cnt++;
                if( cell[i][j-1] == 1 ) cnt++;
                if( cell[i][j+1] == 1 ) cnt++;
                if( cell[i+1][j-1] == 1 ) cnt++;
                if( cell[i+1][j] == 1 ) cnt++;
                if( cell[i+1][j+1] == 1 ) cnt++;

                if( cnt < 2 ) temp[i][j] = 0;
                if( (cnt == 2)&&(cell[i][j] > 0) ) temp[i][j] = 1;
                if( cnt == 3 ) temp[i][j] = 1;
                if( cnt > 3 ) temp[i][j] = 0;
            }
        }

        //übergabe der neuen zellpositionen
        for(int i = 0; i < 800; i++)
        {
            for(int j = 0; j < 600; j++) cell[i][j] = temp[i][j];
        }

        //ausgabe der zellpositionen
        for(int i = 0; i < 800; i++)
        {
            for(int j = 0; j < 600; j++)
            {
                switch( cell[i][j] )
                {
                    case 0: {break;}
                    case 1: {putpixel( welt, i, j, makecol(85,107,47) ); b++; break;}
                    default: {textprintf_ex( screen, font, 30, 200, makecol(255,0,0), makecol(0,0,255), "ERROR");
                          while( !key[KEY_ESC] ); break;}
                }
            }
        }
        draw_sprite(screen, welt, 0, 0);    //ausgabe der "welt" an den Bildschirm
    }

    destroy_bitmap(welt);    //Die "welt" wieder freigeben

        return 0;
}
END_OF_MAIN();          //schliesst die allegro anwendung wieder

ich habe es mit g++ unter linux compiliert,....
sollte aber genau so auch überall anders wo allegro installiert ist compilierbar sein.

lg lukas,

BTW: hallo an euch alle!! (erster post)
:)
 
Zuletzt bearbeitet von einem Moderator:
hier meine implementation in 5 Zeilen C-code:
Code:
# define B f[a]
char  f[2][26][82],i,j,a=0,c[]="_o",n;main(){B[3][3]=B[3][2]=B[3][1]=B[2][3]=B[1][2]=1;for
(;;){system("clear");for(i=1;i< 25;i++){for(j=1; j<81;j++){printf("%c",c[f[!a][i][j]]);n=B
[i-1][j-1]+B[i-1][j]+B[i-1][j+1]+B[i][j-1]+B[i][j+1]+B[i+1][j-1]+B[i+1][j]+B[i+1][j+1];f[!
a][i][j]=(!B[i][j]&&n==3) ||(B[i][j]&&n>1&&n<4);}puts("");}sleep(1);a=!a;}}

Hab jetzt endlich ne Sig :D
 
Zurück
Oben