Die Programmiersprache Ruby (German Edition)
umkehrt.
# Dichten Code wie diesen zu schreiben ist wohl kein guter Coding-
# Stil, aber es demonstriert die Leistungs- und Ausdrucksfähigkeit
# der Sprache.
#
# Im Einzelnen funktioniert die Zeile unten wie folgt:
# (0..8).collect ruft den Code in den geschweiften Klammern neunmal
# auf -- je einmal pro Zeile -- und sammelt den Rückgabewert dieses
# Codes in einem Array. Der Code in den geschweiften Klammern nimmt
# ein Teil-Array des Gitters, das eine einzelne Zeile enthält, und
# packt seine Ziffern in einen String. Die Methode join() verbindet
# die Elemente des Arrays zu einem einzelnen String, getrennt durch
# Zeilenumbrüche. Schließlich übersetzt die Methode tr() die binäre
# String-Darstellung in ASCII-Ziffern.
(0..8).collect{|r| @grid[r*9,9].pack('c9')}.join("\n").tr(BIN,ASCII)
end
# Ein Duplikat des Puzzle-Objekts zurückgeben
# Diese Methode überschreibt Object.dup, um das Array @grid zu kopieren.
def dup
copy = super # Grundlegende Kopie durch Aufruf von Object.dup
@grid = @grid.dup # Neue Kopie der internen Daten erzeugen
copy # Kopiertes Objekt zurückgeben
end
# Wir überschreiben den Array-Zugriffsoperator, um den Zugriff auf die
# einzelnen Zellen eines Puzzles zu erlauben. Puzzles sind zwei-
# dimensional und müssen mit Zeilen- und Spaltenkoordinaten indexiert
# werden.
def [](row, col)
# Zweidimensionale (row,col)-Koordinaten in einen eindimensionalen
# Array-Index konvertieren und den Zellenwert bei diesem Index
# zurückgeben
@grid[row*9 + col]
end
# Diese Methode erlaubt die Verwendung des Array-Zugriffsoperators auf
# der linken Seite einer Zugriffsoperation. Sie setzt den Wert der
# Zelle bei (row, col) auf den Wert newvalue.
def []=(row, col, newvalue)
# Ausnahme auslösen, wenn der neue Wert nicht im Bereich 0 bis 9 liegt.
unless (0..9).include? newvalue
raise Invalid, "Illegaler Zellenwert"
end
# Das entsprechende Element des internen Arrays auf den Wert setzen
@grid[row*9 + col] = newvalue
end
# Dieses Array ordnet den Box-Nummern eindimensionale Gitterboxen zu.
# Es wird in der unten stehenden Methode verwendet. Der Name
# BoxOfIndex beginnt mit einem Großbuchstaben und ist daher eine
# Konstante. Außerdem wird das Array mit freeze "eingefroren", so dass
# es nicht mehr verändert werden kann.
BoxOfIndex = [
0,0,0,1,1,1,2,2,2,0,0,0,1,1,1,2,2,2,0,0,0,1,1,1,2,2,2,
3,3,3,4,4,4,5,5,5,3,3,3,4,4,4,5,5,5,3,3,3,4,4,4,5,5,5,
6,6,6,7,7,7,8,8,8,6,6,6,7,7,7,8,8,8,6,6,6,7,7,7,8,8,8
].freeze
# D iese Methode definiert ein benutzerdefiniertes Schleifenkonstrukt
# (einen "Iterator") für Sudoku-Puzzles. Für jede Zelle, deren Wert
# unbekannt ist, übergibt diese Methode mittels yield die Zeilen-,
# Spalten- und Boxnummer an den Block, der mit diesem Iterator
# verknüpft wird.
def each_unknown
0.upto 8 do |row| # Für jede Zeile
0.upto 8 do |col| # Für jede Spalte
index = row*9+col # Zellenindex für (row,col)
next if @grid[index] != 0 # Weiter, wenn Zellwert bekannt
box = BoxOfIndex[index] # Box für diese Zelle ermitteln
yield row, col, box # Den verknüpften Block aufrufen
end
end
end
# true zurückgeben, wenn irgendeine Zeile, Spalte oder Box Duplikate
# enthält. Andernfalls false zurückgeben. Duplikate in Zeilen, Spalten
# oder Boxen sind in Sudoku nicht erlaubt, so dass der Rückgabewert
# true bedeutet, dass das Puzzle ungültig ist.
def has_duplicates?
# uniq! gibt nil zurück, wenn alle Elemente in einem Array einmalig
# sind. Falls uniq! also etwas zurückgibt, enthält das
# Spielfeld Duplikate.
0.upto(8) {|row| return true if rowdigits(row).uniq! }
0.upto(8) {|col| return true if coldigits(col).uniq! }
0.upto(8) {|box| return true if boxdigits(box).uniq! }
false # Keine Duplikate, falls alle Tests bestanden wurden
end
# Array mit der Menge aller Sudoku-Ziffern. Wird unten verwendet.
AllDigits = [1, 2, 3, 4, 5, 6, 7, 8, 9].freeze
# Ein Array aller Werte zurückgeben, die in der Zelle (row,col)
# platziert werden könnten, ohne ein Duplikat in der Zeile, Spalte
# oder Box zu erzeugen. Beachten Sie, dass der Operator + bei Arrays
# Verknüpfungen durchführt, während der Operator - eine Differenz-
# mengenoperation durchführt.
def possible(row, col, box)
AllDigits - (rowdigits(row) + coldigits(col) + boxdigits(box))
end
private # Alle Methoden nach dieser Zeile sind privat für diese Klasse.
# Array aller bekannten Werte in der
Weitere Kostenlose Bücher