Erstellt: 12. Mai 2013 (zuletzt geändert: 1. November 2021)

Puzzle 006

Puzzleteile „mischen“

C64 Studio

Da wir jetzt endlich die Puzzleteile zeichnen können, wollen wir nun zu Beginn auch die Reihenfolge der Teile zufällig festlegen. Dazu müssen wir natürlich erstmal klären, wie man überhaupt Zufallszahlen unter Assembler erzeugt, schließlich gibt es bei den Mnemonics kein RND(), wie im C64-BASIC.

Schaut euch bitte den Beitrag Zufallszahlen in Assembler an, bevor ihr hier weiter lest!!

Da ihr nun fit im Erzeugen von Zufallszahlen seid, wenden wir das Gelernte gleich mal bei unserem Puzzlespiel an.

Das Mischen einbauen

Wir werden nun einfach alle acht Puzzleteile auf die neun möglichen Felder verteilen. Dazu verwenden wir die TIMER-Zufallsroutine aus dem eingangs erwähnten Beitrag und fügen die folgenden Zeilen vor showScreen_Title in unser Programm ein.

;*******************************************************************************
;*** Zufallszahl per Timer-Verknüpfungen bilden.
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: Zufallszahl im Akku
;*******************************************************************************
;*** ändert  : A, SR
;*******************************************************************************
!zone rndTimer
rndTimer
 lda $dc04                          ;Low-Byte  von Timer A aus dem CIA-1
 eor $dc05                          ;High-Byte von Timer A aus dem CIA-1
 eor $dd04                          ;Low-Byte  von Timer A aus dem CIA-2
 adc $dd05                          ;High-Byte von Timer A aus dem CIA-2
 eor $dd06                          ;Low-Byte  von Timer B aus dem CIA-2
 eor $dd07                          ;High-Byte von Timer B aus dem CIA-2
 rts

Jetzt werden wir unsere acht Puzzleteile auf die neun verfügbaren Felder verteilen. Fügt die Funktion direkt vor der von eben ein.

;*******************************************************************************
;*** Die Puzzleteile zufällig verteilen
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: Neue Position der Puzzleteile in der Tabelle tileOrder
;*******************************************************************************
;*** ändert  : A, X, Y, SR
;*******************************************************************************
!zone shuffleTiles
shuffleTiles
 ldy #$08                           ;alle 9 Felder
 lda #$ff                           ;als leer markieren
.loop
 sta tileOrder,Y                    ;$ff in jedes Feld schreiben
 dey
 bpl .loop
 ldx #$07                           ;die 8 Puzzleteile platzieren
.loop1
 jsr rndTimer                       ;Zufallszahl holen
 and #%00001111                     ;wir brauchen nur 0-8, also unteres Nibble
 cmp #$09                           ;ist die Zufallszahl größer als 8?
 bcs .loop1                         ;wenn ja, eine neue holen
 tay                                ;Zufallszahl ins Y-Register (Feld-Pos.)
 lda tileOrder,Y                    ;Feld laden
 bpl .loop1                         ;ist es nicht mehr frei ($ff), neue Zahl
 txa                                ;sonst aktuelles Teil (X-Reg) -> Akku
 sta tileOrder,Y                    ;und bei tileorder: speichern
 dex                                ;nächstes Puzzleteil
 bpl .loop1                         ;solange noch eins da ist
 rts                                ;zurück

Am Anfang setzten wir erstmal alle Felder auf frei. Ihr erinnert euch? Der Wert $ff steht für das leere Feld. Anschließend benutzen wir das X-Register als Schleifenzähler für unsere 8 Puzzleteile und verteilen diese in der Schleife .loop1 auf die Felder.
Wir holen uns zunächst eine Zufallszahl per jsr rndTimer in den Akku. Diese legt fest, auf welchem Feld das aktuelle Puzzleteil (X-Register) landen soll. Da wir nur Zahlen von 0-8 (unsere Zählung beginnt wie so häufig bei 0!) benötigen, beschränken wir uns aufs untere Nibble. Dann kontrollieren, ob die Zahl kleiner als 9 ist, falls ja machen wir weiter, sonst holen wir uns eine neue Zufallszahl. Sobald wir eine gültige Zufallszahl haben, ab ins Y-Register damit. Nun müssen wir kontrollieren, ob das per Zufallszahl ermittelte Feld noch frei ist. Dazu einfach das Feld in den Akku holen und prüfen, ob der Wert positiv ist ($ff kennzeichnet ja ein freies Feld und dieser Wert ist negativ). Falls es bereits belegt ist, holen wir eine neue Zufallszahl, wenn aber nicht, dann speichern wir unser Puzzleteil aus dem X-Register in diesem Feld ab. Abschließend verringern wir das X-Register fürs nächste Puzzleteil und suchen für dieses ein freies Feld, bis alle Teile platziert sind.

Jetzt müssen wir die Funktion natürlich noch aufrufen. Fügt in puzzleMain vor der Zeile jsr loadSprites, einfach diese Zeile ein:

 jsr shuffleTiles                   ;Das Puzzle mischen

Das war es schon alles.
Jetzt sollten die Puzzleteile bei jedem Start eine andere Position einnehmen.

OK ein / zwei Kleinigkeit fehlen eigentlich noch! Es könnte nun ja passieren, dass das Puzzle auch per Zufallsgenerator gleich gelöst wird, sprich alle Teile sind am richtigen Platz. Wir sollten uns auch noch fragen, ob das Puzzle wirklich immer lösbar ist, wenn wir die Teile reinzufällig setzen? Darum kümmern wir uns ein anderes Mal.


Auf dem D64-Image im Download findet ihr neben der hier entworfenen Version, auch noch ein „LOVE FAST“, das zeigt, wie flott alles läuft, obwohl wir bisher keinen Wert auf optimierte Abläufe gelegt haben. Außerdem gibt es dort ein „LOVE KEY“, das erst nach einem Tastendruck alles erneut durchmischt. Im herunterladbaren Projekt findet ihr am Anfang des Quellkodes, die zwei auskommentierten Konstanten FAST und KEY, mit denen ihr diese Funktionen aktivieren könnt.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (5 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


ZurückWeiter

2 Gedanken zu „Puzzle 006“

  1. Hier ist leider im zweiten Codebeispiel die falsche Funktion reingerutscht…

    Das Problem konnte ich aber gut durch deinen runterladbaren Quelltext beheben, da ja da auch alles drin ist. :0D

    Ich hoffe wirklich, dass irgendwann wieder neue Beiträge von dir kommen.. Ich hab schon leicht bammel, ab der Stelle, wo ich neue Sachen durch stundenlanges Suchen im Netz, lernen muss…
    Geht zwar auch, aber dein Tutorial ist wirklich gut geschrieben und immer wieder mit richtig guten Erklärungen und Hintergrundinfos gespickt, darauf möchte ich eigentlich nicht verzichten…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Protected by WP Anti Spam