Good day to all,
I've been working on a C# Sudoku Solver application but I sincerely underestimated the difficulty of the algorithms to solve a sudoku. I've been searching the web for possible algorithms that I could implement, but I've had no luck finding an easy algorithm that I can get my head around.
I found an algorithm that may work in my application, however this person is using a single-dimensional array to work it out.
I've tried to change it to make it work with a multidimensional array, but I can't get it to work properly.
Could anybody give me advice or show me how I could change the code so that it works with a multidimensional array(int[,])? I just can't seem to find it on my own. The code is found here: http://blah.winsmarts.com/2007-1-sudoku_solver_in_c-.aspx
If you have another algorithm that would work with an int[,], that's also wonderful of course.
Help would be greatly appreciated since I've been searching for a long time.
Thanks in advance!
The code you linked already logically uses a 2D array, it just uses a 1D array as a backing. Change this:
private int[] vals = new int[81];
public int this[int row, int column]
{
get { return vals[FindIndex(row, column)]; }
set
{
vals[FindIndex(row, column)] = value;
}
}
private int FindIndex(int row, int column)
{
return (((column - 1) * 9) + row - 1);
}
To:
private int[,] vals = new int[9,9];
public int this[int row, int column]
{
get { return vals[row - 1, column - 1]; }
set
{
vals[row - 1, column - 1] = value;
}
}
(The - 1's are necessary with the rest of the current code because row and column start at 1 instead of 0.)
Recursive backtracking , brute force, algorithm.
public class SudokoSolver
{
private readonly Grid _grid;
public SudokoSolver(Grid grid)
{
_grid = grid;
_grid.Validate();
}
public int?[,] SolvePuzzle()
{
Solve();
Console.WriteLine(_grid.Assigns + " tries total.");
return _grid.Data;
}
private bool Solve()
{
int row, col;
if (!_grid.FindUnassignedLoc(out row, out col))
{
return true;
}
for (int num = 1; num <= 9; num++)
{
if (_grid.NoConflicts(row, col, num))
{
_grid.Assign(row, col, num);
if (Solve())
{
return true;
}
_grid.Unassign(row, col);
}
}
return false;
}
public int?[,] Data
{
get { return _grid.Data; }
}
}
public class Grid
{
public int?[,] Data { get; private set; }
private int _curC = 0;
private int _curR = 0;
private int _assigns = 0;
public Grid(int?[,] data)
{
Data = data ?? new int?[9,9];
}
public bool FindUnassignedLoc(out int row, out int col)
{
while (Data[_curR, _curC].HasValue)
{
_curC++;
if (_curC == 9)
{
_curR++;
_curC = 0;
}
if (_curR == 9)
{
row = -1;
col = -1;
return false;
}
}
row = _curR;
col = _curC;
return true;
}
public bool NoConflicts(int row, int col, int num)
{
for (int r = 0; r < 9; ++r)
{
if (Data[r, col] == num)
{
return false;
}
}
for (int c = 0; c < 9; c++)
{
if (Data[row, c] == num)
{
return false;
}
}
int fromC = 3 * (col/3);
int fromR = 3 * (row / 3);
for (int c = fromC; c < fromC + 3; c++)
{
for (int r = fromR; r < fromR + 3; r++)
{
if (Data[r, c] == num)
{
return false;
}
}
}
return true;
}
public void Assign(int row, int col, int num)
{
_assigns++;
Data[row, col] = num;
}
public void Unassign(int row, int col)
{
Data[row, col] = null;
_curC = col;
_curR = row;
}
public int Assigns
{
get { return _assigns; }
}
public void Validate()
{
if (Data.Length != 81)
{
throw new Exception("Invalid dimentions!");
}
if (!IsLegal())
{
throw new Exception("Illigal numbers populated!");
}
}
public bool IsLegal()
{
var container = new HashSet<int>();
//vertical check
for (int c = 0; c < 9; ++c)
{
container.Clear();
for (int r = 0; r < 9; ++r)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
// horizontal check
for (int r = 0; r < 9; ++r)
{
container.Clear();
for (int c = 0; c < 9; ++c)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
// square check
var topLeftCorners = new List<Tuple<int, int>>
{
new Tuple<int, int>(0,0),
new Tuple<int, int>(0,3),
new Tuple<int, int>(0,6),
new Tuple<int, int>(3,0),
new Tuple<int, int>(3,3),
new Tuple<int, int>(3,6),
new Tuple<int, int>(6,0),
new Tuple<int, int>(6,3),
new Tuple<int, int>(6,6)
};
foreach (var topLeftCorner in topLeftCorners)
{
int fromC = topLeftCorner.Item2;
int fromR = topLeftCorner.Item1;
container.Clear();
for (int c = fromC; c < fromC + 3; c++)
{
for (int r = fromR; r < fromR + 3; r++)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
}
return true;
}
}
Related
I am trying to make a Sudoku solver. Whenever I try to run it it gives me a Stack Overflow Error:
System.StackOverflowException: 'Exception of type 'System.StackOverflowException' was thrown.'
I believe that it probably has to do with the solve function calling on the FindEmpy function too much?
Any help is greatly appreciated!
Thanks so much!
using System;
namespace sudokusolver
{
class Program
{
static public void PrintBoard(int[][] bo)
{
for (int i = 0; i < bo.Length; i++)
{
if (i % 3 == 0 && i != 0)
{
Console.WriteLine("- - - - - - - - - - - - -");
}
for (int j = 0; j < bo[0].Length; j++)
{
if (j % 3 == 0 && j != 0)
{
Console.Write(" | ");
}
if (j == 8)
{
Console.WriteLine(bo[i][j]);
}
else
{
Console.Write(bo[i][j] + " ");
}
}
}
}
static public (int,int) FindEmpty(int[][] bo)
{
for (int i = 0; i < bo.Length; i++)
{
for (int j = 0; j < bo[0].Length; j++)
{
if (bo[i][j] == 0)
{
return (i, j);
}
}
}
return (100, 100);
}
static public bool Solve(int[][] bo)
{
int x;
int y;
if (FindEmpty(bo) == (100, 100))
{
return true;
}
else
{
y = FindEmpty(bo).Item1;
x = FindEmpty(bo).Item2;
}
for (int i = 0; i < 10; i++)
{
if (IsValid(bo, i, x, y) == true)
{
bo[y][x] = i;
if (Solve(bo) == true)
{
return true;
}
else
{
bo[y][x] = 0;
}
}
}
return false;
}
static public bool IsValid(int[][] bo, int num, int x, int y)
{
for (int i = 0; i < bo.Length; i++)
{
if (bo[y][i] == num && x != i)
{
return false;
}
}
for (int i = 0; i < bo[0].Length; i++)
{
if (bo[i][x] == num && y != i)
{
return false;
}
}
int boxx = x / 3;
int boxy = y / 3;
for (int i = boxy * 3; i < boxy * 3 + 3; i++)
{
for (int j = boxx * 3; j < boxx * 3 + 3; j++)
{
if (bo[i][j] == num && i != y && j != x)
{
return false;
}
}
}
return true;
}
static void Main(string[] args)
{
int[][] board = {
new int[] {7,0,0,0,0,0,2,0,0},
new int[] {4,0,2,0,0,0,0,0,3},
new int[] {0,0,0,2,0,1,0,0,0},
new int[] {3,0,0,1,8,0,0,9,7},
new int[] {0,0,9,0,7,0,6,0,0},
new int[] {6,5,0,0,3,2,0,0,1},
new int[] {0,0,0,4,0,9,0,0,0},
new int[] {5,0,0,0,0,0,1,0,6},
new int[] {0,0,6,0,0,0,0,0,8}
};
PrintBoard(board);
Solve(board);
PrintBoard(board);
}
}
}
static public bool Solve(int[][] bo)
{
int x;
int y;
if (FindEmpty(bo) == (100, 100))
{
return true;
}
else
{
y = FindEmpty(bo).Item1;
x = FindEmpty(bo).Item2;
}
- for (int i = 0; i < 10; i++)
+ for (int i = 1; i < 10; i++)
{
if (IsValid(bo, i, x, y) == true)
{
bo[y][x] = i;
if (Solve(bo) == true)
{
return true;
}
else
{
bo[y][x] = 0;
}
}
}
return false;
}
At some point IsValid(bo, 0, x, y) returns true, so you replace the zero with another zero forever.
Based on the alorithm given here https://en.wikipedia.org/wiki/Gaussian_elimination#Pseudocode,
I tried to implement a C# version of the Gaussian Elimination:
public Matrix GaussianElimination(double epsilon = 1e-10)
{
var result = Copy();
var kMax = Math.Min(result.RowCount, result.ColumnCount);
for (var k = 0; k < kMax; k++)
{
// Find k-th pivot, i.e. maximum in column max
var iMax = result.FindColumnAbsMax(k);
if (Math.Abs(result[iMax, k]) < epsilon)
{
throw new ArithmeticException("Matrix is singular or nearly singular.");
}
// Swap maximum row with current row
SwapRows(k, iMax);
// Make all rows below the current one, with 0 in current column
for (var i = k + 1; i < result.RowCount; i++)
{
var factor = result[i, k] / result[k, k];
for (var j = k + 1; j < result.ColumnCount; j++)
{
result[i, j] = result[i, j] - result[k, j] * factor;
}
result[i, k] = 0;
}
}
return result;
}
It works in most cases (note that this is not performing the back substitution step). However, for the first example given in Wikipedia, the algorithm stop on the singular matrix case and throw the related exception on the row echelon form right before back substitution step with:
public class Program
{
public static void Main(string[] args)
{
var matrix = Matrix.Parse("[1 3 1 9; 1 1 -1 1; 3 11 5 35]");
Console.WriteLine(matrix);
Console.WriteLine(matrix.GaussianElimination());
Console.ReadKey();
}
}
k = 2
kMax = 3
iMax = 2
result = [1 3 1 9; 0 -2 -2 -8; 0 0 0 0]
[EDIT]
The Matrix implementation is a bit lengthy but here is what it is used in regard to the string parsing and the elimination method:
public class Matrix
{
public const string MatrixStart = "[";
public const string MatrixStop = "]";
public const char RowSeparator = ';';
public const char RowCellSeparator = ' ';
public int RowCount { get; }
public int ColumnCount { get; }
public int CellCount => _data.Length;
public bool IsSquare => RowCount == ColumnCount;
public bool IsVector => ColumnCount == 1;
private readonly double[] _data;
public double this[int rowIndex, int columnIndex]
{
get => _data[Convert2DIndexTo1DIndex(rowIndex, columnIndex)];
set => _data[Convert2DIndexTo1DIndex(rowIndex, columnIndex)] = value;
}
public Matrix(Matrix matrix)
: this(matrix.RowCount, matrix.ColumnCount)
{
for (var i = 0; i < _data.Length; i++)
{
_data[i] = matrix._data[i];
}
}
public Matrix(int size, double placeHolder = 0)
: this(size, size, placeHolder)
{
}
public Matrix(int rowCount, int columnCount, double initializationValue = 0)
{
if (rowCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(rowCount));
}
if (columnCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(columnCount));
}
RowCount = rowCount;
ColumnCount = columnCount;
_data = new double[RowCount * ColumnCount];
if (Math.Abs(initializationValue) > 0)
{
Set(initializationValue);
}
}
public Matrix(int rowCount, int columnCount, double[] initializationValues)
{
if (rowCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(rowCount));
}
if (columnCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(columnCount));
}
if (initializationValues.Length != rowCount * columnCount)
{
throw new ArgumentOutOfRangeException(nameof(initializationValues));
}
RowCount = rowCount;
ColumnCount = columnCount;
_data = new double[initializationValues.Length];
initializationValues.CopyTo(_data, 0);
}
private int Convert2DIndexTo1DIndex(int rowIndex, int columnIndex)
{
return rowIndex * ColumnCount + columnIndex;
}
public void Set(double value)
{
for (var i = 0; i < _data.Length; i++)
{
_data[i] = value;
}
}
public Matrix Transpose()
{
var result = new Matrix(ColumnCount, RowCount);
for (var i = 0; i < result.RowCount; i++)
{
for (var j = 0; j < result.ColumnCount; j++)
{
result[i, j] = this[j, i];
}
}
return result;
}
public Matrix Copy()
{
return new Matrix(this);
}
private int FindColumnAbsMax(int index)
{
return FindColumnAbsMax(index, index);
}
private int FindColumnAbsMax(int rowStartIndex, int columnIndex)
{
var maxIndex = rowStartIndex;
for (var i = rowStartIndex + 1; i < RowCount; i++)
{
if (Math.Abs(this[maxIndex, columnIndex]) <= Math.Abs(this[i, columnIndex]))
{
maxIndex = i;
}
}
return maxIndex;
}
public void SwapRows(int rowIndexA, int rowIndexB)
{
for (var j = 0; j < ColumnCount; j++)
{
var indexA = Convert2DIndexTo1DIndex(rowIndexA, j);
var indexB = Convert2DIndexTo1DIndex(rowIndexB, j);
_data.Swap(indexA, indexB);
}
}
public void SwapColumns(int columnIndexA, int columnIndexB)
{
for (var i = 0; i < RowCount; i++)
{
var indexA = Convert2DIndexTo1DIndex(i, columnIndexA);
var indexB = Convert2DIndexTo1DIndex(i, columnIndexB);
_data.Swap(indexA, indexB);
}
}
public static Matrix Parse(string matrixString)
{
if (!matrixString.StartsWith(MatrixStart) || !matrixString.EndsWith(MatrixStop))
{
throw new FormatException();
}
matrixString = matrixString.Remove(0, 1);
matrixString = matrixString.Remove(matrixString.Length - 1, 1);
var rows = matrixString.Split(new[] { RowSeparator }, StringSplitOptions.RemoveEmptyEntries);
if (rows.Length <= 0)
{
return new Matrix(0, 0);
}
var cells = ParseRow(rows[0]);
var matrix = new Matrix(rows.Length, cells.Length);
for (var j = 0; j < cells.Length; j++)
{
matrix[0, j] = cells[j];
}
for (var i = 1; i < matrix.RowCount; i++)
{
cells = ParseRow(rows[i]);
for (var j = 0; j < cells.Length; j++)
{
matrix[i, j] = cells[j];
}
}
return matrix;
}
private static double[] ParseRow(string row)
{
var cells = row.Split(new [] { RowCellSeparator }, StringSplitOptions.RemoveEmptyEntries);
return cells.Select(x => Convert.ToDouble(x.Replace(" ", string.Empty))).ToArray();
}
}
And the 1D Array extension for swapping two items:
public static class ArrayHelpers
{
public static void Swap<TSource>(this TSource[] source, int indexA, int indexB)
{
var tmp = source[indexA];
source[indexA] = source[indexB];
source[indexB] = tmp;
}
}
I have two variables: long[] nextState and List<long[]> TabuList.
I use this code to add items to TabuList:
TabuList.add(nextState);
or this:
TabuList.insert(Index, nexState);
but the problem is that after either of these operations, all of TabuList’s items automatically convert to the current value of nextState.
my complete code is:
class TabuSearch
{
private long[] current { get; set; }
private double Delta;
private Random rnd = new Random();
int foundLists = 0;
public TabuSearch()
{
current = new long[Convert.ToInt32(num_list1)];
}
public long[] TabuMOSA3Objectives(long[] c)
{
assign(current, c);
long[] nextState = new long[Convert.ToInt32(num_list1)];
List<long[]> TabuList = new List<long[]>();
double proba;
double alpha = 0.969;
double temperature = 500.0;
double epsilon = 0.0001;
short domination_st;
int iter = 0;
while (temperature > epsilon)
{
iter++;
Delta = 1;
assign(nextState, GenerateNextState(primaryList, current));
domination_st = CheckDomination3Objective(nextState, current);
try { var tmp = TabuList.Find(x => x == nextState); if (tmp == null) foundLists = 0; else foundLists = tmp.Count(); }
catch { }
if (foundLists == 0)
{
if (domination_st > 0)
{
assign(current, nextState);
}
else // domination_st < 0
{
proba = rnd.NextDouble();
if (proba < 1 / (1 + Math.Exp(Delta * temperature)))
{
assign(current, nextState);
}
else
{
if (TabuList.Count == 10)
TabuList.RemoveAt(0);
assign(nextState, TabuList);
}
}
}
//cooling proces on every iteration
temperature *= alpha;
}
return current;
}
}
static void assign(long[] c, long[] n)
{
for (int i = 0; i < c.Length; i++)
c[i] = n[i];
}
static void assign(long[] item, List<long[]> list)
{
list.Add(item);
}
I'm trying to implement the MinMax algorithm for four in a row (or connect4 or connect four) game.
I think I got the idea of it, it should build a tree of possible boards up to a certain depth, evaluate them and return their score, then we just take the max of those scores.
So, aiChooseCol() checks the score of every possible column by calling MinMax() and returns the column with the max score.
Now I wasn't sure, is this the right way to call MinMax()?
Is it right to check temp = Math.Max(temp, 1000);?
I still haven't made the heuristic function but this should at least recognize a winning column and choose it, but currently it just choose the first free column from the left... I can't figure out what am I doing wrong.
private int AiChooseCol()
{
int best = -1000;
int col=0;
for (int i = 0; i < m_Board.Cols; i++)
{
if (m_Board.CheckIfColHasRoom(i))
{
m_Board.FillSignInBoardAccordingToCol(i, m_Sign);
int t = MinMax(5, m_Board, board.GetOtherPlayerSign(m_Sign));
if (t > best)
{
best = t;
col = i;
}
m_Board.RemoveTopCoinFromCol(i);
}
}
return col;
}
private int MinMax(int Depth, board Board, char PlayerSign)
{
int temp=0;
if (Depth <= 0)
{
// return from heurisitic function
return temp;
}
char otherPlayerSign = board.GetOtherPlayerSign(PlayerSign);
char checkBoard = Board.CheckBoardForWin();
if (checkBoard == PlayerSign)
{
return 1000;
}
else if (checkBoard == otherPlayerSign)
{
return -1000;
}
else if (!Board.CheckIfBoardIsNotFull())
{
return 0; // tie
}
if (PlayerSign == m_Sign) // maximizing Player is myself
{
temp = -1000;
for (int i = 0; i < Board.Cols; i++)
{
if (Board.FillSignInBoardAccordingToCol(i, PlayerSign)) // so we don't open another branch in a full column
{
var v = MinMax(Depth - 1, Board, otherPlayerSign);
temp = Math.Max(temp, v);
Board.RemoveTopCoinFromCol(i);
}
}
}
else
{
temp = 1000;
for (int i = 0; i < Board.Cols; i++)
{
if (Board.FillSignInBoardAccordingToCol(i, PlayerSign)) // so we don't open another branch in a full column
{
var v = MinMax(Depth - 1, Board, otherPlayerSign);
temp = Math.Min(temp, v);
Board.RemoveTopCoinFromCol(i);
}
}
}
return temp;
}
Some notes:
FillSignInBoardAccordingToCol() returns a boolean if it was successful.
The board type has a char[,] array with the actual board and signs of the players.
This code is in the AI Player class.
So I decided to write my own MinMax Connect 4. I used the depth to determine the value of a win or loss so that a move that gets you closer to winning or blocking a loss will take precedence. I also decide that I will randomly pick the move if more than one has the same heuristic. Finally I stretched out the depth to 6 as that's how many moves are required to find possible win paths from the start.
private static void Main(string[] args)
{
var board = new Board(8,7);
var random = new Random();
while (true)
{
Console.WriteLine("Pick a column 1 -8");
int move;
if (!int.TryParse(Console.ReadLine(), out move) || move < 1 || move > 8)
{
Console.WriteLine("Must enter a number 1-8.");
continue;
}
if (!board.DropCoin(1, move-1))
{
Console.WriteLine("That column is full, pick another one");
continue;
}
if (board.Winner == 1)
{
Console.WriteLine(board);
Console.WriteLine("You win!");
break;
}
if (board.IsFull)
{
Console.WriteLine(board);
Console.WriteLine("Tie!");
break;
}
var moves = new List<Tuple<int, int>>();
for (int i = 0; i < board.Columns; i++)
{
if (!board.DropCoin(2, i))
continue;
moves.Add(Tuple.Create(i, MinMax(6, board, false)));
board.RemoveTopCoin(i);
}
int maxMoveScore = moves.Max(t => t.Item2);
var bestMoves = moves.Where(t => t.Item2 == maxMoveScore).ToList();
board.DropCoin(2, bestMoves[random.Next(0,bestMoves.Count)].Item1);
Console.WriteLine(board);
if (board.Winner == 2)
{
Console.WriteLine("You lost!");
break;
}
if (board.IsFull)
{
Console.WriteLine("Tie!");
break;
}
}
Console.WriteLine("DONE");
Console.ReadKey();
}
private static int MinMax(int depth, Board board, bool maximizingPlayer)
{
if (depth <= 0)
return 0;
var winner = board.Winner;
if (winner == 2)
return depth;
if (winner == 1)
return -depth;
if (board.IsFull)
return 0;
int bestValue = maximizingPlayer ? -1 : 1;
for (int i = 0; i < board.Columns; i++)
{
if (!board.DropCoin(maximizingPlayer ? 2 : 1, i))
continue;
int v = MinMax(depth - 1, board, !maximizingPlayer);
bestValue = maximizingPlayer ? Math.Max(bestValue, v) : Math.Min(bestValue, v);
board.RemoveTopCoin(i);
}
return bestValue;
}
public class Board
{
private readonly int?[,] _board;
private int? _winner;
private bool _changed;
public Board(int cols, int rows)
{
Columns = cols;
Rows = rows;
_board = new int?[cols, rows];
}
public int Columns { get; }
public int Rows { get; }
public bool ColumnFree(int column)
{
return !_board[column, 0].HasValue;
}
public bool DropCoin(int playerId, int column)
{
int row = 0;
while (row < Rows && !_board[column,row].HasValue)
{
row++;
}
if (row == 0)
return false;
_board[column, row - 1] = playerId;
_changed = true;
return true;
}
public bool RemoveTopCoin(int column)
{
int row = 0;
while (row < Rows && !_board[column, row].HasValue)
{
row++;
}
if (row == Rows)
return false;
_board[column, row] = null;
_changed = true;
return true;
}
public int? Winner
{
get
{
if (!_changed)
return _winner;
_changed = false;
for (int i = 0; i < Columns; i++)
{
for (int j = 0; j < Rows; j++)
{
if (!_board[i, j].HasValue)
continue;
bool horizontal = i + 3 < Columns;
bool vertical = j + 3 < Rows;
if (!horizontal && !vertical)
continue;
bool forwardDiagonal = horizontal && vertical;
bool backwardDiagonal = vertical && i - 3 >= 0;
for (int k = 1; k < 4; k++)
{
horizontal = horizontal && _board[i, j] == _board[i + k, j];
vertical = vertical && _board[i, j] == _board[i, j + k];
forwardDiagonal = forwardDiagonal && _board[i, j] == _board[i + k, j + k];
backwardDiagonal = backwardDiagonal && _board[i, j] == _board[i - k, j + k];
if (!horizontal && !vertical && !forwardDiagonal && !backwardDiagonal)
break;
}
if (horizontal || vertical || forwardDiagonal || backwardDiagonal)
{
_winner = _board[i, j];
return _winner;
}
}
}
_winner = null;
return _winner;
}
}
public bool IsFull
{
get
{
for (int i = 0; i < Columns; i++)
{
if (!_board[i, 0].HasValue)
return false;
}
return true;
}
}
public override string ToString()
{
var builder = new StringBuilder();
for (int j = 0; j < Rows; j++)
{
builder.Append('|');
for (int i = 0; i < Columns; i++)
{
builder.Append(_board[i, j].HasValue ? _board[i,j].Value.ToString() : " ").Append('|');
}
builder.AppendLine();
}
return builder.ToString();
}
}
here will be my code for famous Knights Tour for 8x8 deck. So, the main idea of my code is: we will choose from Turns our destination, check it with isPossible and then go recursevly to it, marked this cell to '1'. So, check every cell, and if we will be in 64's cell - return true.
But my code goes to infinite recurssion, and I can't debug it, any recommendation will be greatly appreciated.
class Class1
{
static void Main(string[] args)
{
int x = 0;
int y = 0;
Console.WriteLine("Enter X and press enter");
x = Int32.Parse(Console.ReadLine());
Console.WriteLine("Enter Y and press enter");
y = Int32.Parse(Console.ReadLine());
TurnVariation Turns = new TurnVariation();
EmptyBoard Board = new EmptyBoard();
if (TryPut.Put(Board, x, y, Turns, 1, false))
{
Console.WriteLine("МОЖНА!!!!");
}
else
{
Console.WriteLine("NET!!");
}
}
}
public class TryPut : EmptyBoard
{
public static bool Put(EmptyBoard Board, int x, int y, TurnVariation Turns, int count, bool flag)
{
int tempX = 0;
int tempY = 0;
if (count >= 64)
{
Console.WriteLine("yeab");
return true;
}
for (int i = 0; i <= 7; i++)
{
tempX = x + Turns.Turns[i,0];
tempY = y + Turns.Turns[i,1];
//Console.WriteLine(count);
if (IsPossible(Board, tempX, tempY))
{
Board.Array[tempX, tempY] = 1;
flag = Put(Board, tempX, tempY, Turns, count+1, flag);
if (flag)
{
break;
}
Board.Array[tempX, tempY] = 0;
}
}
if (flag)
return true;
else
return false;
}
public static bool IsPossible(EmptyBoard Board, int x, int y)
{
if ((x < 0) || (x > 7) || (y < 0) || (y > 7))
return false;
if (Board.Array[x, y] == 1)
return false;
return true;
}
}
public class TurnVariation
{
public int[,] Turns = new int[8, 2];
public TurnVariation()
{
Turns[0, 0] = -2; Turns[0, 1] = 1;
Turns[1,0] = -2; Turns[1,1] = -1;
Turns[2,0] = -1; Turns[2,1] = 2;
Turns[3,0] = 1; Turns[3,1] = 2;
Turns[4,0] = 2; Turns[4,1] = 1;
Turns[5,0] = 2; Turns[5,1] = -1;
Turns[6,0] = 1; Turns[6,1] = -2;
Turns[7,0] = -1; Turns[7,1] = -2;
}
}
public class EmptyBoard
{
public const int N = 8;
public int[,] Array = new int[N, N];
public EmptyBoard()
{
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
Array[i, j] = 0;
}
}
I think your problem is that your testing for count<64, but you never assign to count. You just pass (by value!) 'Count + 1' to the put method. You are probably thinking that this will bewritten back to the count variable. But that is not the case...
Do note that debugging is the first skill you need to learn!