このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
さて、PuzzleSolver はテスト仕様であり、
今までは縦横のヒントを一度実行するだけだった。
このままでは、一度行列のスキャンを行うだけで、
PuzzleSolver や PuzzleLine などのオブジェクトが
解体されてしまい、昨日作った進捗管理が意味を成さない。
そこでこれを改造し、PuzzleSolver の Solve 呼び出しで、
一気に答えが出るところまでもっていこう。
中には、これらのアルゴリズムで解けない問題もあるため、
終了条件としては、1 セルも解けなくなるか、
エラー(矛盾)が発生するまでということにしよう。
Solve メソッドは、ユーザの呼び出しインタフェースなので、
矛盾が生じた場合には、戻り値などで返すのではなく、
エラーを発生させて通知するほうが好ましい。
ということで、まずはエラーコードを定義しよう。
VB のエラーは、COM で HRESULT と呼ばれる定数に該当し、
カスタムエラーを定義する場合、
vbObjectError という定数以降を使う必要がある。
vbObjectError は、&H80040000 の値である。
詳しくは述べないが、HRESULT のエラーは、
上位 16 ビットは意味が決まっており、
下位 16 ビットを自由に使うことができる。
ほかのアプリケーションとのバッティングを防ぎたいので、
アプリが使用するエラーは、中途半端な場所からにしよう。
Private Const ERROR_STATUS_BASE = vbObjectError Or &H7700
では、エラー定数を定義しよう。
Public Enum LogicPuzzleErrorConstants
NONOGRAM_E_BADFORMAT = ERROR_STATUS_BASE
NONOGRAM_E_INCONSISTENT = ERROR_STATUS_BASE + 1
End Enum
変わった名前のつけ方ではあるが、
これは、HRESULT の定数の命名規則に準じている。
ついでに、エラーメッセージも定義しておこう。
Private Const ERRMSG_NONOGRAM_E_INCONSISTENT = _
"塗り潰しパターンとヒントの数値が矛盾しています。"
よし、Solve メソッドを実装しよう。
Public Sub Solve()
Dim c As Long
Dim r As Long
Dim lTotal As Long
Dim lResult As Long
Do
lTotal = 0
For c = 0 To m_oAnswer.Width - 1
lResult = m_oColumns(c).Solve()
If lResult = -1 Then
Call Err.Raise(NONOGRAM_E_INCONSISTENT, _
, ERRMSG_NONOGRAM_E_INCONSISTENT)
End If
lTotal = lTotal + lResult
Next
For r = 0 To m_oAnswer.Height - 1
lResult = m_oRows(r).Solve()
If lResult = -1 Then
Call Err.Raise(NONOGRAM_E_INCONSISTENT, _
, ERRMSG_NONOGRAM_E_INCONSISTENT)
End If
lTotal = lTotal + lResult
Next
Loop While lTotal > 0
End Sub
全体をループで挟み、
行列の精査で解答を得られたセル数を合計、
合計が 0 であればこれ以上進まないので終了だ。
もし、行の Solve で -1 が返れば矛盾が発生したので、
Err.Raise() を使って、エラーを発生させる。
Err.Raise の第 3 引数は説明文だ。
名前つき引数を使ってもいいのだが、
個人的に嫌いなので、第 2 引数を省略することで書く。
よし、ではこれで実行してみよう。
解答欄を選択してクリアし、F8 でマクロを実行する。
一発で答えが画面に表示された。
これが難しい問題であれば、おそらく一部だけか、
あるいはまったく解けない状態でとまるはずだ。
例えば、以下の「参」の文字だが、
この問題、実は重解となっているため、
どうしても途中までしか確定できない。
これを実行すれば、途中までの解等が表示された。
http://img1.mixi.jp/photo/bbs_comm/28/98/72122898_45.jpg
後は、最初の問題にもどり、
明らかに矛盾している解答状態にした上でマクロを実行。
----------------------------------------------
実行時エラー'-2147191039 (80047701)':
塗り潰しパターンとヒントの数値が矛盾しています。
----------------------------------------------
よし、エラーが出た。
しかし、エラー処理をしていないため、
ユーザにとっては迷惑なダイアログではある。
とりあえずは良好に動いているようだ。