2017-11-25 8 views
0

Ich versuche zu verstehen this Implementierung von Tetris.Brauchen Sie Hilfe, diese Implementierung von Tetris zu verstehen

Ich habe ein paar Fragen.

In update_score Funktion

if ((score > LEVEL_UP * level)) ; then   # if level should be increased 
    ((level++))         # increment level 
    pkill -SIGUSR1 -f "/bin/bash $0" 

Was ist die Verwendung von überhaupt einen separaten Prozess mit der Verzögerung zur Einstellung? Warum verwenden Sie SIGUSR1 und SIGUSR2?

Warum in der Funktion draw_piece mit 8 multiplizieren? Ich verstehe nicht, wie die Konvertierung stattfindet oder wie der Begriff "Rotation" hier umgesetzt wird.

for ((i = 0; i < 8; i += 2)) { 
    # relative coordinates are retrieved based on orientation and added to absolute coordinates 
    ((x = $1 + ${piece[$3]:$((i + $4 * 8 + 1)):1} * 2)) 
    ((y = $2 + ${piece[$3]:$((i + $4 * 8)):1})) 
    xyprint $x $y "$5" 

    ... 
} 

Noch verstehe ich die Syntax mit: hier.

In clear_next, warum ist draw_next ${filled_cell//?/ } anstelle von nur ${filled_cell} erforderlich? Was bedeutet die //?

Antwort

3

Ich bin ein Anfänger-Scripting und Programmierung im Allgemeinen zu schälen, und ich habe versucht worden, diese Implementierung von Tetris [in der Schale] zu verstehen

Irgendwie vermute ich Sie leichter haben könnten gefunden Programme für den Anfang.

Wozu dient ein separater Prozess zum Einstellen der Verzögerung? Warum verwenden Sie [SIGUSR1] und [SIGUSR2]?

Ich glaube nicht, es gibt einen separaten Prozess für die Verzögerung einzustellen, aber für den Timer zu implementieren. Der Timer muss laufen, auch wenn das Programm auf die Eingabe des Players wartet. Wenn die Shell-Funktionen keine Möglichkeit bieten, ein Timeout für read zu haben, muss das in einen anderen Prozess exportiert werden. Also dann bekommen Sie, was es am Ende des Skripts ist, eine Kluft in den Timer, die Benutzereingabe-Handler und die eigentliche Spiellogik, mit Ausgabe der ersten beide gehen in den letzten:

(ticker & reader) | (controller) 

Bash read hat die -t Flag für Timeout, also wenn es in Bash implementiert wurde, benötigen Sie möglicherweise nicht den zusätzlichen Timer-Prozess. Wenn der Timer jedoch in einen externen Prozess versetzt wird, ist er auch unabhängig von der Benutzereingabe. Das Zeitlimit read wird stattdessen jedes Mal zurückgesetzt, wenn der Benutzer auf eine Schaltfläche klickt. Um dies zu umgehen, müsste man die verstrichene Zeit genau bestimmen (oder ein sehr kurzes Timeout auf read verwenden und die Ticks zählen).

SIGUSR1 und SIGUSR2 sind nur „unschuldig“ Signale, die im Allgemeinen keine Bedeutung auf das System haben, so können sie hier verwendet werden. Natürlich könntest du andere benutzen, aber das Auffangen von SIGINT oder SIGHUP würde die Benutzer verärgern, wenn sie das Spiel beenden wollten.

Warum in der Funktion draw_piece mit 8 multiplizieren?

((x = $1 + ${piece[$3]:$((i + $4 * 8 + 1)):1} * 2)) 

Die piece Array enthält die verschiedenen Formen und Ausrichtungen der Teile. Ein Stück ist 4 Quadrate groß, jedes Quadrat benötigt zwei Koordinaten, also erhalten wir 8 Zahlen pro Stück/Orientierung. Denn Beispiel ist die Zeichenfolge für das S Stück 0001111201101120, so hat es zwei Ausrichtungen:

yx yx yx yx yx yx yx yx 
00 01 11 12 01 10 11 20 

Und das Stück sieht ungefähr so ​​aus:

012  012 
0 xx. 0 .x. 
1 .xx 1 xx. 
2 ... 2 x.. 

Die ${variable:position:length} Notation nimmt einen Teilstring aus dem gegebenen Variable, so erhält das Programm die einzelnen Ziffern aus der größeren Zeichenfolge. Das ist eine etwas seltsame Art, ein Array zu implementieren.

In clear_next, warum ist draw_next ${filled_cell//?/ } notwendig ...? Was bedeutet die //?

Das ${parameter/foo/bar} Konstrukt ist ein Muster, Ersatz (siehe zum Beispiel Bash's manual on parameter expansion, suchen Sie nach "ersetzen"). Was immer foo im Wert von parameter entspricht, wird durch bar ersetzt und das Ergebnis wird erweitert. Mit einem doppelten Schrägstrich werden alle Übereinstimmungen ersetzt, mit einem einzigen Schrägstrich, nur der erste. Das Fragezeichen entspricht einem beliebigen Zeichen wie beim Dateinamen globs, so dass effektiv eine Zeichenfolge aus Leerzeichen so lange wie die ursprüngliche Zeichenfolge erstellt wird.

Zum Beispiel:

$ str="hallo hallo" 
$ echo "${str/a/e}" 
hello hallo 
$ echo "${str//a/e}" 
hello hello 
$ str="abc" 
$ echo "x${str//?/ }x" 
x x 
+0

Dank! Können Sie die Syntax der Anweisung erklären, die Folgendes beinhaltet: Wo versucht sie die Koordinaten zuzuweisen? Das scheint ein häufiges Element im Programm zu sein, und ich kann es nicht im Sinne von if-else interpretieren – Enne

+0

@Enne, der '$ {::}'? Teilzeichenfolge bearbeitet. gleiche Seite des Bash-Handbuchs. – ilkkachu

+0

Das Ausführen des Timers in einem separaten Prozess ist wenig sinnvoll, da der Trap-Handler nicht ausgeführt wird, bevor der 'read'-Befehl zurückgegeben wird. Aber ich gebe zu, dass Shells anders als 'bash' das anders handhaben können. –

Verwandte Themen