Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Denethtos

Frischling

  • »Denethtos« ist der Autor dieses Themas

Beiträge: 13

Beruf: Schüler

  • Private Nachricht senden

1

21.04.2013, 00:26

[C++ & SDL] GameOfLife - Simulierung geht schief.

Hallo,

Ich habe vor ca. einer Woche mit der Spieleprogrammierung angefangen.
Ich verwende C++ zusammen mit SDL und schreibe momentan einen Simulator für Conways Game of Life, dieser will aber leider (noch) nicht so richtig funktionieren.
Das kompilieren verläuft Fehlerfrei und das Programm läuft (bis auf die Simulation) fehlerfrei.
Der Debugger gibt auch keine Fehler an.

Ich vermute, dass mein Fehler irgendwo in der Berechnung des neuen Schrittes liegt, kann ihn aber nirgendwo finden.

Hier die Schleife, in der immer der nächste Schritt erstellt wird:

C-/C++-Quelltext

1
2
3
4
5
6
7
void Game::GameLoop() {
    if(OnSimulate == true) {
        SDL_Delay(250);
        GameOfLife.NextStep();  /// Aktuelle Situation wird gespeichert
        GameOfLife.CalculateNewState(); /// Neue Situation wird mithilfe der alten berechnet
    }
}


NextStep() :

C-/C++-Quelltext

1
2
3
4
5
6
7
void Field::NextStep() {
    for(int X = 0; X < 50; X++) {
        for(int Y = 0; Y < 50; Y++) {
            GameField[X][Y].LastState = GameField[X][Y].ActualState;
        }
    }
}


und CalculateNewState() :

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void Field::CalculateNewState() {
    for(int X = 0; X < 50; X++) {
        for(int Y = 0; Y < 50; Y++) {
            int NeighborAlive = 0;

            for(int i = 0; i < 8; i++) {
                if(GameField[X][Y].Neighbor[i]->LastState == ALIVE) {
                    NeighborAlive += 1;
                }
                else {
                    NeighborAlive = NeighborAlive;
                }
            }

            if(GameField[X][Y].LastState == DEAD) {
                if(NeighborAlive == 3) {
                    GameField[X][Y].ActualState = ALIVE;
                }
                else {
                    GameField[X][Y].ActualState = DEAD;
                }
            }
            else {
                if(NeighborAlive == 2 || NeighborAlive == 3) {
                    GameField[X][Y].ActualState = ALIVE;
                }
                else {
                    GameField[X][Y].ActualState = DEAD;
                }
            }
        }
    }
}


GameField[50][50] ist ein Array der Struktur Cell, welche den aktuellen Stand, den letzten Stand (ALIVE, DEAD) und Zeiger auf ihre Nachbarzellen enthält.

Wer sich den ganzen Quellcode ansehen möchte finden ihn hier finden: https://github.com/Denethtos/ConwaysGameOfLife

Ich bedanke mich schonmal vielmals für eure Hilfe und entschuldige mich, falls ich das falsche Unterforum erwischt habe :/

Mit freundlichen Grüßen Tobias.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Denethtos« (21.04.2013, 09:09)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

21.04.2013, 17:45

Wäre nett wenn du uns ein wenig zum Fehler schreiben würdest. Habe deinen hier geposteten Code überflogen und der scheint soweit richtig zu sein. Wird wohl an anderer Stelle liegen. Aber jetzt deinen Code zu durchforsten und mir alles selbst zusammen zu suchen halte ich für etwas aufwendig;) Schreib doch mal was genau bei der Simulation nicht klappt. Ansonsten ist hier möglicherweise der Moment gekommen, wo du dich mit dem Debugger beschäftigst. Damit kannst du dein Programm Schritt für Schritt durchlaufen und genau gucken wie welche Werte geändert werden. Damit fällt es einem normal recht schnell auf wo Probleme vorhanden sind.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Denethtos

Frischling

  • »Denethtos« ist der Autor dieses Themas

Beiträge: 13

Beruf: Schüler

  • Private Nachricht senden

3

21.04.2013, 18:33

Vielen Dank für die schnelle Antwort :)

Wie schon geschrieben, der Debugger sagt, dass alles ok ist.
Ich hab mir heute auch nochmal alles angesehen und glaube momentan eher das ich den Fehler an der falschen Stelle vermutet habe. :/

Ich hab den Code für die erstellung des nächsten Schrittes einmal Testweise geändert, wobei sich herausstellte das es anscheinend irgendwo bei der Initialisierung einen Fehler gibt. Denn obwohl am Anfang alle Zellen "tot" sind breitet sich alles von der oberen rechten Ecke aus.

Werde die Initialisierung nachher nochmal umschreiben und evtl. auch noch das erstellen des nächsten Schrittes bzw. das Speichern der Daten in der Struktur Cell.

Bisher sehen die betroffenen Stellen noch so aus:

Struktur Cell:

C-/C++-Quelltext

1
2
3
4
5
struct Cell {
    bool ActualState;
    bool LastState;
    Cell *Neighbor[8];
};


Initialisierung:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
    for(int X = 0; X < 50; X++) {
        for(int Y = 0; Y < 50; Y++) {
            for(int i = 0; i < 8; i++) {
                GameField[X][Y].Neighbor[i] = GetNeighbor(i, X, Y);
            }
        }
    }
    ResetActualState();
    ResetLastState();


C-/C++-Quelltext

1
GetNeighbor(int Pos_Neighbor, int Pos_X, int Pos_Y)


Die Funktion GetNeighbor gibt einen Pointer auf die Nachbarzellen wieder (von welcher bestimmt Pos_Neighbor).

Das werde ich mir heut Abend aber nochmal genau angucken. ^^

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Denethtos« (21.04.2013, 19:12)


Denethtos

Frischling

  • »Denethtos« ist der Autor dieses Themas

Beiträge: 13

Beruf: Schüler

  • Private Nachricht senden

4

21.04.2013, 18:36

Die Regeln werden jetzt richtig eingehalten, nachdem ich einen Fehler in GetNeighbor gefunden habe.
Das einzige was jetzt noch falsch läuft ist, dass am Rand Zellen Alive sind, welche nichtmals auf dem Bildschirm sind...^^
Den Fehler muss ich nachher noch finden.

EDIT:

Der Fehler ist gefunden.
In der Funktion GetNeighbor habe ich an einer Stelle versehentlich einen Wert falsch gesetzt, weswegen viele Zeiger entstanden sind, welche auf irgendwas gezeigt haben was nichts mit dem Programm zu tun hatte.
Komisch, dass sowas nicht vom Compiler oder Debugger entdeckt wird ^^

Aber trotzdem vielen Dank für die Unterstützung :D

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Denethtos« (21.04.2013, 22:17) aus folgendem Grund: Fehler gefunden.


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

22.04.2013, 19:08

Deinen Fehler hattest du uns aber trotzdem nicht genannt. Wie hätte dir da jemand helfen sollen? Du musst deinen Fehler genau umschreiben. Irgendetwas funktioniert nicht hilft uns nicht:) Und beim debuggen immer gucken dass du es richtig machst. Zum Beispiel kannst du eine kleine Welt nehmen mit 9 Zellen. Dann setzt du einen Breakpoint vor die Berechnung der neuen Welt. Einen weiteren setzt du danach. Jetzt kannst du dich zur Not auch annähern und gucken wie viele Nachbarn werden zum Beispiel gefunden. Wenn du merkst, dass da was falsch läuft, dann stepst du einfach mal in die Berechnung und suchst was da falsch läuft. Dann kommt man damit normal schnell zum Ziel.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Denethtos

Frischling

  • »Denethtos« ist der Autor dieses Themas

Beiträge: 13

Beruf: Schüler

  • Private Nachricht senden

6

22.04.2013, 19:39

Ok, nächste mal werde ich den Fehler besser eingrenzen.
Der Fehler an sich war, dass obwohl während der Initiierung alle Zellen als DEAD gespeichert wurden am Anfang der Simulation Leben vom Rand des Fensters kam. Sprich: Außerhalb des Feldes war Leben, welches auf das Feld kam.
Der andere Fehler, den ich gefunden habe, hat dafür gesorgt, dass die Zellen nach ganz anderen Regeln Leben, weil alle Zellen einen falschen linken Nachbar zugewiesen bekommen haben.

7

22.04.2013, 20:09

Ach ja, weil es mir schon beim ersten überfliegen des Quellcodes aufgefallen ist: Den Destruktor von Field kannst du komplett streichen.
"Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why." - Anon

Denethtos

Frischling

  • »Denethtos« ist der Autor dieses Themas

Beiträge: 13

Beruf: Schüler

  • Private Nachricht senden

8

23.04.2013, 00:31

Joa, dass hatte ich auch schon überlegt^^
Wollt den Code - jetzt wo er endlich funktioniert - sowieso noch einmal überarbeiten und an ein paar Stellen kürzen.

Werbeanzeige