前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
さぁ、解析処理を作っていくぞ。
例題として、こちらの問題を用意しました。
データを入力。
まず、ピクロス解法の定石パターンとして、確実に塗れるところから塗っていくというもの。
この例題からすると、
この赤い部分は全て塗れるのは、すぐに分かりますよね。
さらに、
ここも塗れるのは分かりますでしょうか。
例えば、[1,4,3]と合った場合は、
■×■■■■×■■■
と10マスが確定しますよね?
これを公式化すると、
数字の合計+(数字の数ー1)=マスの数
※1+4+3+(3-1) = 10
となった場合、その列または行の塗れるマスは自動的に確定します。
これを実装します。
// 解析パターンその1
private void pattern1()
{
// Row
pattern1Row();
// Col
pattern1Col();
}
/**
* Rowに対して解析パターン1を適用
*/
private void pattern1Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
int total = 0;
foreach (var v in rowlist)
{
total += v;
}
total += rowlist.Count - 1;
if (total == colNumbers.Count)
{
// 塗れるマス確定
// リストを反転コピー
List<int> revRowList = new List<int>();
foreach (var v in rowlist)
{
revRowList.Add(v);
}
revRowList.Reverse();
int col = 0;
foreach (var v in revRowList)
{
int c;
for (c = 0; c < v; c++)
{
_bitmapData[row, col + c].Paint();
}
if(col + c < colNumbers.Count)
{
_bitmapData[row, col + c].Mask();
c++;
}
col += c;
}
}
row++;
}
}
/**
* Colに対して解析パターン1を適用
*/
private void pattern1Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
int total = 0;
foreach (var v in collist)
{
total += v;
}
total += collist.Count - 1;
if (total == colNumbers.Count)
{
// 塗れるマス確定
// リストを反転コピー
List<int> revColList = new List<int>();
foreach (var v in collist)
{
revColList.Add(v);
}
revColList.Reverse();
int row = 0;
foreach (var v in revColList)
{
int r;
for (r = 0; r < v; r++)
{
_bitmapData[row + r, col].Paint();
}
if (row + r < rowNumbers.Count)
{
_bitmapData[row + r, col].Mask();
r++;
}
row += r;
}
}
col++;
}
}
列の数字データは右から順に並んでいるので、これを反転させる必要があります。
ただ、直接Reverse()を使用すると、インプットデータが壊れてしまうので、コピーを作成してからReverse()を使用します。
あとは、Listの先頭からピクロスのルールに従って塗っていきます。
実行結果はこうなりました。
解析がしやすくなるように、塗れないマスは×を表示するようにしました。
まぁ、ここまでは順調ですな。