using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;
namespace Assets.NetSyncDemo.Test
{
// N皇后C#算法
public class TestNQueen : MonoBehaviour
{
private void Start()
{
int n = 8;
var result = SolveQueue(n);
UnityEngine.Debug.Log($"皇后 行数={n}, 排列方法={result.Count}");
int index = 0;
foreach (var solve in result)
{
UnityEngine.Debug.Log("方法" + index +": \n" + PrintQueue(solve));
index++;
}
}
private readonly int[] dirX = new int[] { -1, -1, -1, 0, 0, 1, 1, 1 };
private readonly int[] dirY = new int[] { -1, 0, 1, -1, 1, -1, 0, 1 };
private List<List<List<bool>>> SolveQueue(int count)
{
List<List<List<bool>>> result = new List<List<List<bool>>>();
var attack = new List<List<bool>>();
var queen = new List<List<bool>>();
for(int i = 0; i < count; i++)
{
var attackI = new List<bool>();
var queenI = new List<bool>();
for (int j = 0; j < count; j++)
{
attackI.Add(false);
queenI.Add(false);
}
attack.Add(attackI);
queen.Add(queenI);
}
BackTrace(0, count, ref attack, ref queen, ref result);
return result;
}
private void BackTrace(int lineIndex, int count, ref List<List<bool>> attack,
ref List<List<bool>> queen, ref List<List<List<bool>>> result)
{
if (lineIndex == count)
{
result.Add(Clone<List<bool>>(queen));
}
else
{
for(int i = 0; i < count; i++)
{
if(attack[lineIndex][i] == false)
{
List<List<bool>> tmpAttack = Clone<List<bool>>(attack);
queen[lineIndex][i] = true;
InsertQueen(lineIndex, i, count, ref attack);
BackTrace(lineIndex + 1, count, ref attack, ref queen, ref result);
attack = tmpAttack;
queen[lineIndex][i] = false;
}
}
}
}
private void InsertQueen( int x, int y, int count, ref List<List<bool>> attack)
{
attack[x][y] = true;
int dx, dy;
for(int i = 0; i < count; i++)
{
for (int j = 0; j < 8; j++)
{
dx = x + i * dirX[j];
dy = y + i * dirY[j];
if(dx >= 0 && dx < count && dy >= 0 && dy < count)
{
attack[dx][dy] = true;
}
}
}
}
private static List<T> Clone<T>(object list)
{
using (Stream objectStream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(objectStream, list);
objectStream.Seek(0, SeekOrigin.Begin);
return formatter.Deserialize(objectStream) as List<T>;
}
}
private static string PrintQueue(List<List<bool>> list)
{
StringBuilder sb = new StringBuilder();
foreach (var row in list)
{
foreach (var col in row)
{
sb.Append(col ? 1 : 0);
}
sb.AppendLine();
}
return sb.ToString();
}
}
}