Forum: Mikrocontroller und Digitale Elektronik Game of Life läuft nur eine Runde!


von J. T. (chaoskind)


Angehängte Dateien:

Lesenswert?

MoinMoin,

nachdem ich nun endlich mein STM32F746Disco soweit zum Laufen bekommen 
habe, dass ich auf dem LCD rummalen kann, habe ich angefangen ein Game 
of Life zu schreiben. Wahrscheinlich sehr von hinten durch die 
Hühneraugenbrust.

Unter anderem ist mir nicht eingefallen, wie ich mir die if-Abfrage für 
jedes Feld spare, ob es am Rand liegt oder nicht. Meine Spielwelt soll 
ein Torus sein, sprich was rechts aus dem Bild läuft kommt links wieder 
rein, und umgekehrt, selbiges gilt für oben und unten.

Die Felder müssen auf lebende Nachbarn überprüft werden, mitten im Feld 
kein Problem, einfach die Felder
( (Feldkoordinate+1X+1Y) (Feldkoordinate+1X+0Y) (Feldkoordinate+1X-1Y)
  (Feldkoordinate+0X+1Y)____________________(Feldkoordinate+0X-1Y)
  (Feldkoordinate-1X+1Y) (Feldkoordinate-1X+0Y) (Feldkoordinate-1X-1Y) )
abfragen.

Aber am Rand käme es dann ja zu Unterlaufen, und er würde auf Felder 
prüfen, die ausserhalb der Spielwelt und wer weiß wo/was im Speicher 
liegen. Das Spielfeld wird übrigens als uint8_t Spielfeld[][] 
initialisiert.

Also die Abfrageroutine für die Ecken gesondert behandelt, und die für 
die Ränder gesondert behandelt. Im Endeffekt die selbe Routine wie im 
Feld, nur mit teils festgelegten statt dynamischen Koordinaten.
Das sollte dann doch schneller laufen, als wenn ich in jedem Feld eine 
Randprüfung machen würde? Zumindest ab einer gewissen Spielfeldgröße?

Das ist aber nur ne kleine Nebenfrage....


Mein Hauptproblem ist folgendes, und es wäre super wenn da jemand nen 
Fehler findet, bzw mir sagen kann, was ich falsch mache:

Das Spiel läuft nach dem Initialisieren nur eine Runde, danach bleibt 
alles gleich. Soweit ich das beim Durchsteppen beobachten konnte, macht 
er soweit aber alles wie im ersten Durchlauf, wo sich ja etwas 
ändert....
Ich arbeite übrigens mit SW4STM32, falls dass irgendwie helfen sollte. 
Und der Controller ist wie erwähnt ein STM32F746 auf dem Discovery 
Board.

Also starten/init -->
Auf den Bildschirm malen, ich seh was (nennen wie es X) -->

Nachbarschaft prüfen, Ergbenisse in ein Schattenspielfeld speichern -->
Schattenspielfeld aufs Spielfeld übertragen und Schattenspielfeld wieder 
leeren -->

"Neues" Spielfeld auf Bildschirm malen, ich seh was anderes (nennen wir 
es  Y) -->

Nachbarschaft prüfen, Ergbenisse in ein Schattenspielfeld speichern -->

Schattenspielfeld aufs Spielfeld übertragen und Schattenspielfeld wieder 
leeren -->

"Neues" Spielfeld auf Bildschirm malen, ich seh das gleiche/selbe (Y)-->

Nachbarschaft prüfen, Ergbenisse in ein Schattenspielfeld speichern -->

Schattenspielfeld aufs Spielfeld übertragen und Schattenspielfeld wieder 
leeren -->

"Neues" Spielfeld auf Bildschirm malen, ich seh das gleiche/selbe (Y)-->
.
.
.


Ich starte das Programm. Das Spielfeld wird mit zufälligen 
Lebend/Tot-Zellen initialsiert:
1
void GameOfLife_Spielfeldinit_Random(uint8_t Wahrscheinlichkeit, uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y, uint8_t *SpielfeldPt, uint8_t *SpielfeldschattenPt)
2
{
3
  uint16_t X = 0;
4
  uint16_t Y = 0;
5
6
  while (Y < Spielfeldgroesse_y)
7
  {
8
    while (X < Spielfeldgroesse_x)
9
    {
10
      *( SpielfeldPt +((Y * Spielfeldgroesse_x) + (X)) ) = Zufall(Wahrscheinlichkeit)%2;
11
      *( SpielfeldschattenPt +((Y * Spielfeldgroesse_x) + (X)) ) = *( SpielfeldPt +((Y * Spielfeldgroesse_x) + (X)) );
12
13
      X++;
14
    }
15
    X = 0;
16
    Y++;
17
  }
18
}

Das Spielfeld wird gezeichnet. Ich hab erst auf einen Layer gezeichnet, 
während ich einen anderen gezeigt hab, damit es nicht so flackert beim 
malen. Ich dachte evtl klemmt es beim Layerumschalten, also den Teil 
auskommentiert. Keine Änderung:
1
void GameOfLife_Spielfeldzeichnen(uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y, uint8_t *SpielfeldPt)
2
{
3
  uint32_t X = 0;
4
  uint32_t Y = 0;
5
6
  uint8_t i = 0;
7
  uint8_t j = 0;
8
9
  uint8_t Textarray[] = "Conways Game of Life";
10
  uint8_t *TextPt = &Textarray[0];
11
12
13
  /*
14
  Layerswitch ^= 1;
15
16
  if(Layerswitch)
17
  {
18
    Layer1_schreiben__Layer2_zeigen();
19
  }
20
  else
21
    {
22
      Layer2_schreiben__Layer1_zeigen();
23
    }
24
25
  */
26
27
28
  while (Y < Spielfeldgroesse_y)
29
  {
30
    while (X < Spielfeldgroesse_x)
31
    {
32
      if(  *( SpielfeldPt +((Y * Spielfeldgroesse_x) + (X)) )  )
33
      {
34
        while(i <= 5)
35
        {
36
          while(j <= 5)
37
          {
38
            DrawPixel( ((X*5)+j), ((Y*5)+i), 0xFFFF0000);
39
            j++;
40
          }
41
          j = 0;
42
          i++;
43
        }
44
        i = 0;
45
      }
46
47
      X++;
48
    }
49
    X = 0;
50
    Y++;
51
  }
52
  Y = 0;
53
54
  while ( Y <= (5*Spielfeldgroesse_y) )
55
  {
56
    DrawLine(0, Y, 5*Spielfeldgroesse_x, Y);
57
    Y += 5;
58
  }
59
  Y = 0;
60
61
  while ( X <= (5*Spielfeldgroesse_x) )
62
  {
63
    DrawLine(X, 0, X, 5*Spielfeldgroesse_y);
64
    X += 5;
65
  }
66
  X = 0;
67
68
  DrawString(10, 252, TextPt);
69
70
71
  /*
72
  if(Layerswitch)
73
  {
74
    Layer2_schreiben__Layer1_zeigen();
75
  }
76
  else
77
    {
78
      Layer1_schreiben__Layer2_zeigen();
79
    }
80
  */
81
82
}

Dann werden die oben angesprochen Vergleiche gemacht:
1
void GameOfLife_Zug (uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y, uint8_t *SpielfeldPt, uint8_t *SpielfeldschattenPt)
2
{
3
  uint8_t Spielregeln[3] = {1, 4, 3};
4
  /*
5
   * Wenn eine lebende Zelle den ersten Arraywert oder weniger lebende Nachbarn hat, stirbt sie an Vereinsamung.
6
   * Wenn eine lebende Zelle den zweiten Arraywert oder mehr lebende Nachbarn hat, stirbt sie an Überbevölkerung.
7
   * Wenn eine tote Zelle genau den dritten Arraywert an lebenden Nachbarn hat, wird sie lebendig.
8
   */
9
  uint8_t *RegelPt = &Spielregeln[0];
10
11
12
  LinksObenCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
13
  RechtsObenCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
14
  LinksUntenCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
15
  RechtsUntenCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
16
  RandObenCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
17
  RandUntenCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
18
  RandLinksCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
19
  RandRechtsCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
20
  FeldCheck(RegelPt, SpielfeldPt, SpielfeldschattenPt, Spielfeldgroesse_x, Spielfeldgroesse_y);
21
}

Exemplarisch je für eine Ecke, einen Rand und das Innenfeld:
1
void LinksObenCheck(uint8_t *RegelPt, uint8_t *SpielfeldPt, uint8_t *SpielfeldschattenPt, uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y)
2
{
3
  uint8_t Nachbarschaft = 0;
4
  /*
5
   * hier wird die obere linke Eckezelle auf lebende Nachbarn überprüft. Die "Nachbarn" liegen aber auch über die Ecken,
6
   * daher würde der Zahlindex unterlaufen (0 --> 65535) da dass Spielfeld nicht 16bit groß ist. Um die in der Nachbarschaftsabfrage
7
   * für die Zellen im Feld und nicht am Rand sonst nötige If-Abfrage zu sparen, werden die Ecken und Ränder einzeln abgehandelt.
8
   */
9
  if( *SpielfeldPt )                    //Prüfen ob Zelle(0,0) lebt. Zelle(0,0) ist die in der linken oberen Ecke
10
  {                          //Falls sie lebt
11
    if( *( SpielfeldPt + 1) )            //prüfen ob die Zelle(1,0) rechts daneben lebt
12
    {
13
      Nachbarschaft++;
14
    }
15
16
    if( *(SpielfeldPt + Spielfeldgroesse_x) )     //prüfen ob die Zelle(0,1) darunter lebt (SpielfeldPt + Spielfeldgroesse_x) ist die erste Zelle der 2ten Reihe
17
    {
18
      Nachbarschaft++;
19
    }
20
21
    if( *(SpielfeldPt + Spielfeldgroesse_x + 1) )     //prüfen ob die Zelle(1,1) darunter rechts lebt (SpielfeldPt + Spielfeldgroesse_x + 1) ist  die zweite Zelle der 2ten Reihe
22
    {
23
      Nachbarschaft++;
24
    }
25
26
    if( *(SpielfeldPt + Spielfeldgroesse_x - 1) )     //(SpielfeldPt + Spielfeldgroesse_x - 1) ist  die letzte Zelle der 1ten Reihe
27
    {
28
      Nachbarschaft++;
29
    }
30
31
    if( *(SpielfeldPt + (Spielfeldgroesse_x*2) - 1) )     //(SpielfeldPt + (Spielfeldgroesse_x*2) - 1) ist  die letze Zelle der 2ten Reihe
32
    {
33
      Nachbarschaft++;
34
    }
35
36
    if( *(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1))) )     //(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1))) ist  die erste Zelle der letzten Reihe
37
    {
38
      Nachbarschaft++;
39
    }
40
41
    if( *(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1)) + 1) )     //(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1)) +1) ) ist  die zweite Zelle der letzten Reihe
42
    {
43
      Nachbarschaft++;
44
    }
45
46
    if( *(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y)) - 1) )     //(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y)) - 1) ist  die letzte Zelle der letzten Reihe
47
    {
48
      Nachbarschaft++;
49
    }
50
51
    /*
52
     * Nach Überprüfung der Anzahl an lebendigen Nachbarn, wird die Zelle in Abhängikeit der Regeln als TOT oder LEBENDIG
53
     * auf dem Schattenspielfeld abgelegt. Das Schattenspielfeld dient dazu, die neuen Leben/Tot Verhältnisse bis zur
54
     * vollständigen Überprüfung des Spielfeldes aufbewahrt. Läge man die Werte direkt auf dem Spielfeld ab,
55
     * verfälschten sie die Werte für die weitere Überprüfung.
56
     */
57
    if ( (Nachbarschaft <= *(RegelPt + LuG)) )
58
    {
59
      *SpielfeldschattenPt = TOT;
60
    }
61
    else if ( (Nachbarschaft >= *(RegelPt + LoG)) )
62
      {
63
        *SpielfeldschattenPt = TOT;
64
      }
65
      else
66
        {
67
          *SpielfeldschattenPt = LEBENDIG;
68
        }
69
    Nachbarschaft = 0;
70
71
  }
72
  else  //Falls die Zelle tot ist:
73
  {
74
    if( *( SpielfeldPt + 1) )            //prüfen ob die Zelle(1,0) rechts daneben lebt
75
    {
76
      Nachbarschaft++;
77
    }
78
79
    if( *(SpielfeldPt + Spielfeldgroesse_x) )     //prüfen ob die Zelle(0,1) darunter lebt (SpielfeldPt + Spielfeldgroesse_x) ist die erste Zelle der 2ten Reihe
80
    {
81
      Nachbarschaft++;
82
    }
83
84
    if( *(SpielfeldPt + Spielfeldgroesse_x + 1) )     //prüfen ob die Zelle(1,1) darunter rechts lebt (SpielfeldPt + Spielfeldgroesse_x + 1) ist  die zweite Zelle der 2ten Reihe
85
    {
86
      Nachbarschaft++;
87
    }
88
89
    if( *(SpielfeldPt + Spielfeldgroesse_x - 1) )     //(SpielfeldPt + Spielfeldgroesse_x - 1) ist  die letzte Zelle der 1ten Reihe
90
    {
91
      Nachbarschaft++;
92
    }
93
94
    if( *(SpielfeldPt + (Spielfeldgroesse_x*2) - 1) )     //(SpielfeldPt + (Spielfeldgroesse_x*2) - 1) ist  die letze Zelle der 2ten Reihe
95
    {
96
      Nachbarschaft++;
97
    }
98
99
    if( *(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1))) )     //(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1))) ist  die erste Zelle der letzten Reihe
100
    {
101
      Nachbarschaft++;
102
    }
103
104
    if( *(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1)) + 1) )     //(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y-1)) +1) ) ist  die zweite Zelle der letzten Reihe
105
    {
106
      Nachbarschaft++;
107
    }
108
109
    if( *(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y)) - 1) )     //(SpielfeldPt + (Spielfeldgroesse_x*(Spielfeldgroesse_y)) - 1) ist  die letzte Zelle der letzten Reihe
110
    {
111
      Nachbarschaft++;
112
    }
113
114
    /*
115
     * Nach Überprüfung der Anzahl an lebendigen Nachbarn, wird die Zelle in Abhängikeit der Regeln als TOT oder LEBENDIG
116
     * auf dem Schattenspielfeld abgelegt. Das Schattenspielfeld dient dazu, die neuen Leben/Tot Verhältnisse bis zur
117
     * vollständigen Überprüfung des Spielfeldes aufbewahrt. Läge man die Werte direkt auf dem Spielfeld ab,
118
     * verfälschten sie die Werte für die weitere Überprüfung.
119
     */
120
    if ( (Nachbarschaft == *(RegelPt + TwL)) )
121
    {
122
      *SpielfeldschattenPt = LEBENDIG;
123
    }
124
    else
125
      {
126
        *SpielfeldschattenPt = TOT;
127
      }
128
    Nachbarschaft = 0;
129
  }
130
}
131
132
void RandObenCheck(uint8_t *RegelPt, uint8_t *SpielfeldPt, uint8_t *SpielfeldschattenPt, uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y)
133
{
134
  uint8_t Nachbarschaft = 0;
135
  uint8_t X = 1;
136
137
  while( X < (Spielfeldgroesse_x - 1) )
138
  {
139
    if( *(SpielfeldPt + X) )
140
    {
141
      if( *(SpielfeldPt + (X-1)) )
142
      {
143
        Nachbarschaft++;
144
      }
145
146
      if( *(SpielfeldPt + (X+1)) )
147
      {
148
        Nachbarschaft++;
149
      }
150
151
      if( *(SpielfeldPt + (Spielfeldgroesse_x + X - 1)) )
152
      {
153
        Nachbarschaft++;
154
      }
155
156
      if( *(SpielfeldPt + (Spielfeldgroesse_x + X)) )
157
      {
158
        Nachbarschaft++;
159
      }
160
161
      if( *(SpielfeldPt + (Spielfeldgroesse_x + X + 1)) )
162
      {
163
        Nachbarschaft++;
164
      }
165
166
      if( *(SpielfeldPt + ((Spielfeldgroesse_x *(Spielfeldgroesse_y-1)) + X-1)) )
167
      {
168
        Nachbarschaft++;
169
      }
170
171
      if( *(SpielfeldPt + ((Spielfeldgroesse_x *(Spielfeldgroesse_y-1)) + X)) )
172
      {
173
        Nachbarschaft++;
174
      }
175
176
      if( *(SpielfeldPt + ((Spielfeldgroesse_x *(Spielfeldgroesse_y-1)) + X+1)) )
177
      {
178
        Nachbarschaft++;
179
      }
180
181
      if ( (Nachbarschaft <= *(RegelPt + LuG)) )
182
      {
183
        *(SpielfeldschattenPt + X) = TOT;
184
      }
185
      else if ( (Nachbarschaft >= *(RegelPt + LoG)) )
186
        {
187
          *(SpielfeldschattenPt + X) = TOT;
188
        }
189
        else
190
          {
191
            *(SpielfeldschattenPt + X) = LEBENDIG;
192
          }
193
      Nachbarschaft = 0;
194
    }
195
    else
196
    {
197
      if( *(SpielfeldPt + (X-1)) )
198
      {
199
        Nachbarschaft++;
200
      }
201
202
      if( *(SpielfeldPt + (X+1)) )
203
      {
204
        Nachbarschaft++;
205
      }
206
207
      if( *(SpielfeldPt + (Spielfeldgroesse_x + X - 1)) )
208
      {
209
        Nachbarschaft++;
210
      }
211
212
      if( *(SpielfeldPt + (Spielfeldgroesse_x + X)) )
213
      {
214
        Nachbarschaft++;
215
      }
216
217
      if( *(SpielfeldPt + (Spielfeldgroesse_x + X + 1)) )
218
      {
219
        Nachbarschaft++;
220
      }
221
222
      if( *(SpielfeldPt + ((Spielfeldgroesse_x *(Spielfeldgroesse_y-1)) + X-1)) )
223
      {
224
        Nachbarschaft++;
225
      }
226
227
      if( *(SpielfeldPt + ((Spielfeldgroesse_x *(Spielfeldgroesse_y-1)) + X)) )
228
      {
229
        Nachbarschaft++;
230
      }
231
232
      if( *(SpielfeldPt + ((Spielfeldgroesse_x *(Spielfeldgroesse_y-1)) + X+1)) )
233
      {
234
        Nachbarschaft++;
235
      }
236
237
      if ( (Nachbarschaft == *(RegelPt + TwL)) )
238
          {
239
            *(SpielfeldschattenPt + X) = LEBENDIG;
240
          }
241
          else
242
            {
243
              *(SpielfeldschattenPt + X) = TOT;
244
            }
245
          Nachbarschaft = 0;
246
    }
247
    X++;
248
  }
249
}
250
251
void FeldCheck(uint8_t *RegelPt, uint8_t *SpielfeldPt, uint8_t *SpielfeldschattenPt, uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y)
252
{
253
  uint8_t Nachbarschaft = 0;
254
  uint8_t X = 1;
255
  uint8_t Y = 1;
256
257
  while( Y < (Spielfeldgroesse_y - 1) )
258
  {
259
    while( X < (Spielfeldgroesse_x - 1) )
260
    {
261
      if( *(SpielfeldPt + (Spielfeldgroesse_x * Y) + (X) ) )
262
      {
263
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y-1)) + (X-1) ) )
264
        {
265
          Nachbarschaft++;
266
        }
267
268
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y-1)) + (X) ) )
269
        {
270
          Nachbarschaft++;
271
        }
272
273
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y-1)) + (X+1) ) )
274
        {
275
          Nachbarschaft++;
276
        }
277
278
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y)) + (X-1) ) )
279
        {
280
          Nachbarschaft++;
281
        }
282
283
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y)) + (X+1) ) )
284
        {
285
          Nachbarschaft++;
286
        }
287
288
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y+1)) + (X-1) ) )
289
        {
290
          Nachbarschaft++;
291
        }
292
293
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y+1)) + (X) ) )
294
        {
295
          Nachbarschaft++;
296
        }
297
298
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y+1)) + (X+1) ) )
299
        {
300
          Nachbarschaft++;
301
        }
302
303
        if ( (Nachbarschaft <= *(RegelPt + LuG)) )
304
        {
305
          *(SpielfeldschattenPt + (Spielfeldgroesse_x*Y) + X ) = TOT;
306
        }
307
        else if ( (Nachbarschaft >= *(RegelPt + LoG)) )
308
          {
309
            *(SpielfeldschattenPt + (Spielfeldgroesse_x*Y) + X ) = TOT;
310
          }
311
          else
312
            {
313
              *(SpielfeldschattenPt + (Spielfeldgroesse_x*Y) + X ) = LEBENDIG;
314
            }
315
        Nachbarschaft = 0;
316
      }
317
      else
318
      {
319
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y-1)) + (X-1) ) )
320
        {
321
          Nachbarschaft++;
322
        }
323
324
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y-1)) + (X) ) )
325
        {
326
          Nachbarschaft++;
327
        }
328
329
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y-1)) + (X+1) ) )
330
        {
331
          Nachbarschaft++;
332
        }
333
334
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y)) + (X-1) ) )
335
        {
336
          Nachbarschaft++;
337
        }
338
339
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y)) + (X+1) ) )
340
        {
341
          Nachbarschaft++;
342
        }
343
344
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y+1)) + (X-1) ) )
345
        {
346
          Nachbarschaft++;
347
        }
348
349
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y+1)) + (X) ) )
350
        {
351
          Nachbarschaft++;
352
        }
353
354
        if( *(SpielfeldPt + (Spielfeldgroesse_x * (Y+1)) + (X+1) ) )
355
        {
356
          Nachbarschaft++;
357
        }
358
359
        if ( (Nachbarschaft == *(RegelPt + TwL)) )
360
        {
361
          *(SpielfeldschattenPt + (Spielfeldgroesse_x*Y) + X ) = LEBENDIG;
362
        }
363
        else
364
          {
365
            *(SpielfeldschattenPt + (Spielfeldgroesse_x*Y) + X ) = TOT;
366
          }
367
        Nachbarschaft = 0;
368
      }
369
370
      X++;
371
    }
372
    X = 0;
373
    Y++;
374
  }
375
}

Und dann wird noch das Schattenspielfeld aufs Spielfeldübertragen und 
gelöscht:
1
  GameOfLife_Spielfeldinit_Random(Wahrscheinlichkeit, Spielfeldgroesse_x, Spielfeldgroesse_y, SpielfeldPt, SpielfeldschattenPt);
2
  while(1)
3
  {
4
    GameOfLife_Spielfeldzeichnen(Spielfeldgroesse_x, Spielfeldgroesse_y, SpielfeldPt);
5
    GameOfLife_Zug(Spielfeldgroesse_x, Spielfeldgroesse_y, SpielfeldPt, SpielfeldschattenPt);
6
7
    while(y < Spielfeldgroesse_y)
8
    {
9
      while(x < Spielfeldgroesse_x)
10
      {
11
        *(SpielfeldPt + (Spielfeldgroesse_x*y) + x ) = *(SpielfeldschattenPt + (Spielfeldgroesse_x*y) + x );
12
        *(SpielfeldschattenPt + (Spielfeldgroesse_x*y) + x ) = 0;
13
        x++;
14
      }
15
      x = 0;
16
      y++;
17
    }
18
  }
19
}

Im Anhang auch noch alle vermutlich wichtigen Dateien. Das wird zu viel 
sonst hier. Falls noch irgendwas fehlen sollte, einfach Bescheid sagen.

Vielen Dank schonmal fürs Lesen und mit freundlichen Grüßen
Chaos

P.S. Die letzten Male als ich was fragen wollte, ist mir die Lösung 
immer beim Verfassen des Beitrages wie Schuppen von den Augen gefallen. 
Das hat diesmal leider nicht geklappt, obwohl ich mir wirklich Mühe 
gegeben hab ;-)

: Verschoben durch User
von Ralph S. (jjflash)


Lesenswert?

... sorry, aber kein Mensch liest im Posting hier den ellen langen 
Programmcode (auch wenn der wahrscheinlich in deinen angehängten Dateien 
noch einmal vorkommt)...

von J. T. (chaoskind)


Lesenswert?

Ralph S. schrieb:
> auch wenn der wahrscheinlich in deinen angehängten Dateien
> noch einmal vorkommt)...

Ja tut er, kann man also erstmal drüberscrollen, und ja durch dieses 
Vergleichsgewulst isses echt lang geworden. Dazu hätte ich später auch 
noch Fragen, aber Stück für Stück

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

J. T. schrieb:
> Unter anderem ist mir nicht eingefallen, wie ich mir die if-Abfrage für
> jedes Feld spare, ob es am Rand liegt oder nicht.

Indem du als Spielfeldgröße eine 2er-Potenz wählst und mit Masken 
arbeitest.

von J. T. (chaoskind)


Lesenswert?

Wolfgang schrieb:
> J. T. schrieb:
> Unter anderem ist mir nicht eingefallen, wie ich mir die if-Abfrage für
> jedes Feld spare, ob es am Rand liegt oder nicht.
>
> Indem du als Spielfeldgröße eine 2er-Potenz wählst und mit Masken
> arbeitest.

Und wenn ich ein freies Verhältniss haben möchte?

Aber der Teil ist wie gesagt nicht das wirkliche Problem denke ich.

Ich würd gern wissen wieso nur im ersten Durchlauf Änderungen passieren.

von Wolfgang (Gast)


Lesenswert?

J. T. schrieb:
> Und wenn ich ein freies Verhältniss haben möchte?

Dann musst du eben die Prozessorleistung dafür vorhalten oder mit 
entsprechend geringerer Frame-Rate leben.

von zero-q2 (Gast)


Lesenswert?

that's real live ;-)

von J. T. (chaoskind)


Lesenswert?

Wolfgang schrieb:
> Dann musst du eben die Prozessorleistung dafür vorhalten oder mit
> entsprechend geringerer Frame-Rate leben

Tue ich gerne.

J. T. schrieb:
> Ich würd gern wissen wieso nur im ersten Durchlauf Änderungen passieren

Kannst du dazu auch was sagen? Um nun mal auf das eigentliche Problem zu 
kommen?

von J. T. (chaoskind)


Lesenswert?

Ralph S. schrieb:
> ... sorry, aber kein Mensch liest im Posting hier den ellen langen
> Programmcode (auch wenn der wahrscheinlich in deinen angehängten Dateien
> noch einmal vorkommt)...

Dann halt hier nochmal der Eingangspost ohne Code:

MoinMoin,

nachdem ich nun endlich mein STM32F746Disco soweit zum Laufen bekommen
habe, dass ich auf dem LCD rummalen kann, habe ich angefangen ein Game
of Life zu schreiben. Wahrscheinlich sehr von hinten durch die
Hühneraugenbrust.

Unter anderem ist mir nicht eingefallen, wie ich mir die if-Abfrage für
jedes Feld spare, ob es am Rand liegt oder nicht. Meine Spielwelt soll
ein Torus sein, sprich was rechts aus dem Bild läuft kommt links wieder
rein, und umgekehrt, selbiges gilt für oben und unten.

Die Felder müssen auf lebende Nachbarn überprüft werden, mitten im Feld
kein Problem, einfach die Felder
( (Feldkoordinate+1X+1Y) (Feldkoordinate+1X+0Y) (Feldkoordinate+1X-1Y)
  (Feldkoordinate+0X+1Y)____________________(Feldkoordinate+0X-1Y)
  (Feldkoordinate-1X+1Y) (Feldkoordinate-1X+0Y) (Feldkoordinate-1X-1Y) )
abfragen.

Aber am Rand käme es dann ja zu Unterlaufen, und er würde auf Felder
prüfen, die ausserhalb der Spielwelt und wer weiß wo/was im Speicher
liegen. Das Spielfeld wird übrigens als uint8_t Spielfeld[][]
initialisiert.

Also die Abfrageroutine für die Ecken gesondert behandelt, und die für
die Ränder gesondert behandelt. Im Endeffekt die selbe Routine wie im
Feld, nur mit teils festgelegten statt dynamischen Koordinaten.
Das sollte dann doch schneller laufen, als wenn ich in jedem Feld eine
Randprüfung machen würde? Zumindest ab einer gewissen Spielfeldgröße?

Das ist aber nur ne kleine Nebenfrage....


Mein Hauptproblem ist folgendes, und es wäre super wenn da jemand nen
Fehler findet, bzw mir sagen kann, was ich falsch mache:

Das Spiel läuft nach dem Initialisieren nur eine Runde, danach bleibt
alles gleich. Soweit ich das beim Durchsteppen beobachten konnte, macht
er soweit aber alles wie im ersten Durchlauf, wo sich ja etwas
ändert....
Ich arbeite übrigens mit SW4STM32, falls dass irgendwie helfen sollte.
Und der Controller ist wie erwähnt ein STM32F746 auf dem Discovery
Board.

Also starten/init -->
Auf den Bildschirm malen, ich seh was (nennen wie es X) -->

Nachbarschaft prüfen, Ergbenisse in ein Schattenspielfeld speichern -->
Schattenspielfeld aufs Spielfeld übertragen und Schattenspielfeld wieder
leeren -->

"Neues" Spielfeld auf Bildschirm malen, ich seh was anderes (nennen wir
es  Y) -->

Nachbarschaft prüfen, Ergbenisse in ein Schattenspielfeld speichern -->

Schattenspielfeld aufs Spielfeld übertragen und Schattenspielfeld wieder
leeren -->

"Neues" Spielfeld auf Bildschirm malen, ich seh das gleiche/selbe (Y)-->

Nachbarschaft prüfen, Ergbenisse in ein Schattenspielfeld speichern -->

Schattenspielfeld aufs Spielfeld übertragen und Schattenspielfeld wieder
leeren -->

"Neues" Spielfeld auf Bildschirm malen, ich seh das gleiche/selbe (Y)-->
.
.
.


Ich starte das Programm. Das Spielfeld wird mit zufälligen
Lebend/Tot-Zellen initialsiert:

void GameOfLife_Spielfeldinit_Random(uint8_t Wahrscheinlichkeit, 
uint16_t Spielfeldgroesse_x, uint16_t Spielfeldgroesse_y, uint8_t 
*SpielfeldPt, uint8_t *SpielfeldschattenPt)



Das Spielfeld wird gezeichnet. Ich hab erst auf einen Layer gezeichnet,
während ich einen anderen gezeigt hab, damit es nicht so flackert beim
malen. Ich dachte evtl klemmt es beim Layerumschalten, also den Teil
auskommentiert. Keine Änderung:

void GameOfLife_Spielfeldzeichnen(uint16_t Spielfeldgroesse_x, uint16_t 
Spielfeldgroesse_y, uint8_t *SpielfeldPt)



Dann werden die oben angesprochen Vergleiche gemacht:

void GameOfLife_Zug (uint16_t Spielfeldgroesse_x, uint16_t 
Spielfeldgroesse_y, uint8_t *SpielfeldPt, uint8_t *SpielfeldschattenPt)



Und dann wird noch das Schattenspielfeld aufs Spielfeldübertragen und
gelöscht:

  GameOfLife_Spielfeldinit_Random(Wahrscheinlichkeit, 
Spielfeldgroesse_x, Spielfeldgroesse_y, SpielfeldPt, 
SpielfeldschattenPt)


Im Anhang auch noch alle vermutlich wichtigen Dateien. Das wird zu viel
sonst hier. Falls noch irgendwas fehlen sollte, einfach Bescheid sagen.

Vielen Dank schonmal fürs Lesen und mit freundlichen Grüßen
Chaos

P.S. Die letzten Male als ich was fragen wollte, ist mir die Lösung
immer beim Verfassen des Beitrages wie Schuppen von den Augen gefallen.
Das hat diesmal leider nicht geklappt, obwohl ich mir wirklich Mühe
gegeben hab ;-)

von Purzel (Gast)


Lesenswert?

Ich empfehl den code auf einem PC mit Debugger laufenzulassen. Ein PC 
Compiler in einer PC IDE hat ueblicherweise einen Singlestep debugger. 
Dann wird's supertrivial...

von Wolfgang (Gast)


Lesenswert?

J. T. schrieb:
> Tue ich gerne.

Du kannst natürlich auch am Algorithmus feilen, indem du erstmal prüfst, 
ob sich die Zelle, für die der Zustand gerade neu berechnet werden soll, 
überhaupt in Randnähe befindet. Wenn nicht, kannst du dir die ganze 
Prüferei sparen.

> Kannst du dazu auch was sagen? Um nun mal auf das eigentliche Problem zu
> kommen?

Guck einfach nach, was das Programm macht, während du von ihm erwartest, 
dass es sich um die Berechnung des nächsten Frames kümmert. Dafür gibt 
es Debugger.

von J. T. (chaoskind)


Lesenswert?

Purzel schrieb:
> Ich empfehl den code auf einem PC mit Debugger laufenzulassen. Ein PC
> Compiler in einer PC IDE hat ueblicherweise einen Singlestep debugger.
> Dann wird's supertrivial...

Wolfgang schrieb:
> Guck einfach nach, was das Programm macht, während du von ihm erwartest,
> dass es sich um die Berechnung des nächsten Frames kümmert. Dafür gibt
> es Debugger.

J. T. schrieb:
> Soweit ich das beim Durchsteppen beobachten konnte, macht
> er soweit aber alles wie im ersten Durchlauf, wo sich ja etwas
> ändert..

Ich meine es ist nett, dass ihr helfen wollt. Aber irgendwie hab ich das 
Gefühl, ihr lest gar nicht, wobei ihr helfen wollt. Aber es wird halt 
nicht supertrivial.

Im ersten Durchlauf zur Berechnung der nächsten "Generation" verfolge 
ich im Debugger alles. Die Pointer schreiben an die richtigen Stellen 
auf dem Schattenspielfeld. Die umgebenden Zellen werden richtig 
ausgewertet. Das wird dann ausgegeben. Beim nächsten Durchlauf werden 
wieder alle Zellen richtig ausgewertet und an die richtigen Stellen 
geschrieben. Aber irgendwie wird das nicht übernommen... Diese Stelle 
finde ich aber beim Durchsteppen nicht...

von Egon D. (Gast)


Lesenswert?

J. T. schrieb:

> Unter anderem ist mir nicht eingefallen, wie ich mir
> die if-Abfrage für jedes Feld spare, ob es am Rand
> liegt oder nicht. Meine Spielwelt soll ein Torus sein,
> sprich was rechts aus dem Bild läuft kommt links wieder
> rein, und umgekehrt, selbiges gilt für oben und unten.

Das ist ausgerechnet einfach: Restklassen --> modulo.

Gegebenenfalls müsstest Du prüfen, wie die entsprechenden
Operatoren mit negativen Zahlen umgehen; das kann zu
Ärger führen.

von J. T. (chaoskind)


Lesenswert?

Wolfgang schrieb:
> Du kannst natürlich auch am Algorithmus feilen, indem du erstmal prüfst,
> ob sich die Zelle, für die der Zustand gerade neu berechnet werden soll,
> überhaupt in Randnähe befindet. Wenn nicht, kannst du dir die ganze
> Prüferei sparen.

Und um mir die Prüferei ganz zu sparen, hab ich die Kanten und Ecken 
halt ausgesondert. So muss ich gar nicht erst prüfen, sondern weiß. Die 
Frage in dem Zusammenhang war einfach nur, ob das Zyklen spart. Ich 
meine: Ja.

Die Schleife für die Sonderfälle bleibt die selbe, nur die Werte der 
Pointer werden anders festgelegt. Da dürften also nicht viele Zyklen 
zukommen. Ich spare mir aber bei JEDEM Feld die Prüferei, was je nach 
Spielfeldgröße ne Menge Zyklen sparen könnte. Um eine Abschätzung der 
Einsparung ging es mir bei dieser. Wobei dass, wie nun schon mehrfach 
erwähnt, gar nicht die Frage ist, um die es mir geht.

Um wieder darau zurückzukommen:

Ich hab nochmal ein wenig über den Code geschaut. In der 
GameOfLife_Spielfeldinit_Random hatte ich auch das Schattenspielfeld auf 
die Zufallswerte initialisiert. Hab das nun auf 0 geändert und hatte 
bedenken, dass nun nichts mehr passieren würde, da die Änderung nur 
Artefakte aus der Mischung von Prüfung und altem Feld wären, da ich die 
Felder mit 0 initialisiere und nur 1 schreibe.

von J. T. (chaoskind)


Angehängte Dateien:

Lesenswert?

Anbei ein paar Bilder... Evtl verdeutlicht das ja mein Problem

: Bearbeitet durch User
von J. T. (chaoskind)


Lesenswert?

Es läuft...
1
  while(1)
2
  {
3
    GameOfLife_Spielfeldzeichnen(Spielfeldgroesse_x, Spielfeldgroesse_y, SpielfeldPt, Feldgroesse);
4
    GameOfLife_Zug(Spielfeldgroesse_x, Spielfeldgroesse_y, SpielfeldPt, SpielfeldschattenPt, *RegelPt);
5
6
    while(y < Spielfeldgroesse_y)
7
    {
8
      while(x < Spielfeldgroesse_x)
9
      {
10
        *(SpielfeldPt + (Spielfeldgroesse_x*y) + x ) = *(SpielfeldschattenPt + (Spielfeldgroesse_x*y) + x );
11
        *(SpielfeldschattenPt + (Spielfeldgroesse_x*y) + x ) = 0;
12
        x++;
13
      }
14
      x = 0;
15
      y++;
16
    }
17
    y = 0;  //<----DIESES y WURDE NICHT ZURÜCKGESETZT
18
  }

nachdem ich das y = 0; eingefügt hab, läufts  nun!

Wie ich diese Art von Fehler hasse. :D

Da mein Hauptanliegen nun gelöst ist, und ihr es vorhin eh viel 
spannender fandet das Randproblem zu diskutieren, dürft ihr euch nun 
gern aufs herzlichste die Köpfe einhauen =)

: Bearbeitet durch User
von --- (Gast)


Lesenswert?

Fuer so dummes Zeug wie:
1
    while(y < Spielfeldgroesse_y)
2
    {
3
      ...
4
      y++;
5
    }
6
    y = 0;

haette jemand mit Restverstand gleich:
1
    for(y = 0; y < Spielfeldgroesse_y; y++)
2
    {
3
      ...
4
    }

geschrieben.
Such die naechste Betonwand und hau ein paarmal deine Birne dagegen.
Schlimmer kann es nicht mehr werden.

von Florian (Gast)


Lesenswert?

Purzel schrieb:
> supertrivial

Das ist in etwa so wie "unglaublich redundant"

von Stefan F. (Gast)


Lesenswert?

J. T. schrieb:
> Ich meine es ist nett, dass ihr helfen wollt. Aber
> irgendwie hab ich das Gefühl, ihr lest gar nicht, wobei
> ihr helfen wollt. Aber es wird halt nicht supertrivial.

Da ist was dran. Ich habe bei deinem ersten Beitrag nach dem ersten 
viertel aufgehört zu lesen und den Rest nur noch überflogen. Mir fehlt 
die Motivation, so viel Text verstehend zu lesen - aber das ist heute 
mein persönliches Problem. Mein Job hat mich diese Woche ausgepowert.

Andererseits möchte ich Dich dafür loben, dein Problem so detailliert 
dargestellt zu haben. Das andere Extrem kommt zur Zeit nämlich leider 
viel zu häufig vor, und diese Fälle gehen mir richtig auf die Nerven.

Ich habe mir das mal bei Youtube angesehen. Es geht wohl um eine 
Simulation von Einfachen Individuen, die miteinander interagieren.

> Das Spiel läuft nach dem Initialisieren nur eine Runde,
> danach bleibt alles gleich.
> Soweit ich das beim Durchsteppen beobachten konnte, macht
> er soweit aber alles wie im ersten Durchlauf, wo sich ja etwas
> ändert

Ich kenne dieses "Game of Life" nicht wirklich. Was mir an diesen beiden 
Sätzen auffällt ist allerdings, dass beim zweiten Durchlauf alles gleich 
läuft, obwohl sich etwas ändern soll. Also müsste doch beim Durchsteppen 
des zweiten Durchlaufen offensichtlich sein, was sich fälschlicherweise 
nicht geändert hat.

Da sich nach dem ersten Schritt in den folgenden Schritten nichts mehr 
ändert, würde ich es mit Einzelschritt-Debugging mit einem sehr kleinen 
Spielfeld untersuchen. Da gibt es doch Bedingungen, die zur Interaktion 
(also Veränderung) führen. Entweder werden diese Bedingungen in deinem 
Code nicht richtig erkannt, oder die Aktionen funktionieren nicht.

Erzeuge Dir also ein Bild, dokumentiere auf Papier die Bedingungen und 
Aktionen, die als nächstes kommen müssen. Dann lässt du dein Programm 
Zeile für Zeile laufen, um zu sehen, wo es sich anders (falsch) verhält.

Nachtrag: Dafür habe ich jetzt 40 Minuten gebraucht und wurde durch 
andere Beiträge überholt. Alles für die Katz, ich ahnte es schon. Ich 
lege mich wieder hin, bis diese kack Woche (ist nicht Deine Schuld) 
zuende ist.

PS: Du solltest nicht mitten in der Nacht Arbeiten durchführen, die 
klares Denken erfordern.

von CM (Gast)


Lesenswert?

Man könnte das Ganze natürlich auch arduinofizieren, dann wird's nochmal 
einfacher:

https://github.com/ChrisMicro/Arduino_STM32F7_Discovery/tree/master/_0211_GameOfLife

von Stefan F. (Gast)


Lesenswert?

CM schrieb:
> Man könnte das Ganze natürlich auch arduinofizieren

Und dann auf den Debugger verzichten?

Mir ist jetzt auch irgendwie nicht klar, inwiefern Arduino das Problem 
vereinfacht hätte.

von Wolfgang (Gast)


Lesenswert?

Stefanus F. schrieb:
> Ich kenne dieses "Game of Life" nicht wirklich.

Game of Life ist ein inzwischen fast 50 Jahre alter Zellulärer Automat, 
der 1970 von John Horton Conway entworfen wurde und schon kurz danach 
selbst auf einem 6502 lief.

von J. T. (chaoskind)


Lesenswert?

Stefanus F. schrieb:
> J. T. schrieb:
>> Ich meine es ist nett, dass ihr helfen wollt. Aber
>> irgendwie hab ich das Gefühl, ihr lest gar nicht, wobei
>> ihr helfen wollt. Aber es wird halt nicht supertrivial.
>
> Da ist was dran. Ich habe bei deinem ersten Beitrag nach dem ersten
> viertel aufgehört zu lesen und den Rest nur noch überflogen. Mir fehlt
> die Motivation, so viel Text verstehend zu lesen - aber das ist heute
> mein persönliches Problem. Mein Job hat mich diese Woche ausgepowert.

Dann erst mal meinen besonderen Dank, dass du dir dennoch die Mühe 
machst,  mir so eine ausgedehnte Antwort zu schreiben =)

> Andererseits möchte ich Dich dafür loben, dein Problem so detailliert
> dargestellt zu haben. Das andere Extrem kommt zur Zeit nämlich leider
> viel zu häufig vor, und diese Fälle gehen mir richtig auf die Nerven.

Das geht mir genauso. Manchmal ist es aber schwierig, da die richtige 
Waage zu halten. Besonders wenn ein Problem aus mehreren Teilen besteht. 
Dann sollte man die Teile nicht nur erwähnen, sondern auch beschreiben. 
Ein weiterer wertvoller Teil davon, so detailiert zu schreiben, ist dass 
einem Fehler in der Logik eigentlich schon beim Erstellen des Beitrages 
aufallen. So geht es mir zumindest meistens. War bei diesem Problem 
nicht der Fall. Kann man wohl als Indikator sehen, dass das Problem 
vermutlich nicht in der Logik liegt. War dann ja auch der Fall.

>
> Ich habe mir das mal bei Youtube angesehen. Es geht wohl um eine
> Simulation von Einfachen Individuen, die miteinander interagieren.
>
>> Das Spiel läuft nach dem Initialisieren nur eine Runde,
>> danach bleibt alles gleich.
>> Soweit ich das beim Durchsteppen beobachten konnte, macht
>> er soweit aber alles wie im ersten Durchlauf, wo sich ja etwas
>> ändert
>
> Ich kenne dieses "Game of Life" nicht wirklich. Was mir an diesen beiden
> Sätzen auffällt ist allerdings, dass beim zweiten Durchlauf alles gleich
> läuft, obwohl sich etwas ändern soll. Also müsste doch beim Durchsteppen
> des zweiten Durchlaufen offensichtlich sein, was sich fälschlicherweise
> nicht geändert hat.
>
Das solltest du ändern ;-). Zumindest ich finde es ziemlich 
faszinierend, was sich aus solch einfachen Regeln entwickeln kann.

> Da sich nach dem ersten Schritt in den folgenden Schritten nichts mehr
> ändert, würde ich es mit Einzelschritt-Debugging mit einem sehr kleinen
> Spielfeld untersuchen. Da gibt es doch Bedingungen, die zur Interaktion
> (also Veränderung) führen. Entweder werden diese Bedingungen in deinem
> Code nicht richtig erkannt, oder die Aktionen funktionieren nicht.
>
> Erzeuge Dir also ein Bild, dokumentiere auf Papier die Bedingungen und
> Aktionen, die als nächstes kommen müssen. Dann lässt du dein Programm
> Zeile für Zeile laufen, um zu sehen, wo es sich anders (falsch) verhält.

So bin ich dann auch vorgegangen, aber in Kombination mit

> PS: Du solltest nicht mitten in der Nacht Arbeiten durchführen, die
> klares Denken erfordern.

kann es schonmal vorkommen, dass man mehrmals durchsteppen muss :D

>
> Nachtrag: Dafür habe ich jetzt 40 Minuten gebraucht und wurde durch
> andere Beiträge überholt. Alles für die Katz, ich ahnte es schon. Ich
> lege mich wieder hin, bis diese kack Woche (ist nicht Deine Schuld)
> zuende ist.
>

Also nochmal herzlichen Dank für deinen Beitrag und mir bleibt dann nur 
noch, dir eine bessere nächste Woche zu wünschen.
Chaos

von J. T. (chaoskind)


Lesenswert?

CM schrieb:
> Man könnte das Ganze natürlich auch arduinofizieren, dann wird's nochmal
> einfacher:

Stefanus F. schrieb:
> Und dann auf den Debugger verzichten?
>
> Mir ist jetzt auch irgendwie nicht klar, inwiefern Arduino das Problem
> vereinfacht hätte.

Mir irgendwie auch nicht. Ohne den Debugger hät ich das fehlende y=0; 
vermutlich nie entdeckt.

--- schrieb:
> Fuer so dummes Zeug wie:
>
>     while(y < Spielfeldgroesse_y)
>     {
>       ...
>       y++;
>     }
>     y = 0;
>
> haette jemand mit Restverstand gleich:
>
>     for(y = 0; y < Spielfeldgroesse_y; y++)
>     {
>       ...
>     }
>
> geschrieben.
> Such die naechste Betonwand und hau ein paarmal deine Birne dagegen.
> Schlimmer kann es nicht mehr werden.

Irgendwann hatte ich mir mal einen plausiblen Grund ausgedacht, lieber 
while- statt for-schleifen zu benutzen. Der fällt mir natürlich nicht 
mehr ein, führte aber dazu mir die for-schleifen abzugewöhnen :D.
Beim Schreiben dieses Teils blitzte sogar einmal für ne millisekunde ein 
"nimm lieber ne for" durchs Hirn.

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

J. T. schrieb:
> Irgendwann hatte ich mir mal einen plausiblen Grund ausgedacht

Plausibel heißt nicht richtig, und missbrauchen kann man beide 
Konstrukte. Solange du draus gelernt hast, ist ja alles gut.

von Cyblord -. (cyblord)


Lesenswert?

S. R. schrieb:
> J. T. schrieb:
>> Irgendwann hatte ich mir mal einen plausiblen Grund ausgedacht
>
> Plausibel heißt nicht richtig, und missbrauchen kann man beide
> Konstrukte. Solange du draus gelernt hast, ist ja alles gut.

Und es gibt einen gewaltigen Unterschied zwischen FOR und WHILE 
Konstrukten. FOR Schleifen sind theoretisch nicht Turing-Vollständig, da 
sie irgendwann enden müssen. Es sind damit also keine Endlosschleifen 
möglich. Und es lassen sich manche Aufgaben damit nicht lösen. 
Theoretisch allerdings deshalb weil es manche Programmiersprachen 
erlauben die Schleifenvariable innerhalb der Schleife zu manipulieren 
und dann kann man doch wieder endlos erreichen.

Will sagen: Beide Konstrukte sind nicht beliebig austauschbar und "im 
Prinzip dasselbe". Das denken allerdings viele.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Häää?

for(;;) ist definitiv eine endlos-schleife!

von Wolfgang (Gast)


Lesenswert?

Cyblord -. schrieb:
> Und es gibt einen gewaltigen Unterschied zwischen FOR und WHILE
> Konstrukten. FOR Schleifen sind theoretisch nicht Turing-Vollständig, da
> sie irgendwann enden müssen. Es sind damit also keine Endlosschleifen
> möglich.

Aber nicht in C oder wie auch immer die Sprache heißt :-)
Dort wird nicht beim Eintritt in den Block die Anzahl der 
Schleifendurchläufe berechnet und dann ausgeführt, sondern es wird vor 
jedem Durchlauf di Bedinung geprüft.

Damit sind das im eigentlichen Sinne keine for-Schleifen, sondern 
while-Schleifen mit anderer Syntax.

von Cyblord -. (cyblord)


Lesenswert?

Stefanus F. schrieb:
> Häää?
>
> for(;;) ist definitiv eine endlos-schleife!

Das ist halt der viel besungene Unterschied zwischen Theorie und Praxis.
Theoretisch nimmt man eine FOR Schleife um etwas MAXIMAL n mal zu 
durchlaufen.
Praktisch kann man damit in quasi jeder Sprache aber auch viele andere 
Sauereien machen. Vor allem in C.

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Cyblord -. schrieb:
> Das ist halt der viel besungene Unterschied zwischen Theorie und Praxis.

Praktisch gibt es in C keine FOR-Schleife (im Sinne der 
Turing-Vollständigkeit), sondern das ist ein Patch aus den Anfangszeiten 
von C, um die gleiche Logik, die hinter einer WHILE-Schleife steckt, 
auch als FOR-Schleife zu verkaufen. Und nur darum funktioniert die 
C-FOR-Schleife auch als Endlosschleife.

von Stefan F. (Gast)


Lesenswert?

Jetzt kommen wieder die Experten raus, die ganz genau wissen, was sich 
die Erfinder diverser Programmiersprachen bei ihren Schlüsselwörtern 
gedacht haben und was das imaginäre GESETZ dazu sagt.

Nur bringt das hier niemanden auch nur ein Stück weiter.

Wolfgang schrieb:
> Praktisch gibt es in C keine FOR-Schleife (im Sinne der
> Turing-Vollständigkeit)

Doch gibt es, nämlich
1
for (;;) { doSomething(); }

Wenn dir das nicht passt, dann diskutiere bitte über eine andere 
Programmiersprache von der du wenigstens rudimentär Ahnung hast.

Beitrag #5587697 wurde von einem Moderator gelöscht.
von LBO (Gast)


Lesenswert?

Ich finde den Thread toll:
Überall anders wird befohlen, eine klare und ausführliche Beschreibung 
des Projekts abzugeben. Anschließend erfolgt der Verweis aufs 
Datenblatt, welches man gefälligst zu lesen hat - von vorn bis hinten.

Dann kommt einmal ein Threadersteller der alles liefert, was sonst immer 
erfragt wird (sonst könne und wolle man nicht helfen). Die Antwort: Das 
ist mir zu lang, das lese ich nicht. Wenn der Fehler dann vom 
Threadersteller selber gefunden wird kommen alle aus ihren Löchern und 
haben die Weisheit mit Löffeln gefressen - toll!

von Gamer (Gast)


Lesenswert?

> Game of Life läuft nur eine Runde!

Lass den Code so! Du hast durch Zufall das echte Leben simuliert. :-)

Beitrag #5587789 wurde vom Autor gelöscht.
von Cyblord -. (cyblord)


Lesenswert?

Stefanus F. schrieb:
> Doch gibt es, nämlichfor (;;) { doSomething(); }
>
> Wenn dir das nicht passt, dann diskutiere bitte über eine andere
> Programmiersprache von der du wenigstens rudimentär Ahnung hast.

Ach Bub, versuch doch wenigstens mal zu verstehen was der Wolfgang damit 
sagen wollte anstatt erstmal dummfrech rauszuplärren wie ein verzogenes 
Balg. Du blamierst dich.

von nop (Gast)


Lesenswert?

--- schrieb:
> Fuer so dummes Zeug wie:
>
>
1
> 
2
>     while(y < Spielfeldgroesse_y)
3
>     {
4
>       ...
5
>       y++;
6
>     }
7
>     y = 0;
8
> 
9
>
>
> haette jemand mit Restverstand gleich:
>
>
1
> 
2
>     for(y = 0; y < Spielfeldgroesse_y; y++)
3
>     {
4
>       ...
5
>     }
6
> 
7
>
>
> geschrieben.
> Such die naechste Betonwand und hau ein paarmal deine Birne dagegen.
> Schlimmer kann es nicht mehr werden.


viele Wege führen nach Rom, wer will da sagen welcher davon der bessere 
ist.
Aber er probiert es wenigstens!
Straffer Code ist in Zeiten von Terrabyte und Gigaherz sowieso nicht 
gefragt, vielmehr TTM, leider.

von Tim S. (tseidel)


Lesenswert?

Cyblord -. schrieb:
> FOR Schleifen sind theoretisch nicht Turing-Vollständig, da
> sie irgendwann enden müssen.

Cyblord -. schrieb:
> Ach Bub, versuch doch wenigstens mal zu verstehen was der Wolfgang damit
> sagen wollte anstatt erstmal dummfrech rauszuplärren wie ein verzogenes
> Balg. Du blamierst dich.

Für den Ton fehlt dir leider die Präzision und die Richtigkeit deiner 
Aussagen. Hier machst nur du dich nur lächerlich.

Du kannst offensichtlich nicht zwischen Sprache und Sprachelement 
unterscheiden. Nur so lässt sich erklären, dass du FOR Schleifen in die 
nicht Turing Vollständigkeit drückst.
Selbst die Definition einer FOR/LOOP Schleife in der entsprechenden 
FOR/LOOP Sprache erfüllt die Bedingung der Nicht-Turing-Vollständigkeit 
nicht ohne weitere Einschränkung der Sprache die nicht in der FOR 
Semantik begründet sind. Beispiel:

x = 1
FOR x DO BEGIN
  x = 1
END

Ist durchaus mächtiger als FOR/LOOP Sprachen, obwohl die FOR Syntax 
und Semantik eingehalten sind. Nur wenn Zähler und Literale distinkt 
sind, funktioniert deine Aussage. Das ist aber keine Eigenschaft des 
FOR.

Zudem gilt FOR/LOOP is subset of TV. -> FOR/LOOP Schleifen sind in jeder 
TV Sprache implementierbar. D.h. die Implikation funktioniert nur 
andersherum: Ist eine Sprache ledigglich FOR/LOOP mächtig und nicht TV, 
so kann Sie keine infiniten FOR enthalten.

: Bearbeitet durch User
von J. T. (chaoskind)


Lesenswert?

LBO schrieb:
> Ich finde den Thread toll:
> Überall anders wird befohlen, eine klare und ausführliche Beschreibung
> des Projekts abzugeben. Anschließend erfolgt der Verweis aufs
> Datenblatt, welches man gefälligst zu lesen hat - von vorn bis hinten.
>
> Dann kommt einmal ein Threadersteller der alles liefert, was sonst immer
> erfragt wird (sonst könne und wolle man nicht helfen). Die Antwort: Das
> ist mir zu lang, das lese ich nicht. Wenn der Fehler dann vom
> Threadersteller selber gefunden wird kommen alle aus ihren Löchern und
> haben die Weisheit mit Löffeln gefressen - toll!

Das dachte ich mir auch irgendwie. Aber das fällt ja in den letzten 1-2 
Jahren immer mehr auf, wie sehr die Qualität dieses Forums gelitten hat. 
Ein zwei Ausnahmen gibt es immer wieder mal, die tatsächlich versuchen 
zu helfen oder es sogar tun, aber das meiste ist doch nur 
"MeinSchwanzIsLängerAlsDeiner-Geblubber". Irgendwie traurig. Und damit 
werden dann auch fähige Leute vergrault. Karl-Heinz zb, der hat mir 
früher sehr gute Erklärungen und Ausführungen zu meinen Problemen 
liefern können. Von dem zb hab ich ewig nichts mehr gelesen. Schade 
drum.

Gamer schrieb:
> Lass den Code so! Du hast durch Zufall das echte Leben simuliert. :-)

:D :D :D  Das echte Leben hab ich aber so schon jeden Tag um mich. Da 
brauch ich keine Simulation mehr von. Oder leben wir etwa alle doch in 
einem Computer in ner Simulation? :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.