Hallo zusammen, ich arbeite an einem TicTacToe-Spiel für unsere Projektarbeit und habe eine kurze Frage. Wenn man mitten in einem Spiel das Spiel abbrechen möchte, drückt der Spieler einen Taster und ein Interrupt wird ausgelöst. Nun wird der Interrupt ausgelöst und eine Prozedur wird ausgeführt, z.B. Spielfeld leeren, neuen Anfangsspieler bestimmen, etc. Wie schaffe ich es, dass nach dem Reset das Programm nicht dort weiter ausgeführt wird wo der Interrupt stattgefunden hat sondern z.B. am Anfang der main-Methode? oder ist dieses nur mit unsinnigen Methoden möglich? Habe ja schon gesucht und auch was über SRAM-Manipulierung gelesen, aber das möchte ich dann doch nicht. Wenn es keine vernünftige Lösung gibt, dann fall ich auf den Fall zurück, dass das Feld nur dann resettet werden darf, wenn schon jemand gewonnen hat und man somit an keine unschöne Stelle (KI-Algorithmus) zurückspringt. Vielen Dank für das Helfen
Wie wärs mit den Hardware Reset, den eigentlich jeder µC hat? Mfg
Darüber habe ich natürlich auch schon nachgedacht, nur dann kann ich nicht die gesamten Spielrunden zählen lassen bzw. den Spieler immer wechseln lassen, da der µC ja alle Einstellungen von neuem lädt.
einfach ein flag setzen und dann in den ensprechendne routingen abfragen
if (ende) {
return;
};
Hallo Peter II, das kann durchaus eine Lösung sein, nur was mache ich, wenn der Controller mitten in einer Zugberechnung ist und diese sagen wir mal noch 4 Sekunden dauert (über Sinn und Unsinn dieser Berechnung kann man sich streiten, nur meinte mein Lehrer, ich sollte einen Algorithmus implementieren => MiniMax)? Für diesen Fall finde ich die Lösung etwas unangebracht.
> oder ist dieses nur mit unsinnigen Methoden möglich?
Ich würde mal sagen, deine ganze VOrgehensweise mit Spielfeld resetten
im Interrupt ist schon Unsinn genug.
Mach es richtig. Und das beginnt schon mal damit, dass man
Tasterauswertung nicht mittels Interrupt machen muss/soll. Wenn aber
Interrupt, dann registriert der Interrupt den Tastendruck, tut selbst
aber nichts weiter. Die Auswertung, was dieser Tastendruck zu bedeuten
hat, geschieht an einer ganz anderen Stelle, nämlich in der
Hauptschleife.
> mitten in einer Zugberechnung ist und diese sagen wir mal > noch 4 Sekunden dauert Auch die Zugberechnung kann ab und an überprüfen, ob vom Benutzer ein Abbruch gefordert wurde, hinter sich aufräumen und zurückkehren. (*) das Aufräumen ist nämlich mit einer der wichtigen Gründe, warum du nicht einfach mit einem Interrupt alles abwürgen kannst!
Marco M. schrieb: > das kann durchaus eine Lösung sein, nur was mache ich, wenn der > Controller mitten in einer Zugberechnung ist und diese sagen wir mal > noch 4 Sekunden dauert dann mach die Abfrage in die Zugberechnung rein.
Marco M. schrieb: > da der µC ja alle Einstellungen von neuem lädt. Das ist wohl ein Design-Fehler. Du musst dir einfach einteilen, welche Daten dauerhaft gespeichert werden und welche bei jedem Start neu initialisiert, dann verschwindet das Problem und du musst zum Spielende bloss zum Programmstart springen: da wird ja dann eh der Stack neu initialisiert usw., also ein sauberer Neuanfang, bloss die Dauer-Daten bleiben erhalten - für die musst du eine Löschroutine vorsehen, die der Benutzer nur aufruft, wenn er tatsächlich alle bisherigen Spiele vergessen will. Gruss Reinhard
Marco M. schrieb: > Wenn man mitten in einem Spiel das Spiel abbrechen möchte, drückt der > Spieler einen Taster und ein Interrupt wird ausgelöst. > > Nun wird der Interrupt ausgelöst und eine Prozedur wird ausgeführt, z.B. > Spielfeld leeren, neuen Anfangsspieler bestimmen, etc. Da ist schon das Problem. Das macht man nicht im Interrupt, das gehört ins Hauptprogramm. Im Interrupt wird nur ein Flag gesetzt um zu signalisieren, dass ein Spielabbruch gewünscht wurde. Dieses Flag muss das Hauptprogramm regelmäßig prüfen und dann entsprechend handeln. Wenn es nur darum geht, nicht über ein Dutzend Ebenen zurückkehren zu müssen und dementsprechend überall Abbruchbedingungen einzubauen, kann man sich auch mit setjmp()/longjmp() behelfen.
Andreas B. schrieb: > kann > man sich auch mit setjmp()/longjmp() behelfen. und wer macht dann den stack wieder leer?
Da liegt die einfachste Lösung ja schon auf der Hand, danke allen. Karl Heinz Buchegger schrieb: > Ich würde mal sagen, deine ganze VOrgehensweise mit Spielfeld resetten > im Interrupt ist schon Unsinn genug. Leider habe ich gerade mal ein halbes Jahr Schulerfahrung mit einem Mikrocontroller und dem seiner Programmierung oder besser seinen Gegebenheiten, was man lieber lassen sollte und wie man es besser macht. Wie genau würdest du denn die Sache lösen, dass man über einen Taster ein Spiel abbrechen kann oder liege ich dort schon im Ansatz falsch?
Marco M. schrieb: > Leider habe ich gerade mal ein halbes Jahr Schulerfahrung mit einem > Mikrocontroller und dem seiner Programmierung oder besser seinen > Gegebenheiten, was man lieber lassen sollte und wie man es besser macht. Das ist schon ok. Du bist nicht er einzige, der meint 'Tasten erfordern Interrupt'. > Wie genau würdest du denn die Sache lösen, dass man über einen Taster > ein Spiel abbrechen kann oder liege ich dort schon im Ansatz falsch? Tastenabfrage mit der bewährten Methode aus Entprellung und dann
1 | ...
|
2 | |
3 | int main() |
4 | {
|
5 | |
6 | ... initialisierungen |
7 | |
8 | InitGame(); |
9 | |
10 | while( 1 ) { |
11 | |
12 | if( resetRequested ) { |
13 | InitGame(); |
14 | resetRequested = FALSE; |
15 | }
|
16 | |
17 | if( activePlayer == Human ) { |
18 | let Human Player do his move |
19 | }
|
20 | |
21 | else
|
22 | let Computer calculate its move |
23 | }
|
24 | }
|
25 | |
26 | void let Computer calculate its move |
27 | {
|
28 | .....
|
29 | |
30 | irgendwelche Schleifen oder sonstiges |
31 | und zwischendurch immer wieder mal |
32 | |
33 | if( resetRequested ) |
34 | return; |
35 | |
36 | an Stellen an denen es keine Rechenzeit kostet |
37 | aber auch nicht zu weit auseinander, so dass sich |
38 | eine lange Verzögerung ergibt. |
39 | }
|
Peter II schrieb: >> man sich auch mit setjmp()/longjmp() behelfen. > > und wer macht dann den stack wieder leer? Was soll denn ein leerer Stack? Dann krachts doch beim Fortsetzen. longjmp() stellt natürlich den Stackpointer vom Aufruf von setjmp() wieder her.
Jetzt haben alle so schnell geschrieben, dass ich zig Beiträge außer Acht gelassen habe, also mal alle durchgehen. Reinhard Kern schrieb: > Das ist wohl ein Design-Fehler. Du musst dir einfach einteilen, welche > Daten dauerhaft gespeichert werden und welche bei jedem Start neu > initialisiert, dann verschwindet das Problem und du musst zum Spielende > bloss zum Programmstart springen: da wird ja dann eh der Stack neu > initialisiert usw., also ein sauberer Neuanfang, bloss die Dauer-Daten > bleiben erhalten In der Schule wurde uns gesagt, dass bei einem Hardwarereset der µC "quasi" zum Anfang springt (Adresse 0000). So genau haben wir das ganze nicht durchgenommen. Jedenfalls bin ich nun davon ausgegangen, dass bei einem Reset der Controller von vorne beginnt und somit alles ab Zeile 0 neu lädt. Wenn das falsch ist (ist es ja offensichtlich), sollte man mich bitte korrigieren bzw. eine gute Erklärung verlinken, wo ich neues erlernen kann. Andreas B. schrieb: > Da ist schon das Problem. Das macht man nicht im Interrupt, das gehört > ins Hauptprogramm. Danke. Wieder was neues gelernt. Peter II schrieb: > Andreas B. schrieb: >> kann >> man sich auch mit setjmp()/longjmp() behelfen. > > und wer macht dann den stack wieder leer? Das lasse ich lieber (: Karl Heinz Buchegger schrieb: > Tastenabfrage mit der bewährten Methode aus Entprellung Soll also heißen, dass ich den Taster mit der Methode aus Entprellung immer wieder testen lasse (am besten im Abstand von ca. 300ms, da dies die durchschnittliche Reaktionsfähigkeit einen Menschen ist) anstatt diesen auf einen Interrupt zu legen?
Marco M. schrieb: > In der Schule wurde uns gesagt, dass bei einem Hardwarereset der µC > "quasi" zum Anfang springt (Adresse 0000). So genau haben wir das ganze > nicht durchgenommen. Jedenfalls bin ich nun davon ausgegangen, dass bei > einem Reset der Controller von vorne beginnt und somit alles ab Zeile 0 > neu lädt. > Wenn das falsch ist (ist es ja offensichtlich), sollte man mich bitte > korrigieren bzw. eine gute Erklärung verlinken, wo ich neues erlernen > kann. Dein Denkfehler ist, dass du den Wunsch eines Benutzers, die aktuelle Berechnung bzw. das aktuelle Spiel abzubrechen, mit einem 'Reset des µC' gleichsetzt. Ein µC-Reset ist ein einschneidendes Ereignis für einen µC. Sowas wie ein Schlag mit dem Hammer auf den Hinterkopf, alle Lichter gehen aus und danach wird er als Baby wiedergeboren. Daher haben die meisten Geräte den Reset-Knopf wohlweislich so, dass man da nicht so leicht rankommt. Wenn dein Benutzer ein neues Spiel will, dann wird einfach die laufende Berechnung gestoppt, ein Grundzustand wieder hergestellt und von dem gehts weiter. Das ist aber kein Reset in dem Sinne, wie ein µC-Reset aufgefasst werden muss. Ein µC-Reset ist im Grunde ein 'Strom aus - Strom ein' ohne den Stromschalter tatsächlich anzufassen.
Marco M. schrieb: > Soll also heißen, dass ich den Taster mit der Methode aus > Entprellung immer wieder testen lasse (am besten im Abstand von ca. > 300ms Die letzte Methode, die mit dem Timer, macht das so alle 5 bis 10 Millisekunden. Das hört sich jetzt kurz an, ist es aber für einen µC nicht. In Prozent Rechenzeit ausgedrückt, bist du da weit unter 1% >, da dies die durchschnittliche Reaktionsfähigkeit einen Menschen > ist) anstatt diesen auf einen Interrupt zu legen? Ziel ist es, das Tastenprellen zu eliminieren. Der Mensch spielt da überhaupt keine Rolle. Aus Sicht eines µC bewegt sich ein Mensch in extremster Zeitlupe.
Karl Heinz Buchegger schrieb: > Die letzte Methode, die mit dem Timer, macht das so alle 5 bis 10 > Millisekunden. Das hört sich jetzt kurz an, ist es aber für einen µC > nicht. In Prozent Rechenzeit ausgedrückt, bist du da weit unter 1% Klar, das ist logisch... man merkt, dass ich noch nicht so lange mit der Materie arbeite. Karl Heinz Buchegger schrieb: > Ziel ist es, das Tastenprellen zu eliminieren. Der Mensch spielt da > überhaupt keine Rolle. Aus Sicht eines µC bewegt sich ein Mensch in > extremster Zeitlupe. extrem ist ja schon fast untertrieben ;)
Danke an alle, die sich die Mühe gemacht haben, mir zu helfen ! Ich denke, ich weiß nun, was ich zu tun habe.
Marco M. schrieb: >> überhaupt keine Rolle. Aus Sicht eines µC bewegt sich ein Mensch in >> extremster Zeitlupe. > > extrem ist ja schon fast untertrieben ;) :-) erinnert mich immer an die Zeit als Digitaluhren mit Stoppuhr Funktion aufkamen. Wer schafft es den Knopf 2 mal hintereinander am schnellsten zu Drücken. Ich erinnere mich da so an 15 Hunderstel Sekunden als ungefähres Minimum, schneller ging einfach nie. In dieser Zeit arbeitet ein 1Mhz getriebener AVR rund 120-tausend Befehle ab :-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.