このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
空白の確定に関する考え方は
塗り潰しの確定と同じということが分かった。
これを実装する場合、PuzzleLine の
SolveLine メソッドに追加するのが最も自然だ。
塗り潰しセルを確定するコードの後に追加しよう。
少しややこしいのは、前詰めと後ろ詰めの位置だ。
lStarts と lEnds という配列には、
後ろ詰めでの塗り潰し部分の開始位置、
前詰めでの塗り潰し部分の終端位置が格納されている。
これは、塗り潰しの確定位置を求めるには都合よかったが、
空白の確定位置を求めるには面倒だ。
必要なのは、後ろ詰めでの空白部分の開始位置と、
前詰めでの空白部分の終端位置である。
ではどうやって求めるか考えてみよう。
昨日の例を挙げよう。
.0..1..2..3..4..5..6..7..8..9.101112
◇□◆■○○●●■△□△△(前詰め)
.0..1..2..3..4..5..6..7..8..9.101112
◇□◇■◆○○●■●□△△(後ろ詰め)
この場合、Hints は、2, 3、
lEnds は、3, 8、lStarts は、3, 7 だ。
最初の空白(◇)は、最初の塗り潰し部分の前である。
もし存在した場合、最初の空白は行の最初から始まるので、
後ろ詰めでの空白部分の開始位置は、必ず 0 になるはずだ。
前詰めでの空白部分の終端位置は、
最初の塗り潰し部分の終端位置から計算し、
lEnds(0) - Hints(0) となる。
途中の空白(○)に関しては、
後ろ詰めでの空白部分の開始位置は、
直前の塗り潰し部分の開始位置から計算し、
lStarts(0) + Hints(0) となる。
同様に、前詰めでの空白部分の終端位置は、
直後の塗り潰し部分の終端位置から計算し、
lEnds(1) - Hints(1) となる。
最後の空白(△)は、最後の塗り潰し部分の後ろである。
後ろ詰めでの空白部分の開始位置は、
直前の塗り潰し部分の開始位置から計算し、
lStarts(1) + Hints(1) となる。1 は、Hints.Count - 1 だ。
もし存在した場合、最後の空白は行の最初から始まるので、
前詰めでの空白部分の終端位置は、必ず 12 になるはずだ。
これは、行の最後のインデックスとなる。
では、これを踏まえて実装してみよう。
' 重複する空白セルを確定する
' 最初の空白(存在しない場合もある)
For c = 0 To lEnds(0) - Hints(0)
If States(c) = CELL_UNSOLVED Then
States(c) = CELL_CHECKED
lDecided = lDecided + 1
End If
Next
' 塗り潰し部分の間の空白
For h = 0 To Hints.Count - 2
For c = lStarts(h) + Hints(h) To lEnds(h + 1) - Hints(h + 1)
If States(c) = CELL_UNSOLVED Then
States(c) = CELL_CHECKED
lDecided = lDecided + 1
End If
Next
Next
' 最後の空白(存在しない場合もある)
For c = lStarts(Hints.Count - 1) + Hints(Hints.Count - 1) To UBound(States)
If States(c) = CELL_UNSOLVED Then
States(c) = CELL_CHECKED
lDecided = lDecided + 1
End If
Next
これを、
SolveLine = lDecided
End Function
の直前に追加すれば、空白部分も確定できるはずだ。