2006 年 5 月 11 日 18 時 27 分

PuzzleSheetLoader #3: セルを徘徊


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


ヒントは列や行によって数が異なるため、
単純に特定範囲という風に決めることができない。
セルを順番に調べていく必要がある。

しかしながらルールがなければ読み込みはできないので、
まずはヒントのあり方についてルールを決めよう。
雑誌を見てみると、大体がこの法則に従っている。

●行のヒントについて
・各行の解答欄と同じ行の左側のセルに入力される
・行には必ず 1 つ以上のヒント数値がある。
・常に右寄せで入力され、
 解答欄の左の隣接したセルには必ず数値が入る。

●列のヒントについて
・各列の解答欄と同じ行の上側のセルに入力される
・列には必ず 1 つ以上のヒント数値がある。
・常に下寄せで入力され、
 解答欄の上の隣接したセルには必ず数値が入る。

では行ヒントについて考えてみよう。やることは次の通り。

1. 行の解答欄の範囲に隣接する左のセルを取得する
2. セルの値を調べ、数値ならそれをヒントとする
3. 更に左のセルを調べて上記を繰り返す
4. 空のセルがみつかればそこで検索を止める
5. 見つけたヒントを最後の方から並べて返却する

結構複雑になりそうだ。

では実装する。今回は引数や論理エラーチェックは省こう。
これらを書けばかなりコードが大きくなるのでやめておく。

本来は、インデックス範囲チェックとか、
数値の有効性とか、セル範囲とか色々調べる必要はあるが、
それらが目的ではないため、今回はざっくり削る。

    Public Property Get RowHints(ByVal Index As Long) As ArrayList
        Dim c As Range
        Dim oHints As ArrayList

        Set oHints = New ArrayList

        ' 解答欄に隣接する、最も右のヒントセルに移動
        Set c = m_oAnswerRange(Index + 1, 0)

        ' セルに値がある限り繰り返す
        Do Until IsEmpty(c.Value)

            ' ヒントを最初に追加
            Call oHints.Insert(0, CLng(c.Value))

            ' 左端セルなら抜ける
            If c.Column = 1 Then Exit Do

            ' 一つ左に移動
            Set c = c(1, 0)
        Loop
   
        Set RowHints = oHints
    End Property

まず、行の位置はプロパティの引数 Index で渡される。
解答欄の範囲に隣接する左のセルは、
Range クラスの既定プロパティを使って、
解答欄のセル範囲から割り出すことができる。

Range は、1 ベースの位置なので、行位置は Index + 1。
今回取得したいセルは解答欄のセル範囲の外だが、
列位置に 0 を指定することで、範囲外でも取得できる。
Range クラスは非常に柔軟だ。

m_oAnswerRange(Index + 1, 0)

セルの値は、Value プロパティで取れる。
値があるかどうかは、機能と同じく IsEmpty 関数で調べる。
空でなければループだ。

セル値があればヒントとみなし、CLng 関数をつかって
強制的に Long 整数値に置き換えよう。
ヒントは、ArrayList に入れるときに、
先頭に挿入すれば、後で並べ替える必要がない。

すぐ左隣のセルの取得は、先ほどと同じように
既定プロパティを使って (1, 0) で取得できる。

ただ、ヒントがシートの左端までびっしり書かれていると
範囲外のセルを取得しようとしてエラーになるので、
シートの左端のセルに到達したかどうか調べる。
セルの列位置は、Column プロパティで取得できる。
これも 1 ベースだ。
(Columns プロパティもあるので紛らわしい)

If c.Column = 1 Then Exit Do   

こんな感じかな。列は、行とほぼ同じように書けるはず。
セルの行位置は、想像通り Row プロパティで取得できる。

Range クラスは複雑ではあるが、
実際に使うプロパティはそれほど多くはない。



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