using System;
using System.Collections.Generic;
class Program
{
const int UB = 5 - 1;
struct JyoutaiDef
{
internal char[,] BanArr;
internal HashSet<char> UsedPieceNameSet;
}
static void Main()
{
var Stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.BanArr = new char[UB + 1, UB + 1];
for (int X = 0; X <= UB; X++) {
for (int Y = 0; Y <= UB; Y++) {
WillPush.BanArr[X, Y] = ' ';
}
}
WillPush.BanArr[2, 1] = 'A'; WillPush.BanArr[4, 1] = 'B';
WillPush.BanArr[3, 2] = 'C'; WillPush.BanArr[4, 2] = 'D';
WillPush.BanArr[2, 4] = 'E';
WillPush.UsedPieceNameSet = new HashSet<char>();
Stk.Push(WillPush);
while (Stk.Count > 0) {
JyoutaiDef Popped = Stk.Pop();
//クリア判定
if (Popped.UsedPieceNameSet.Count == 3) {
if (IsClear(Popped.BanArr)) {
Console.WriteLine("解を発見");
PrintBan(Popped.BanArr);
}
continue;
}
for (int X = 0; X <= UB; X++) {
for (int Y = 0; Y <= UB; Y++) {
char CurrChar = Popped.BanArr[X, Y];
if (CurrChar == ' ') continue;
if (Popped.UsedPieceNameSet.Contains(CurrChar))
continue;
PointDef[] CanMovePosList = DeriveCanMovePosList(Popped.BanArr, X, Y);
foreach (PointDef EachPos in CanMovePosList) {
WillPush.BanArr = (char[,])Popped.BanArr.Clone();
WillPush.BanArr[X, Y] = ' ';
WillPush.BanArr[EachPos.X, EachPos.Y] = CurrChar;
WillPush.UsedPieceNameSet = new HashSet<char>(Popped.UsedPieceNameSet);
WillPush.UsedPieceNameSet.Add(CurrChar);
Stk.Push(WillPush);
}
}
}
}
}
//クリア判定
static bool IsClear(char[,] pBanArr)
{
for (int X = 0; X <= UB; X++) {
for (int Y = 0; Y <= UB; Y++) {
if (pBanArr[X, Y] == ' ') continue;
if (IsValid(pBanArr, X, Y) == false) return false;
}
}
return true;
}
//座標を引数として、既存の駒の効き筋ならFalseを返す
static bool IsValid(char[,] pBanArr, int pCurrX, int pCurrY)
{
//上チェック
for (int Y = pCurrY - 1; 0 <= Y; Y--)
if (pBanArr[pCurrX, Y] != ' ') return false;
//下チェック
for (int Y = pCurrY + 1; Y <= UB; Y++)
if (pBanArr[pCurrX, Y] != ' ') return false;
//左チェック
for (int X = pCurrX - 1; 0 <= X; X--)
if (pBanArr[X, pCurrY] != ' ') return false;
//右チェック
for (int X = pCurrX + 1; X <= UB; X++)
if (pBanArr[X, pCurrY] != ' ') return false;
//左下チェック
for (int X = pCurrX - 1, Y = pCurrY + 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X--, Y++)
if (pBanArr[X, Y] != ' ') return false;
//左上チェック
for (int X = pCurrX - 1, Y = pCurrY - 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X--, Y--) {
if (pBanArr[X, Y] != ' ') return false;
}
//右下チェック
for (int X = pCurrX + 1, Y = pCurrY + 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X++, Y++) {
if (pBanArr[X, Y] != ' ') return false;
}
//右上チェック
for (int X = pCurrX + 1, Y = pCurrY - 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X++, Y--) {
if (pBanArr[X, Y] != ' ') return false;
}
return true;
}
struct PointDef
{
internal int X;
internal int Y;
}
//座標を引数として、移動可能な座標の配列を返す
static PointDef[] DeriveCanMovePosList(char[,] pBanArr, int pCurrX, int pCurrY)
{
var WillReturn = new List<PointDef>();
Func<int, int, bool> AddFunc = (pX, pY) =>
{
if (pBanArr[pX, pY] == ' ') {
WillReturn.Add(new PointDef() { X = pX, Y = pY });
return true;
}
return false;
};
//上チェック
for (int Y = pCurrY - 1; 0 <= Y; Y--)
if (AddFunc(pCurrX, Y) == false) break;
//下チェック
for (int Y = pCurrY + 1; Y <= UB; Y++)
if (AddFunc(pCurrX, Y) == false) break;
//左チェック
for (int X = pCurrX - 1; 0 <= X; X--)
if (AddFunc(X, pCurrY) == false) break;
//右チェック
for (int X = pCurrX + 1; X <= UB; X++)
if (AddFunc(X, pCurrY) == false) break;
//左下チェック
for (int X = pCurrX - 1, Y = pCurrY + 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X--, Y++) {
if (AddFunc(X, Y) == false) break;
}
//左上チェック
for (int X = pCurrX - 1, Y = pCurrY - 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X--, Y--) {
if (AddFunc(X, Y) == false) break;
}
//右下チェック
for (int X = pCurrX + 1, Y = pCurrY + 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X++, Y++) {
if (AddFunc(X, Y) == false) break;
}
//右上チェック
for (int X = pCurrX + 1, Y = pCurrY - 1;
0 <= X && X <= UB && 0 <= Y && Y <= UB; X++, Y--) {
if (AddFunc(X, Y) == false) break;
}
return WillReturn.ToArray();
}
//盤面を出力
static void PrintBan(char[,] pBanArr)
{
var sb = new System.Text.StringBuilder();
for (int Y = 0; Y <= UB; Y++) {
for (int X = 0; X <= UB; X++) {
char CurrChar = pBanArr[X, Y];
if (CurrChar == ' ') sb.Append('□');
else sb.Append((char)('A' + pBanArr[X, Y] - 'A'));
}
sb.AppendLine();
}
Console.WriteLine(sb.ToString());
}
}