using System; using System.Collections.Generic; using System.Diagnostics; using System.DirectoryServices; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace PuzzlePlayer_Namespace { internal class Sudoku : Board { private static int boardLength; private static int rootBoardLength; private static Random random = new Random(); public Sudoku(int boardSize = 9) { boardState = GetClearBoard(boardSize, boardSize); lastGeneratedBoard = GetClearBoard(boardSize, boardSize); boardLength = boardSize; rootBoardLength = (int)Math.Sqrt(boardLength); description = "Sudoku is played on any perfect square-numbered grid, with some cells initially containing numbers. The goal of the puzzle is to fill all cells such that:\r\n● Each row and column must contain all of the numbers exactly once\r\n● Each box indicated by thicker lines must also contain all of the numbers exactly once\r\n● Every sudoku must have an unique solution"; drawFactor = 1; } public override void Draw(Graphics gr, Rectangle r) { StringFormat format = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center, }; Size tilesize = new Size(r.Width / boardState.GetLength(0), r.Height / boardState.GetLength(1)); Pen border = new Pen(Color.Black, 2); gr.FillRectangle(Brushes.Beige, r.X, r.Y, tilesize.Width * boardState.GetLength(0), tilesize.Height * boardState.GetLength(1)); for (int i = 0; i < boardState.GetLength(0); i++) { for (int j = 0; j < boardState.GetLength(1); j++) { gr.DrawRectangle(Pens.LightGray, r.X + i * tilesize.Width, r.Y + j * tilesize.Height, tilesize.Width, tilesize.Height); if (boardState[i,j] != -1) { gr.DrawString( (boardState[i, j]).ToString(), new Font("Arial", tilesize.Width / 2), Brushes.Black, (float)(r.X + (i + 0.27) * tilesize.Width + tilesize.Width / 4), (float)(r.Y + (j + 0.33) * tilesize.Height + tilesize.Height / 4), format ); } if (lastGeneratedBoard[i, j] != Board.emptySpace) { gr.FillRectangle(Brushes.LightGray, (int)(r.X + ((double)i + 0.4375) * tilesize.Width), (int)(r.Y + ((double)j + 0.4375) * tilesize.Height), tilesize.Width / 8, tilesize.Height / 8); } } } for (int i = 1; i < Math.Sqrt(boardState.GetLength(0)); i++) { gr.DrawLine(Pens.Black, r.X + i * (int)Math.Sqrt((double)boardState.GetLength(0)) * tilesize.Width, r.Y, r.X + i * (int)Math.Sqrt((double)boardState.GetLength(0)) * tilesize.Width, r.Bottom); gr.DrawLine(Pens.Black, r.X, r.Y + i * (int)Math.Sqrt((double)boardState.GetLength(1)) * tilesize.Height, r.Right, r.Y + i * (int)Math.Sqrt((double)boardState.GetLength(1)) * tilesize.Height); } } public override void Generate() { boardState = GetClearBoard(boardLength, boardLength); for (int i = 0; i < boardLength; i += rootBoardLength) { FillBox(i, i); } SolveSudoku(); RemoveSpaces((int)(boardLength * boardLength - 30)); } public override SOLUTIONS Solve(bool b) { if (SolveSudoku()) { return SOLUTIONS.UNIQUE; } return SOLUTIONS.NONE; } private int RandomNumber(int number) { return (int)Math.Floor((double)(random.NextDouble() * number + 1)); } private void FillBox(int row, int col) { int num; for (int i = 0; i < rootBoardLength; i++) { for (int j = 0; j < rootBoardLength; j++) { do { num = RandomNumber(boardLength); } while (BoxFlag(row, col, num)); boardState[row + i, col + j] = num; } } } private bool DoAllChecks(int i, int j, int num) { return (BoxFlag(i - i % rootBoardLength, j - j % rootBoardLength, num) || ColFlag(i, num) || RowFlag(j, num)); } private bool BoxFlag(int row, int col, int num) { for (int i = 0; i < rootBoardLength; i++) { for (int j = 0; j < rootBoardLength; j++) { if (boardState[row + i, col + j] == num) { return true; } } } return false; } private bool ColFlag(int i, int num) { for (int j = 0; j < boardLength; j++) { if (num == boardState[i, j]) { return true; } } return false; } private bool RowFlag(int j, int num) { for (int i = 0; i < boardLength; i++) { if(num == boardState[i, j]) { return true; } } return false; } // Heilige piramide private bool SolveSudoku() { for (int row = 0; row < boardLength; row++) { for (int col = 0; col < boardLength; col++) { if (boardState[row, col] == emptySpace) { for (int num = 1; num <= boardLength; num++) { if (!DoAllChecks(row, col, num)) { boardState[row, col] = num; if (SolveSudoku()) { return true; } boardState[row, col] = emptySpace; } } return false; } } } return true; } private static string BoardToString(int[,] board) { string result = ""; for (int i = 0; i < board.GetLength(0); i++) { for (int j = 0; j < board.GetLength(1); j++) { result += (board[i, j] == emptySpace ? "." : board[i, j].ToString()); } result += "|"; } return result; } private static int[,] BoardFromString(string board) { string[] parts = board.Split('|', StringSplitOptions.RemoveEmptyEntries); int[,] result = new int[parts.Length, parts.Length]; for (int i = 0; i < result.GetLength(0); i++) { for (int j = 0; j < result.GetLength(1); j++) { string s = parts[i][j].ToString(); if (s == ".") result[i, j] = emptySpace; else if (int.Parse(s) >= 0 && int.Parse(s) <= 8) result[i, j] = int.Parse(s); else return null; } } return result; } public override void TileInput(Point? p, Keys k) { if (p == null) return; int num = (int)k - 48; if (num >= 1 && num <= boardLength) boardState[((Point)p).X, ((Point)p).Y] = num; } public override void TileClick(Point p, int x) { if (x == 1) { x = -1; } if (x == 0) { x = 1; } if (boardState[p.X, p.Y] == emptySpace) { if (x == 1) { boardState[p.X, p.Y] = 1; return; } else { boardState[p.X, p.Y] = boardLength; return; } } else if (boardState[p.X, p.Y] == boardLength) { if (x == 1) { boardState[p.X, p.Y] = emptySpace; return; } else { boardState[p.X, p.Y] += x; return; } } else if (boardState[p.X, p.Y] == 1) { if (x == -1) { boardState[p.X, p.Y] = emptySpace; return; } else { boardState[p.X, p.Y] += x; return; } } else { boardState[p.X, p.Y] += x; return; } } private void RemoveSpaces(int k) { for(int i = 0; i < k; i++) { int row; int col; row = RandomNumber(boardLength) - 1; col = RandomNumber(boardLength) - 1; if (boardState[row, col] != emptySpace) { boardState[row, col] = emptySpace; } else { i--; } } } protected override List<Move> GetSolveList(int[,] boardToSolve) { List<Move> result = new List<Move>(); return result; } } }