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
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
@Enne, der '$ {::}'? Teilzeichenfolge bearbeitet. gleiche Seite des Bash-Handbuchs. – ilkkachu
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. –