2006 年 5 月 27 日 23 時 35 分

PuzzleLine #3: 空白確定の実装


このアーカイブは同期化されません。 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

の直前に追加すれば、空白部分も確定できるはずだ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.