Sudoku.cs 10.50 KiB
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;
}
}
}