using System;
using System.Collections.Generic;
class Program
{
const int UB = 8;
struct PieceInfoDef
{
internal int PieceID;
internal List<char[]> HaitiArrList;
}
static PieceInfoDef[] mPieceInfoArr;
struct JyoutaiDef
{
internal char[,] BanArr;
internal int Level;
internal List<int> UsedPieceIDList;
}
static void Main()
{
//ピースごとの情報を取得
DerivePieceInfo();
//回転解の排除で、ピース1は回転させない
mPieceInfoArr[0].HaitiArrList.RemoveRange(1, mPieceInfoArr[0].HaitiArrList.Count - 1);
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.Level = 0;
WillPush.UsedPieceIDList = new List<int>();
Stk.Push(WillPush);
int AnswerCnt = 0;
while (Stk.Count > 0) {
JyoutaiDef Popped = Stk.Pop();
//クリア判定
if (Popped.Level == 9) {
Console.WriteLine("解{0}を発見", ++AnswerCnt);
PrintBan(Popped.BanArr, Popped.UsedPieceIDList);
continue;
}
int BaseX, BaseY;
DeriveShikitumePos(Popped.Level, out BaseX, out BaseY);
foreach (PieceInfoDef EachPieceInfo in mPieceInfoArr) {
if (Popped.UsedPieceIDList.Contains(EachPieceInfo.PieceID))
continue;
foreach (char[] EachHaitiArr in EachPieceInfo.HaitiArrList) {
WillPush.BanArr = (char[,])Popped.BanArr.Clone();
WillPush.BanArr[BaseX + 1, BaseY] = EachHaitiArr[0];
WillPush.BanArr[BaseX + 2, BaseY + 1] = EachHaitiArr[1];
WillPush.BanArr[BaseX + 1, BaseY + 2] = EachHaitiArr[2];
WillPush.BanArr[BaseX, BaseY + 1] = EachHaitiArr[3];
if (IsValid(WillPush.BanArr, Popped.Level) == false) continue;
WillPush.Level = Popped.Level + 1;
WillPush.UsedPieceIDList = new List<int>(Popped.UsedPieceIDList);
WillPush.UsedPieceIDList.Add(EachPieceInfo.PieceID);
Stk.Push(WillPush);
}
}
}
}
//ピースごとの情報を取得
static void DerivePieceInfo()
{
var PieceInfoList = new List<PieceInfoDef>();
Action<int, string> AddAct = (pID, pStr) =>
{
PieceInfoDef WillAdd;
WillAdd.PieceID = pID;
WillAdd.HaitiArrList = DeriveHaitiArrList(pStr.ToCharArray());
PieceInfoList.Add(WillAdd);
};
AddAct(1, "紫緑赤水");
AddAct(2, "赤水黄紫");
AddAct(3, "黄赤紫水");
AddAct(4, "緑水黄赤");
AddAct(5, "黄緑赤水");
AddAct(6, "紫黄緑水");
AddAct(7, "水紫赤緑");
AddAct(8, "赤紫緑黄");
AddAct(9, "緑黄水紫");
mPieceInfoArr = PieceInfoList.ToArray();
}
//回転させた配置を返す(4通り)
static List<char[]> DeriveHaitiArrList(char[] pBaseArr)
{
var WillReturn = new List<char[]>();
for (int I = 0; I <= pBaseArr.GetUpperBound(0); I++) {
var WillAdd = new List<char>();
int CurrInd = I;
for (int J = 1; J <= pBaseArr.Length; J++) {
WillAdd.Add(pBaseArr[I]);
if (++I > pBaseArr.GetUpperBound(0)) I = 0;
}
WillReturn.Add(WillAdd.ToArray());
}
return WillReturn;
}
//レベルを引数として、敷き詰めの座標を返す
static void DeriveShikitumePos(int pLevel, out int pX, out int pY)
{
pX = pY = -1;
if (pLevel == 0) { pX = 0; pY = 0; }
if (pLevel == 1) { pX = 3; pY = 0; }
if (pLevel == 2) { pX = 6; pY = 0; }
if (pLevel == 3) { pX = 0; pY = 3; }
if (pLevel == 4) { pX = 3; pY = 3; }
if (pLevel == 5) { pX = 6; pY = 3; }
if (pLevel == 6) { pX = 0; pY = 6; }
if (pLevel == 7) { pX = 3; pY = 6; }
if (pLevel == 8) { pX = 6; pY = 6; }
}
//盤面とレベルを引数として、有効な盤面かをチェック
static bool IsValid(char[,] pBanArr, int pLevel)
{
if (pLevel == 1 && pBanArr[2, 1] != pBanArr[3, 1]) return false;
if (pLevel == 2 && pBanArr[5, 1] != pBanArr[6, 1]) return false;
if (pLevel == 3 && pBanArr[1, 2] != pBanArr[1, 3]) return false;
if (pLevel == 4 && pBanArr[2, 4] != pBanArr[3, 4]) return false;
if (pLevel == 4 && pBanArr[4, 2] != pBanArr[4, 3]) return false;
if (pLevel == 5 && pBanArr[5, 4] != pBanArr[6, 4]) return false;
if (pLevel == 5 && pBanArr[7, 2] != pBanArr[7, 3]) return false;
if (pLevel == 6 && pBanArr[1, 5] != pBanArr[1, 6]) return false;
if (pLevel == 7 && pBanArr[2, 7] != pBanArr[3, 7]) return false;
if (pLevel == 7 && pBanArr[4, 5] != pBanArr[4, 6]) return false;
if (pLevel == 8 && pBanArr[5, 7] != pBanArr[6, 7]) return false;
if (pLevel == 8 && pBanArr[7, 5] != pBanArr[7, 6]) return false;
return true;
}
//解を出力
static void PrintBan(char[,] pBanArr, List<int> pUsedPieceIDList)
{
var sb = new System.Text.StringBuilder();
sb.AppendLine("ピースIDの配置");
for (int I = 0; I <= pUsedPieceIDList.Count - 1; I++) {
if (I == 3 || I == 6)
sb.AppendLine();
sb.Append(pUsedPieceIDList[I]);
}
sb.AppendLine();
sb.AppendLine("色の配置");
for (int Y = 0; Y <= UB; Y++) {
for (int X = 0; X <= UB; X++) {
sb.Append(pBanArr[X, Y]);
}
sb.AppendLine();
}
Console.WriteLine(sb.ToString());
}
}