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:
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:
* 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
elseif((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.
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 ;-)
... sorry, aber kein Mensch liest im Posting hier den ellen langen
Programmcode (auch wenn der wahrscheinlich in deinen angehängten Dateien
noch einmal vorkommt)...
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
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.
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.
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.
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?
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 ;-)
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...
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.
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...
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.
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.
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 =)
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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!
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.
>> 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.
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.
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? :-)