ビンゴの成立を確認する処理を実装したいと思います。まずはデバッグログでビンゴ成立時にBINGOのログが出ればOK。また縦横と斜めを別に処理したいと思います。今回は縦横のラインの判断のみ行います。
横の列が空いているか調べる
横の列が全て空いているかどうかを行って、ビンゴラインを調べたいと思います。調べる方針としては、Nextで空いた穴の縦横のラインを調べて行きたいと思います。
空いた穴の番号から何段目の穴なのかを知る方法
まずは横一列に対してビンゴになっているかどうかを調べて見たいと思います。今回はわかりやすいように5x5の25のビンゴカードで話を進めます。
最初に知りたいのは、穴の空いた場所が何段目の番号かを自覚できるかです。ここでは下図で11の番号が何段目か、というのを知りたいと思います。左から2番めですが、プログラム的には1という数字が欲しい。さぁどうすればいいでしょうか?
上の並びですが、こんなふうに書き換えてみればピンと来るのでは無いでしょうか?赤い丸で囲んだ部分は11です。11は2×5+1で表されますが、この2を取り出すことができれば何段目にあるものかを知ることが出来ます。
11から2を取り出す方法としては11 ÷ 2の結果から取得することが出来ます。
あとは2×5に0~4までの値を足した数字が2の段のインデックスになります。
上から3段目の数字を表示する
ではまずはテストとして、上から3段目の数字をデバッグログに順々に表示してみましょう。メソッド自体の追加と、NewGameが呼ばれた時に表示させるようにします。どの段を表示するかですが、先程の11番目のマスの段を
public class BingoManager : MonoBehaviour
{
// 他の処理は省略
public void NewGame()
{
GenerateBingoCard(25);
for (int i = 0; i < SQUARE_COUNT; i++)
{
cardAreaView.SetCardNumber(i, bingoSquareList[i].number);
cardAreaView.SetCardClose(i);
}
// ここに追加
DebugShowRowLine(11);
}
private void DebugShowRowLine(int index)
{
int row = index / 5;
for (int i = 0; i < 5; i++)
{
Debug.Log($"row:{row} col:{i} {bingoSquareList[row * 5 + i].number}");
}
}
}
プログラムの更新が出来たら動かしてみましょう。New Gameボタンを押すたびに、上から3段目の数字がデバッグログで表示されます。
横の列でビンゴになっているか確認する
では、横の列に対してビンゴが成立しているかどうかの処理を作りましょう。ビンゴになっているかどうかを判定するには、
- 同列のすべてがOpen状態
- 同列の中にClose状態がない
リーチを知りたいとなると事情は変わりますが、ビンゴになっているかどうかを判断するだけであれば、ライン状に空いてないSquareが一つでもあったらビンゴじゃない!!!と判断するのが簡単だと思います。ちなDebugShowRowLineはコメントアウトしています。
public class BingoManager : MonoBehaviour
{
public void Next()
{
// まだ空いていないSquareを探す
int number = GetRandomNumber();
if (number == -1)
{
return;
}
// イベント発信
OnBingoNumber?.Invoke(number);
// 数字から何番目のSquareのIndexかを探す
int squareIndex = bingoSquareList.FindIndex(x => x.number == number);
// 要素内に存在しない場合はエラー
if (squareIndex == -1)
{
Debug.Log($"number:{number} squareIndex:{squareIndex}");
return;
}
// 表示更新(ここもイベント化しても良さそう)
cardAreaView.SetCardOpen(squareIndex);
// 変数の更新
bingoSquareList[squareIndex].isOpen = true;
if (IsBingo(squareIndex))
{
Debug.Log("Bingo!(横の列が)");
}
}
public bool IsBingo(int squareIndex)
{
// まずはsquareIndexが有効かを確認する
if (squareIndex < 0 || squareIndex >= SQUARE_COUNT)
{
return false;
}
// そのsquareが開いているかを確認する
if (!bingoSquareList[squareIndex].isOpen)
{
return false;
}
// そのsquareがBingoになっているかを確認する
int row = squareIndex / 5;
// 横の判定
bool isBingo = true;
for (int i = 0; i < 5; i++)
{
if (!bingoSquareList[row * 5 + i].isOpen)
{
isBingo = false;
break;
}
}
if (isBingo)
{
return true;
}
return false;
}
}
横のみビンゴになった時反応します。
縦バージョンも作りましょう
横と同様のアプローチで縦バージョンも作りたいと思います。ちょっぴり違うのが縦のインデックスの取り方。
縦の列はどうやって調べれば良い?
基本的には横の列と同じですが、割り算ではなくあまりを使います。先程の11番を例に例えると11を5で割ったあまりが1なら左から2番目ってことですね。
縦の列の数字を表示させる処理
New Game時に特定のSquareの縦の列の数字を表示させる処理を作って、確認だけしておきましょう。
public class BingoManager : MonoBehaviour
{
public void NewGame()
{
GenerateBingoCard(25);
for (int i = 0; i < SQUARE_COUNT; i++)
{
cardAreaView.SetCardNumber(i, bingoSquareList[i].number);
cardAreaView.SetCardClose(i);
}
//DebugShowRowLine(11);
DebugShowColLine(11);
}
private void DebugShowColLine(int index)
{
int col = index % 5;
for (int i = 0; i < 5; i++)
{
Debug.Log($"row:{i * 5} col:{col} {bingoSquareList[i * 5 + col].number}");
}
}
}
縦と横を組み合わせたビンゴチェック処理
では、横のビンゴ処理に縦のビンゴ状態のチェックも合わせてみたいと思います。変更するのはIsBingoメソッドのみ。横のビンゴチェックをした後に縦のビンゴ状態をチェックします。
public class BingoManager : MonoBehaviour
{
// 特定のsquareでBingoになっているかを判定する
public bool IsBingo(int squareIndex)
{
// まずはsquareIndexが有効かを確認する
if (squareIndex < 0 || squareIndex >= SQUARE_COUNT)
{
return false;
}
// そのsquareが開いているかを確認する
if (!bingoSquareList[squareIndex].isOpen)
{
return false;
}
// そのsquareがBingoになっているかを確認する
int row = squareIndex / 5;
int col = squareIndex % 5;
// 横の判定
bool isBingo = true;
for (int i = 0; i < 5; i++)
{
if (!bingoSquareList[row * 5 + i].isOpen)
{
isBingo = false;
break;
}
}
if (isBingo)
{
return true;
}
// 縦の判定
isBingo = true;
for (int i = 0; i < 5; i++)
{
if (!bingoSquareList[col + i * 5].isOpen)
{
isBingo = false;
break;
}
}
if (isBingo)
{
return true;
}
return false;
}
}
あとは動かしてみましょう。縦横の列でビンゴが成立すると反応できるようになります。
コメント