今なら言える。
自粛警察くそくらえ!
札幌市では、非常事態宣言解除を受けて、感染症対策ができた店舗から夜のお店も通常営業に戻りつつあります。
このお店も、昨日から営業再開しました。
外で飲むのは一ヶ月半ぶりかな?
ぼっちに優しいのは、このお店、
タッチパネルで注文できるんです。
この生つくねが食べたかった。
このトング考えた人は天才だと思う。

前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
こちらの問題を解いてみました。

もちろん一発で解けるとは思っていませんでした。
しかし、ここまでハマるとは・・・
解析パターン5にバグがあって、
いろいろコードを書き換えながら試行錯誤していったんですが、
結局、コードと格闘すること5時間。

解けました。
大きな変更としては、解析済みの数字に対して、きちんと解析済みフラグを設定しましょう、ということで、
要するに、
縦の数字を埋めていったら、横の数字も出来上がっているにもかかわらず、解析済みフラグが立っていないケースがあって、それで動きがおかしくなっていたので、きちんと解析完了フラグを立てましょう、ということを入れました。
private void checkAnalyze()
{
checkAnalyzeRowBefore();
checkAnalyzeRowAfter();
checkAnalyzeColBefore();
checkAnalyzeColAfter();
}
private void checkAnalyzeRowBefore()
{
int row = 0;
foreach (var rowList in rowNumbers)
{
if (rowList.IsAnalyzed())
{
row++;
continue;
}
rowList.AnalyzeDatas.Reverse();
int rowIndex = 0;
foreach(var rowData in rowList.AnalyzeDatas)
{
if (rowData.IsAnalyzed())
{
rowIndex++;
}
else
{
break;
}
}
if (rowIndex == rowList.AnalyzeDatas.Count)
{
rowList.AnalyzeDatas.Reverse();
row++;
continue;
}
int painted = 0;
int count = 0;
for (int col = 0; col < colNumbers.Count; col++)
{
if (_bitmapData[row, col].IsPainted())
{
painted++;
}
else if (_bitmapData[row, col].IsMasked())
{
if(count == rowIndex)
{
if (rowList.AnalyzeDatas[rowIndex].Value == painted)
{
rowList.AnalyzeDatas[rowIndex].Analyzed();
rowList.CheckAnalyze();
}
}
else
{
count++;
}
}
else
{
rowList.AnalyzeDatas.Reverse();
row++;
break;
}
}
}
}
private void checkAnalyzeRowAfter()
{
int row = 0;
foreach (var rowList in rowNumbers)
{
if (rowList.IsAnalyzed())
{
row++;
continue;
}
int rowIndex = 0;
foreach (var rowData in rowList.AnalyzeDatas)
{
if (rowData.IsAnalyzed())
{
rowIndex++;
}
else
{
break;
}
}
if(rowIndex == rowList.AnalyzeDatas.Count)
{
row++;
continue;
}
int painted = 0;
int count = 0;
for (int col = colNumbers.Count - 1; col >= 0; col--)
{
if (_bitmapData[row, col].IsPainted())
{
painted++;
}
else if (_bitmapData[row, col].IsMasked())
{
if (count == rowIndex)
{
if (rowList.AnalyzeDatas[rowIndex].Value == painted)
{
rowList.AnalyzeDatas[rowIndex].Analyzed();
rowList.CheckAnalyze();
}
}
else
{
count++;
}
}
else
{
row++;
break;
}
}
}
}
private void checkAnalyzeColBefore()
{
int col = 0;
foreach (var colList in colNumbers)
{
if (colList.IsAnalyzed())
{
col++;
continue;
}
colList.AnalyzeDatas.Reverse();
int colIndex = 0;
foreach (var colData in colList.AnalyzeDatas)
{
if (colData.IsAnalyzed())
{
colIndex++;
}
else
{
break;
}
}
if (colIndex == colList.AnalyzeDatas.Count)
{
colList.AnalyzeDatas.Reverse();
col++;
continue;
}
int painted = 0;
int count = 0;
for (int row = 0; row < rowNumbers.Count; row++)
{
if (_bitmapData[row, col].IsPainted())
{
painted++;
}
else if (_bitmapData[row, col].IsMasked())
{
if (count == colIndex)
{
if (colList.AnalyzeDatas[colIndex].Value == painted)
{
colList.AnalyzeDatas[colIndex].Analyzed();
colList.CheckAnalyze();
}
}
else
{
count++;
}
}
else
{
colList.AnalyzeDatas.Reverse();
col++;
break;
}
}
}
}
private void checkAnalyzeColAfter()
{
int col = 0;
foreach (var colList in colNumbers)
{
if (colList.IsAnalyzed())
{
col++;
continue;
}
int colIndex = 0;
foreach (var colData in colList.AnalyzeDatas)
{
if (colData.IsAnalyzed())
{
colIndex++;
}
else
{
break;
}
}
if (colIndex == colList.AnalyzeDatas.Count)
{
col++;
continue;
}
int painted = 0;
int count = 0;
for (int row = rowNumbers.Count - 1; row >= 0; row--)
{
if (_bitmapData[row, col].IsPainted())
{
painted++;
}
else if (_bitmapData[row, col].IsMasked())
{
if (count == colIndex)
{
if (colList.AnalyzeDatas[colIndex].Value == painted)
{
colList.AnalyzeDatas[colIndex].Analyzed();
colList.CheckAnalyze();
}
}
else
{
count++;
}
}
else
{
col++;
break;
}
}
}
}
細かい所は、直接gitHubのコードを見て欲しく。
何より大変だったのは、既存部分を変更することにより、過去の問題が解けなくなる可能性もあり、その確認のため、過去問を引っ張り出してきたこと。
セーブ&ロード機能実装してて正解だったわ。
無かったら確実に発狂してる。
とはいえ、この作業に大半の時間を使ってしまったので、他の作業ができなかったので、今日は他の作業に取りかかろう。

前回の状況はこちら。
最新ソースはこちら
https://github.com/takishita2nd/diet-mng
さて、前回作成したダイアログから入力したデータをサーバ側に送って、データベースに保存します。
まずはPHP側から。
WebAPIを作成します。
class ApiController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->weightManagement = new WeightManagementRepository();
}
public function add(Request $request)
{
$param = $this->weightManagement->getParam();
$this->weightManagement->add([
$param[0] => date('Y-m-d H:i'),
$param[1] => $request->contents["weight"],
$param[2] => $request->contents["fat_rate"],
$param[3] => $request->contents["bmi"],
], Auth::user());
return response()->json();
}
}
class WeightManagementRepository
{
private $paramNames = ['datetime', 'weight', 'fat_rate', 'bmi'];
public function __construct()
{
}
public function add($param, $user)
{
$model = new WeightManagement();
foreach($this->paramNames as $name)
{
$model->$name = $param[$name];
}
$model->save();
$this->attachToUser($model, $user);
}
public function attachToUser($model, $user)
{
$model->users()->attach($user);
}
public function getParam()
{
return $this->paramNames;
}
}
class WeightManagement extends Model
{
public function users()
{
return $this->belongsToMany('App\User');
}
}
class User extends Authenticatable
{
public function WeightManagements()
{
return $this->belongsToMany('App\Model\WeightManagement');
}
}
Route::post('api/weight/add', 'Weight\ApiController@add');
これでAPIが完成。
次はVue.js側です。
<template>
<div>
<div id="overlay" v-show="show">
<div id="content">
<p v-if="error_flg == true" class="error">
<ui>
<li v-for="error in errors">{{ error }}</li>
</ui>
</p>
<table class="edit">
<tbody>
<tr>
<td>体重</td>
<td><input type="number" v-model="contents.weight" /></td>
</tr>
<tr>
<td>体脂肪</td>
<td><input type="number" v-model="contents.fat_rate" /></td>
</tr>
<tr>
<td>BMI</td>
<td><input type="number" v-model="contents.bmi" /></td>
</tr>
</tbody>
</table>
<p id="command">
<button @click="clickAdd">入力</button>
<button @click="closeModal">閉じる</button>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['show'],
data() {
return {
errors: [],
error_flg: [],
param: {},
contents: {
weight: "",
fat_rate: "",
bmi: "",
},
};
},
created: function() {
},
methods: {
clickAdd: function() {
var self = this;
this.param.contents = this.contents;
axios.post('api/weight/add', this.param).then(function(response){
self.clear();
self.closeModal();
}).catch(function(error){
self.error_flg = true;
self.errors = error.response.data.errors;
});
},
closeModal: function() {
this.$parent.showDialogContent = false;
},
clear: function() {
this.contents.weight = "";
this.contents.fat_rate = "";
this.contents.bmi = "";
this.error_flg = false;
this.errors = [];
}
}
}
</script>
contentsの各パラメータが入力ダイアログのinputの値と結びついています。
入力ボタンをクリックすると、contetsをparamに設定し、app/weight/addへPOSTリクエストを送信します。
応答が帰ってくると、ダイアログを閉じます。


うまくいっているようです。

前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
次は、ここに注目します。

数字が、2,6と並んでいます。
ということは、下の6の数字では、上3マス(数字の2マスとマスク分1マス)は絶対に塗ることはできません。
なので、6という数字については、上の3マスを除いた7マスの間で中心を塗る、解析パターン8と同じロジックが適用できます。
// 解析パターンその10
// 中央の塗った場所から、塗れない場所をマスクする(数字が2個の場合)
private void pattern10()
{
// Row
pattern10Row();
// Col
pattern10Col();
}
private void pattern10Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
// 有効な数字を取り出す
List<int> values = new List<int>();
foreach (var data in rowlist.AnalyzeDatas)
{
if (data.IsAnalyzed())
{
continue;
}
values.Add(data.Value);
}
if (values.Count != 2)
{
row++;
continue;
}
// 対象となるマスを抽出する
List<List<BitmapData>> bitmapLists = extractTargetBitmapListsCol(row);
if (bitmapLists.Count != 1)
{
row++;
continue;
}
// 塗られている場所を特定
int leftCol = colNumbers.Count;
int rightCol = 0;
bool painted = false;
foreach (var bitmap in bitmapLists[0])
{
if(bitmap.IsPainted())
{
leftCol = bitmap.Col;
painted = true;
}
else
{
if (painted)
{
rightCol = bitmap.Col;
break;
}
}
}
var bitmaplist = bitmapLists[0];
if(bitmaplist.Count <= 1)
{
row++;
continue;
}
// 塗る対象は右側か、左側か?
int bigValue = 0;
int smallValue = 0;
if (values[0] > values[1])
{
bigValue = values[0];
smallValue = values[1];
bitmaplist.RemoveRange(0, smallValue + 1);
}
else
{
bigValue = values[1];
smallValue = values[0];
bitmaplist.RemoveRange(bitmaplist.Count - (smallValue + 1), smallValue + 1);
}
paintCenter(bigValue, ref bitmaplist);
row++;
}
}
private void pattern10Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
// 有効な数字で一番大きいものを取り出す
List<int> values = new List<int>();
foreach (var data in collist.AnalyzeDatas)
{
if (data.IsAnalyzed())
{
continue;
}
values.Add(data.Value);
}
if (values.Count != 2)
{
col++;
continue;
}
// 対象となるマスを抽出する
List<List<BitmapData>> bitmapLists = extractTargetBitmapListsRow(col);
if (bitmapLists.Count != 1)
{
col++;
continue;
}
// 塗られている場所を特定
int topRow = rowNumbers.Count;
int downRow = 0;
bool painted = false;
foreach (var bitmap in bitmapLists[0])
{
if (bitmap.IsPainted())
{
topRow = bitmap.Row;
painted = true;
}
else
{
if (painted)
{
downRow = bitmap.Row;
break;
}
}
}
var bitmaplist = bitmapLists[0];
if (bitmaplist.Count <= 1)
{
col++;
continue;
}
// 塗る対象は右側か、左側か?
int bigValue = 0;
int smallValue = 0;
if (values[0] > values[1])
{
bigValue = values[0];
smallValue = values[1];
bitmaplist.RemoveRange(0, smallValue + 1);
}
else
{
bigValue = values[1];
smallValue = values[0];
bitmaplist.RemoveRange(bitmaplist.Count - (smallValue + 1), smallValue + 1);
}
paintCenter(bigValue, ref bitmaplist);
col++;
}
}
今回は数字が2個の場合で、数字が大きい方のみを対象としました。
パターン8、9、10で共通化できる処理があったので、サブルーチンで共通化しています。
private List<List<BitmapData>> extractTargetBitmapListsCol(int row)
{
List<List<BitmapData>> bitmapLists = new List<List<BitmapData>>();
List<BitmapData> bitmaplist = new List<BitmapData>();
for (int col = 0; col < colNumbers.Count; col++)
{
// マスクとマスクの間が全て塗られていたら、そこは対象としない
if (_bitmapData[row, col].IsMasked())
{
if (bitmaplist.Count != 0)
{
bool done = true;
foreach (var bitmap in bitmaplist)
{
if (bitmap.IsPainted() == false)
{
done = false;
}
}
if (done == false)
{
bitmapLists.Add(bitmaplist);
}
bitmaplist = new List<BitmapData>();
}
continue;
}
bitmaplist.Add(_bitmapData[row, col]);
}
if (bitmaplist.Count != 0)
{
bitmapLists.Add(bitmaplist);
}
return bitmapLists;
}
private List<List<BitmapData>> extractTargetBitmapListsRow(int col)
{
List<List<BitmapData>> bitmapLists = new List<List<BitmapData>>();
List<BitmapData> bitmaplist = new List<BitmapData>();
for (int row = 0; row < rowNumbers.Count; row++)
{
// マスクとマスクの間が全て塗られていたら、そこは対象としない
if (_bitmapData[row, col].IsMasked())
{
if (bitmaplist.Count != 0)
{
bool done = true;
foreach (var bitmap in bitmaplist)
{
if (bitmap.IsPainted() == false)
{
done = false;
}
}
if (done == false)
{
bitmapLists.Add(bitmaplist);
}
bitmaplist = new List<BitmapData>();
}
continue;
}
bitmaplist.Add(_bitmapData[row, col]);
}
if (bitmaplist.Count != 0)
{
bitmapLists.Add(bitmaplist);
}
return bitmapLists;
}
private void paintCenter(int value, ref List<BitmapData> bitmaps)
{
if (value < bitmaps.Count && value * 2 > bitmaps.Count)
{
int paintNum = value * 2 - bitmaps.Count;
int countMax = 0;
if (paintNum % 2 == 1)
{
countMax = paintNum / 2 + 1;
}
else
{
countMax = paintNum / 2;
}
for (int count = -paintNum / 2; count < countMax; count++)
{
bitmaps[bitmaps.Count / 2 + count].Paint();
}
}
}
実行結果はこうなりました。

これはウサギかな?

解けたようです。

前回の状況はこちら
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
クイック入力のダイアログの画面を作成します。
<template>
<div>
<div class="dashboard">
<div class="chart">
<canvas id="weight"></canvas>
</div>
<div class="command">
<ul>
<li><a @click="onClickInput">クイック入力</a></li>
<li><a href="">詳細</a></li>
</ul>
</div>
</div>
<div id="overlay" v-show="showDialogContent">
<div id="content">
<table class="edit">
<tbody>
<tr>
<td>体重</td>
<td><input type="number" /></td>
</tr>
<tr>
<td>体脂肪</td>
<td><input type="number" /></td>
</tr>
<tr>
<td>BMI</td>
<td><input type="number" /></td>
</tr>
</tbody>
</table>
<p id="command">
<button @click="closeModal">入力</button>
<button @click="closeModal">閉じる</button>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
showDialogContent: false,
};
},
created: function() {
},
methods: {
onClickInput: function() {
this.showDialogContent = true;
},
closeModal: function() {
this.showDialogContent = false;
}
}
}
</script>

ダイアログの部分は別コンポーネントにしたほうが良かったかも。
あとで直す。

前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
次はこの問題を解いてみます。

解析を実行するとこうなりました。

今回はここに注目します。

10×10の問題ですが、例えば行の数字が7の場合、すでに真ん中の5マスが塗られているので、一番左の1マスは塗ることができないのが分かります。
同じ理由で、行の数字が6ならば、左2マスが塗ることができません。
なので、ここをマスクしちゃいましょう。
今回は条件を簡潔にしたいので、数字が1個の場合で、塗られている部分も1かたまりになっている場合のみとします。
// 解析パターンその9
// 中央の塗った場所から、塗れない場所をマスクする
private void pattern9()
{
// Row
pattern9Row();
// Col
pattern9Col();
}
private void pattern9Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
// 有効な数字で一番大きいものを取り出す
if(rowlist.AnalyzeDatas.Count != 1)
{
row++;
continue;
}
int value = rowlist.AnalyzeDatas[0].Value;
// 対象となるマスを抽出する
List<List<BitmapData>> bitmapLists = new List<List<BitmapData>>();
List<BitmapData> bitmaplist = new List<BitmapData>();
for (int col = 0; col < colNumbers.Count; col++)
{
// マスクとマスクの間が全て塗られていたら、そこは対象としない
if (_bitmapData[row, col].IsMasked())
{
if(bitmaplist.Count != 0)
{
bool done = true;
foreach(var bitmap in bitmaplist)
{
if(bitmap.IsPainted() == false)
{
done = false;
}
}
if(done == false)
{
bitmapLists.Add(bitmaplist);
}
bitmaplist = new List<BitmapData>();
}
continue;
}
bitmaplist.Add(_bitmapData[row, col]);
}
if (bitmaplist.Count != 0)
{
bitmapLists.Add(bitmaplist);
}
if(bitmapLists.Count != 1)
{
row++;
continue;
}
// 塗られている場所を特定
int leftCol = colNumbers.Count;
int rightCol = 0;
bool painted = false;
foreach (var bitmap in bitmapLists[0])
{
if(bitmap.IsPainted())
{
leftCol = bitmap.Col;
painted = true;
}
else
{
if (painted)
{
rightCol = bitmap.Col;
break;
}
}
}
// 左側をマスク
for(int col = 0; col < rightCol - value; col++)
{
if(_bitmapData[row,col].IsValid() == false)
{
_bitmapData[row, col].Mask();
}
}
// 右側をマスク
for (int col = leftCol + value; col < colNumbers.Count; col++)
{
if (_bitmapData[row, col].IsValid() == false)
{
_bitmapData[row, col].Mask();
}
}
row++;
}
}
private void pattern9Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
// 有効な数字で一番大きいものを取り出す
if (collist.AnalyzeDatas.Count != 1)
{
col++;
continue;
}
int value = collist.AnalyzeDatas[0].Value;
// 対象となるマスを抽出する
List<List<BitmapData>> bitmapLists = new List<List<BitmapData>>();
List<BitmapData> bitmaplist = new List<BitmapData>();
for (int row = 0; row < rowNumbers.Count; row++)
{
// マスクとマスクの間が全て塗られていたら、そこは対象としない
if (_bitmapData[row, col].IsMasked())
{
if (bitmaplist.Count != 0)
{
bool done = true;
foreach (var bitmap in bitmaplist)
{
if (bitmap.IsPainted() == false)
{
done = false;
}
}
if (done == false)
{
bitmapLists.Add(bitmaplist);
}
bitmaplist = new List<BitmapData>();
}
continue;
}
bitmaplist.Add(_bitmapData[row, col]);
}
if (bitmaplist.Count != 0)
{
bitmapLists.Add(bitmaplist);
}
if (bitmapLists.Count != 1)
{
col++;
continue;
}
// 塗られている場所を特定
int topRow = rowNumbers.Count;
int downRow = 0;
bool painted = false;
foreach (var bitmap in bitmapLists[0])
{
if (bitmap.IsPainted())
{
topRow = bitmap.Row;
painted = true;
}
else
{
if (painted)
{
downRow = bitmap.Row;
break;
}
}
}
// 左側をマスク
for (int row = 0; row < downRow - value; row++)
{
if (_bitmapData[row, col].IsValid() == false)
{
_bitmapData[row, col].Mask();
}
}
// 右側をマスク
for (int row = topRow + value; row < rowNumbers.Count; row++)
{
if (_bitmapData[row, col].IsValid() == false)
{
_bitmapData[row, col].Mask();
}
}
col++;
}
}
塗られている塊の部分を探し、その左端の行、列と右端の行、列を取得し、その値を数字からどこまでマスクされるかを探しています。
実行結果はこうなりました。

あまり大きな変化はありませんでしたが、こういうときこそ、塗ることができないマスは確実に潰していく事が、ピクロスの解析に重要です。
ちなみに、こんな問題、解けました。


はんだごてが届いたので、早速はんだでピンを接続しました。

カオスなことになっています。
久しぶりのはんだづけなのでピンヘッダが傾いているけど気にするな。
これをブレッドボードに挿して、ラズパイと接続します。

カオス。
ちなみに、どうつないでいるかというと、

LCD側のデータシートがこうなっているので、

こんな感じでつなぎました。
ラズパイ側GPIOの並びがバラバラなので、かなり配線が複雑になってしまいました。
ちなみに、3番、18番は後でハマった所なので後述します。
とりあえず電源ON
LCDが光りました。
そりゃそうだ。バックライトの電源が入ったから。
しかし、画面にはなにも表示されません。
でもよく見ると、なにかうっすら映っているような。
で、ネットを調べてみると、3番18番の秘密が明らかになりました。
http://zattouka.net/GarageHouse/micon/Arduino/GLCD/GLCD.htm
半固定抵抗というものを使用しているんですね。
これは、足が3つあって、一つは5Vの入力、もう一つは-10Vの入力になっています。
そして、半固定抵抗につまみがあって、アナログ的に抵抗を変えて、出力電圧を変えることができるんです。
回路的には、5Vの入力はラズパイの5V、-10Vは18番、半固定抵抗の出力を3番につなぐみたいです。
そうすることでLCDディスプレイのコントラストを調整できるようなんです。
そう、半固定抵抗が必要なんです。
なので、ポチりました。50円。
とりあえず、今回はここまで。

最新ソースはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
とりあえずダッシュボードの画面を作成してみました。

最近のVSCodeは非常に便利でして、

この画面でnpm run watchコマンドを動かしてくれるんです。
わざわざコマンドを入力する必要がないので、便利です。
この画面はVue.jsで書かれています。
久しぶりのhtml,cssだったので、ちょっと時間がかかりましたが、イメージとしては良いのではないでしょうか。

前回までの状況はこちら。
最新ソースはこちら。(gitHub)
https://github.com/takishita2nd/Picross
今回注目したのはここです。

ここはどのように塗っていくかというと、
空いているマスが4マスに対して、数字は3なので、
真ん中の2マスは確実に塗れることが分かります。
なので、これを実装します。
処理を単純化させるため、解析対象となる数字が行、列で1つの場合のみを、このロジックの対象とします。
また、このロジックを適用するマスを抽出するのですが、
マスクとマスクの間が全て塗られていた場合は処理済みと判断してスキップさせます。
その結果、対象のマスが1つの場合のみ、このロジックの対象とします。
この様な説明で分かってもらえるかどうか分からないけど、そういうことをやっています。
// 解析パターンその8
// 数字が大きい場合、真ん中の方を塗る
private void pattern8()
{
// Row
pattern8Row();
// Col
pattern8Col();
}
private void pattern8Row()
{
int row = 0;
foreach (var rowlist in rowNumbers)
{
if (rowlist.IsAnalyzed())
{
row++;
continue;
}
// 有効な数字を取り出す
List<int> values = new List<int>();
foreach(var data in rowlist.AnalyzeDatas)
{
if (data.IsAnalyzed())
{
continue;
}
values.Add(data.Value);
}
if(values.Count != 1)
{
row++;
continue;
}
// 対象となるマスを抽出する
List<List<BitmapData>> bitmapLists = new List<List<BitmapData>>();
List<BitmapData> bitmaplist = new List<BitmapData>();
for (int col = 0; col < colNumbers.Count; col++)
{
// マスクとマスクの間が全て塗られていたら、そこは対象としない
if (_bitmapData[row, col].IsMasked())
{
if(bitmaplist.Count != 0)
{
bool done = true;
foreach(var bitmap in bitmaplist)
{
if(bitmap.IsPainted() == false)
{
done = false;
}
}
if(done == false)
{
bitmapLists.Add(bitmaplist);
}
bitmaplist = new List<BitmapData>();
}
continue;
}
bitmaplist.Add(_bitmapData[row, col]);
}
if (bitmaplist.Count != 0)
{
bitmapLists.Add(bitmaplist);
}
if(bitmapLists.Count != 1)
{
row++;
continue;
}
int value = values[0];
List<BitmapData> bitmaps = bitmapLists[0];
if(value < bitmaps.Count && value * 2 > bitmaps.Count)
{
int paintNum = value * 2 - bitmaps.Count;
int countMax = 0;
if(paintNum % 2 == 1)
{
countMax = paintNum / 2 + 1;
}
else
{
countMax = paintNum / 2;
}
for (int count = -paintNum / 2; count < countMax; count++)
{
bitmaps[bitmaps.Count / 2 + count].Paint();
}
}
row++;
}
}
private void pattern8Col()
{
int col = 0;
foreach (var collist in colNumbers)
{
if (collist.IsAnalyzed())
{
col++;
continue;
}
// 有効な数字を取り出す
List<int> values = new List<int>();
foreach (var data in collist.AnalyzeDatas)
{
if (data.IsAnalyzed())
{
continue;
}
values.Add(data.Value);
}
if (values.Count != 1)
{
col++;
continue;
}
// 対象となるマスを抽出する
List<List<BitmapData>> bitmapLists = new List<List<BitmapData>>();
List<BitmapData> bitmaplist = new List<BitmapData>();
for (int row = 0; row < rowNumbers.Count; row++)
{
// マスクとマスクの間が全て塗られていたら、そこは対象としない
if (_bitmapData[row, col].IsMasked())
{
if (bitmaplist.Count != 0)
{
bool done = true;
foreach (var bitmap in bitmaplist)
{
if (bitmap.IsPainted() == false)
{
done = false;
}
}
if (done == false)
{
bitmapLists.Add(bitmaplist);
}
bitmaplist = new List<BitmapData>();
}
continue;
}
bitmaplist.Add(_bitmapData[row, col]);
}
if (bitmaplist.Count != 0)
{
bitmapLists.Add(bitmaplist);
}
if (bitmapLists.Count != 1)
{
col++;
continue;
}
int value = values[0];
List<BitmapData> bitmaps = bitmapLists[0];
if (value < bitmaps.Count && value * 2 > bitmaps.Count)
{
int paintNum = value * 2 - bitmaps.Count;
int countMax = 0;
if (paintNum % 2 == 1)
{
countMax = paintNum / 2 + 1;
}
else
{
countMax = paintNum / 2;
}
for (int count = -paintNum / 2; count < countMax; count++)
{
bitmaps[bitmaps.Count / 2 + count].Paint();
}
}
col++;
}
}
public BitmapData[,] Run()
{
pattern1();
while (checkPainedCount())
{
pattern2();
pattern3();
pattern4();
pattern5();
pattern6();
pattern7();
pattern8();
doMask();
}
return _bitmapData;
}
実行結果はこうなりました。

全て埋まりましたね。

解けたようです。
やったぁ。
