前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
次は、ここを攻めていきます。
この赤い部分、すでに塗られているマスから、開いているマスは全て塗ることができないことが分かると思います。
これを処理していきましょう。
パターン2では塗られていないマスを数えましたが、パターン3では塗られているマスを数えます。
コードはパターン2と似ていますが、条件が変わっています。
// 解析パターンその3
// すでに塗りつぶされたマスからマスクをする
private void pattern3()
{
// Row
pattern3Row();
// Col
pattern3Col();
}
private void pattern3Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
// 塗ったマスを数える
int col = 0;
int count = 0;
List<int> countList = new List<int>();
while (col < colNumbers.Count)
{
if (_bitmapData[row, col].IsPainted())
{
count++;
}
else
{
if (count != 0)
{
countList.Add(count);
count = 0;
}
}
col++;
if (col == colNumbers.Count)
{
if (count != 0)
{
countList.Add(count);
}
}
}
// 数えた数字が全て一致すれば確定とする
bool result = true;
if (rowlist.AnalyzeDatas.Count != countList.Count)
{
row++;
continue;
}
for (int i = 0; i < countList.Count; i++)
{
if (rowlist.AnalyzeDatas[i].Value != countList[i])
{
result = false;
}
}
if (result)
{
// 開いているところをマスクする
col = 0;
while (col < colNumbers.Count)
{
if (_bitmapData[row, col].IsValid() == false)
{
_bitmapData[row, col].Mask();
}
col++;
}
rowlist.Analyzed();
}
row++;
}
}
private void pattern3Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
// 塗ったマスを数える
int row = 0;
int count = 0;
List<int> countList = new List<int>();
while (row < rowNumbers.Count)
{
if (_bitmapData[row, col].IsPainted())
{
count++;
}
else
{
if (count != 0)
{
countList.Add(count);
count = 0;
}
}
row++;
if (row == rowNumbers.Count)
{
if(count != 0)
{
countList.Add(count);
}
}
}
// 数えた数字が全て一致すれば確定とする
bool result = true;
if (collist.AnalyzeDatas.Count != countList.Count)
{
col++;
continue;
}
countList.Reverse();
for (int i = 0; i < countList.Count; i++)
{
if (collist.AnalyzeDatas[i].Value != countList[i])
{
result = false;
}
}
if (result)
{
// 開いているところをマスクする
row = 0;
while (row < rowNumbers.Count)
{
if (_bitmapData[row, col].IsValid() == false)
{
_bitmapData[row, col].Mask();
}
row++;
}
collist.Analyzed();
}
col++;
}
}
実行結果はこちら。
ここまで来たら、パターン2とパターン3の繰り返しで全て塗れるのでは無いでしょうか?
では、パターン2とパターン3をループ処理させるのに、終了条件を判定する処理を作成します。
private bool checkPainedCount()
{
int newPaintedCount = 0;
for (int row = 0; row < rowNumbers.Count; row++)
{
for(int col = 0; col < colNumbers.Count; col++)
{
if(_bitmapData[row, col].IsValid())
{
newPaintedCount++;
}
}
}
if(oldPaintedCount == newPaintedCount)
{
return false;
}
oldPaintedCount = newPaintedCount;
return true;
}
考え方は、全てのマスが確定したかを判定し、その数を数えます。
ループ前とループ後のカウント数を比較し、変化があればカウント数を更新、変化が無ければループを終了します。
public BitmapData[,] Run()
{
pattern1();
while (checkPainedCount())
{
pattern2();
pattern3();
}
return _bitmapData;
}
実行結果はこうなりました。
これは・・・黒電話かな?
解けたようです。
まだ完全ではないですが、簡単な問題ならこれで解けそうです。