Conways game of life als Endlosschleife



  • Moin moin,

    ich programmiere momentan das gol und wollte es als endlosschleife programmieren, dass wenn eine Figur die rechts seite erreicht hat, links weiter geht bzw. wenn sie unten angekommen ist, oben weiter läuft.

    meine vorgehensweise ist, dass ich ein array für das spielfeld definiert habe und alle 8 felder um eine zelle herum abfrage.
    dummerweise gelingt es mir nicht, dass wenn eine zelle z.b. am rechten rand ist, am linken rand abzufragen, ob am rechten rand zellen vorhanden sind.

    ich verstehe nicht, wie ich dem linken rand nun eine zelle "zum leben erwecken" und eben dann ein wert in mein array des spielfeldes schreiben kann... irgendwie fehlt mir da ein ansatz.

    hat da jemand einen lösungsansatz für mich?

    MfG
    Craiten 🙂



  • modulo



  • hm, in wie fern könnte mir da mudolo helfen?
    bisher habe ich folgendes mal programmiert:

    +------+
    |      |
    |     0|
    |X    0|
    |     0|
    +------+
    

    dort wo das X steht wird abgefragt, ob es rechts Zellen (durch die Nullen markiert) gibt. wenn ja, soll er beim X eine neue Zelle entstehen lassen. dummerweise tut er das nicht. eine erklärung finde ich auch nicht.

    Meine Abfrage ist für diesen Fall diese hier:
    Wobei breite für die breite des Spielfelds steht und (j+m) die drei Zellen abfragt rechts.
    die variable nachbar zählt die nachbarn, welche um eine Zelle herum liegen.

    if(i == 0 && spielfeld[breite][j+m] == 1)
       nachbar++;
    

    den einsatz von modulo sehe ich da nun nicht wirklich 😕



  • Hast Du daran gedacht, dass bei einer Spielfeldbreite von breite die Spaltenindizes von 0 bis breite - 1 gehen?



  • craiten schrieb:

    den einsatz von modulo sehe ich da nun nicht wirklich 😕

    Deswegen fragst du hier auch nach.
    Wie groß sind denn j und m in deinem Beispiel?

    +------+
    |      | 0
    |     0| 1
    |X    0| 2
    |     0| 3
    +------+
     012345
    
    int breite = 6;
    int i;
    for (i = 2*breite; i>=0; --i)
      printf("%d -> %d\n", i, i % breite);
    

    Was kommt bei i = 6 raus?



  • Belli schrieb:

    Hast Du daran gedacht, dass bei einer Spielfeldbreite von breite die Spaltenindizes von 0 bis breite - 1 gehen?

    ja habe ich.

    DirkB schrieb:

    Wie groß sind denn j und m in deinem Beispiel?

    int breite = 6;
    int i;
    for (i = 2*breite; i>=0; --i)
      printf("%d -> %d\n", i, i % breite);
    

    Was kommt bei i = 6 raus?

    bei i =6 bekomme ich eine Null zurückgegeben, ist ja auch klar, ist ja auch kein rest da ;). wie es mir dabei helfen könnte eine topologie zu erzeugen, ist mir leider immernoch unklar. nen gedanklicher anstupser wäre ganz nett 🙂

    also meine funktion sieht wie folgt aus (bisher, aus test zwecken, nur mit der funktion, ob eine zelle am linken rand entstehen kann):

    int pruefe_auf_nachbarn(int spielfeld[breite][hoehe], int i, int j) {
         int m,n,nachbarn = 0;
         for(m = -1; m <= 1; m++) {
              for(n = -1; n <= 1; n++) {
                    if(spielfeld[i+n][j+m] == 1 && (i+n) >= 0 && (j+m) >= 0)
                         nachbarn++;
                    if(i == 0 && spielfeld[breite-1][j+m] == 1)
                         nachbarn++;          
              }
         }
         return nachbarn - spielfeld[i][j];
    
    }
    

    warum das programm aber mit dieser abfrage nicht funktioniert, verstehe ich nicht...

    if(i == 0 && spielfeld[breite-1][j+m] == 1)
                         nachbarn++;
    

    weil ich frage ja auf der rechten seite ab, ob dort 3 zellen anliegen.



  • craiten schrieb:

    bei i =6 bekomme ich eine Null zurückgegeben, ist ja auch klar, ist ja auch kein rest da ;). wie es mir dabei helfen könnte eine topologie zu erzeugen, ist mir leider immernoch unklar. nen gedanklicher anstupser wäre ganz nett

    Wenn du in Spalte 5 bist und dein j+m (oder i+n) 6 ergibt, dann willst du doch auf Spalte 0 zugreifen.
    Mit dem Modulo sparst du dir Sonderbehandlung der Randfelder.
    Du rechnest % breite bei jedem Arrayindex.

    ⚠

    int breite = 6;
    int i;
    for (i = 2*breite; i>=-breite; --i)
      printf("%d -> %d\n", i, i % breite);
    

    Bei negativen Zahlen kann es ein Problem geben.
    Das Ergebnis kann (muss aber nicht) negativ sein.



  • Um negative Werte zu vermeiden kann man sich ja kurz eine eigene Modulo-Funktion basteln:

    int modulo( int x, int m )
    {
    	while ( x < 0 )
    		x += m;
    
    	return x % m;
    }
    

    Vielleicht gibts dafuer noch eine elegantere Loesung aber so sollte es funktionieren.
    In deinem Fall braucht es wohl gar kein 'while', ein 'if' muesste genuegen.


  • Mod

    Ab C99 ist standardisiert, wie sich modulo des Vorzeichens wegen verhalten muss. Das Ergebnis hat dann garantiert das Vorzeichen des Dividenden. Oder genauer gesagt, es gilt:

    (a/b)*b + a%b == a
    

    Das heißt bei a = -1 und b = 6 ist a%b == -1. (Denn (a/b) == 0)

    Das ist natürlich genau das, was man hier nicht möchte, aber wenigstens kann man sich drauf verlassen 🙂 .

    Eine etwas umständlichere Rechnung für das gewünschte Ergebnis wäre daher

    (max_index + (index % max_index)) % max_index
    

    Könnte schneller sein als icarus2s Version, würde ich aber vorher testen, sind immerhin zwei (relativ) teure Divisionen drin.



  • SeppJ schrieb:

    Könnte schneller sein als icarus2s Version, würde ich aber vorher testen, sind immerhin zwei (relativ) teure Divisionen drin.

    Als ob die Berechnung was ausmachen würde.
    Ich sehs schon, alles bis ins letzte Bit optimiert und die Anzeige mit Setpixel 😉



  • SeppJ schrieb:

    würde ich aber vorher testen, sind immerhin zwei (relativ) teure Divisionen drin.

    Lebst Du noch in den Achtzigern?
    Wird Zeit solche Tipps/Aussagen mal einzumotten. Eine Division ist in 99,99999% der Fälle verdammt nochmal nicht "teuer", es ist einfach garnichts im Jahre 2012. Und falls es DOCH mal eine Rolle spielt, dann bestimmt nicht bei einem Anfänger der Game of Life programmiert.

    Sowas liest man hier viel zu oft. Mach den Leuten doch keine Angst mir so einem Käse


  • Mod

    Dann schau mal nach. Du wirst feststellen, eine Division ist viel langsamer (Faktor 10 gegenüber Multiplikation, noch viel mehr gegenüber Addition) als sonstige Grundrechenartenn. Im Endeffekt sind das natürlich trotzdem nur 20-40 Takte, deshalb habe ich auch absichtlich betont, dass der Unterschied relativ zu sehen ist. Bitte aufmerksamer lesen bevor man motzt.



  • So ich habe dann mal meinn code mit inspirationen eurerseits etwas aktualisier 🙂

    int pruefe_auf_nachbarn(int spielfeld[breite][hoehe], int i, int j) {
    
         int m,n,nachbarn = 0,x,y;
         for(m = -1; m <= 1; m++) {
              for(n = -1; n <= 1; n++) {
                 x = (i + n + breite) % breite; // neu
                 y = (j + m + hoehe) % hoehe;   // neu
                 if(spielfeld[x][y] == 1)
                   nachbarn++;           
              }
         }
         return nachbarn - spielfeld[i][j];
    
    }
    

    funktioniert auch alles einwandfrei 🙂
    oder hat da noch jemand etwas an zu merken? 🙂

    icarus, da gibts etwas einfacheres:

    icarus2 schrieb:

    int modulo( int x, int m )
    {
    	while ( x < 0 )
    		x += m;
    
    	return x % m;
    }
    

    =

    int modulo(int x, int m) {
       int w = x % m;
       if (w < 0) w += m;
       return w;
    }
    

    WORÜBER ihr euch nun streitet, würde ich doch gerne mehr hören!
    ich meine, wenn ich mal später etwas programmieren sollte, wo "etwas" zeit die laufzeit schon erheblich reduzieren könnte, würde ich das gerne wissen wollen 🙂



  • SeppJ schrieb:

    Dann schau mal nach. Du wirst feststellen, eine Division ist viel langsamer (Faktor 10 gegenüber Multiplikation, noch viel mehr gegenüber Addition) als sonstige Grundrechenartenn. Im Endeffekt sind das natürlich trotzdem nur 20-40 Takte, deshalb habe ich auch absichtlich betont, dass der Unterschied relativ zu sehen ist. Bitte aufmerksamer lesen bevor man motzt.

    Kann ich so zurück geben. Ich habe nicht bezweifelt, dass die Division langsamer ist als andere Grundrechenarten.


Anmelden zum Antworten