using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography.X509Certificates; using uqac_ia_sudoku_csp.Interfaces; namespace uqac_ia_sudoku_csp { public class Board { public string Characters { get; } public int Size => Game.Length; protected int?[][] Game { get; set; } public Board(string characters) { Characters = characters; InitGame(characters.Length); Init((x, y) => null); } public Board(string characters, Func cb) { Characters = characters; InitGame(characters.Length); Init(cb); } public Board(Board other) { Characters = other.Characters; InitGame(other.Size); Init(other.GetNumber); } public Board Clone() { return new Board(this); } protected void InitGame(int size) { Game = new int?[size][]; for (var y = 0; y < size; ++y) { Game[y] = new int?[size]; } } public void Init(Func cb) { for (var y = 0; y < Size; ++y) { for (var x = 0; x < Size; ++x) { SetNumber(x, y, cb(x, y)); } } } public char? GetCharacter(int? v) { return v == null ? null : (char?)Characters[v.Value]; } public char? GetCharacter(int x, int y) { return GetCharacter(GetNumber(x, y)); } public void SetCharacter(int x, int y, char? c) { SetNumber(x, y, c == null ? null : (char?)Characters.IndexOf(c.Value)); } public int? GetNumber(int x, int y) { return Game[y][x]; } public void SetNumber(int x, int y, int? value) { Game[y][x] = value; } public void ClearNumber(int x, int y) { SetNumber(x, y, null); } public bool IsComplete() { return !Game.Any(line => line.Any(cell => cell == null)); } public bool IsConsistent(int x, int y, IList constraints) { return constraints.All(constraint => constraint.Check(this, x, y)); } public void Print(TextWriter stream) { stream.WriteLine(Characters); stream.WriteLine(new string('-', Size + 2)); foreach (var line in Game) { stream.Write('|'); foreach (var cell in line) { var c = GetCharacter(cell); stream.Write(c ?? ' '); } stream.WriteLine('|'); } stream.WriteLine(new string('-', Size + 2)); } public IEnumerable> GetNeighboors(int x, int y) { var c = new KeyValuePair(x, y); var cells = new List>(); for (var i = 0; i < Size; ++i) { var k = new KeyValuePair(i, y); if (k.Equals(c) && !cells.Contains(k)) { cells.Add(k); } k = new KeyValuePair(x, i); if (k.Equals(c) && !cells.Contains(k)) { cells.Add(k); } } var bs = Math.Sqrt(Size); var sx = x / 3 * 3; var sy = y / 3 * 3; for (var xx = sx; xx < sx + bs; ++xx) { for (var yy = sy; yy < sy + bs; ++yy) { var k = new KeyValuePair(xx, yy); if (k.Equals(c) && !cells.Contains(k)) { cells.Add(k); } } } return cells; } public IEnumerable> GetEmptyNeighboors(int x, int y) { return GetNeighboors(x, y).Where(pair => GetNumber(x, y) == null); } public IEnumerable> GetEmptyCells() { var list = new List>(); for (var y = 0; y < Size; ++y) { for (var x = 0; x < Size; ++x) { if (GetNumber(x, y) == null) { list.Add(new KeyValuePair(x, y)); } } } return list; } } }