diff --git a/PuzzlePlayer/Binary.cs b/PuzzlePlayer/Binary.cs index 6fc0a6281d7bab9db515d3f64199da00ee95bced..8d9f878b033e6461a90e0bfa034a8f79868efa88 100644 --- a/PuzzlePlayer/Binary.cs +++ b/PuzzlePlayer/Binary.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; +using System.Linq; using System.Runtime.CompilerServices; namespace PuzzlePlayer_Namespace @@ -83,7 +84,7 @@ namespace PuzzlePlayer_Namespace } private static int recursionDepth = 0; - private static int maxDepth = 500000; + private static int maxDepth = 1000000; // 1 mil recursions are allowed private static void PrintBoard(int[,] board) { @@ -102,14 +103,14 @@ namespace PuzzlePlayer_Namespace // But i wrote all the code myself private static int[,] BackTrackAlgorithm(int[,] board) { - //recursionDepth++; + recursionDepth++; if (recursionDepth > maxDepth) { - Console.WriteLine("Max recursion depth reached."); - //return null; + Debug.WriteLine("Max recursion depth reached."); + return board; } - - PrintBoard(board); + // print board for debugging + //PrintBoard(board); // check if the board is complete. if so then we can return the result if (IsBoardCompletlyFilledIn(board)) @@ -127,7 +128,7 @@ namespace PuzzlePlayer_Namespace } // check if the current board is already imposible to complete even tho there are still choices left - if (BoardIsImposible(board, choices)) + if (!BoardIsPosible(board, choices)) return null; ///* @@ -149,47 +150,53 @@ namespace PuzzlePlayer_Namespace // do the algorithm for every move foreach (Move m in choices) { - int[,] newBoard = (int[,])board.Clone(); + int[,] newBoard = (int[,])board.Clone(); //create a shallow clone to avoid multiple paths refrencing the same object newBoard[m.x,m.y] = m.changeTo; - + int[,] result = BackTrackAlgorithm(newBoard); // recursion for every move if(result != null) return result; } - //Debug.WriteLine("backtrack want moves empty"); recursionDepth--; + // if all choices fail then we should also return null return null; } - private static bool BoardIsImposible(int[,] board, List<Move> choices) + // checks if the board has a possible outcome to optimise the generating process + private static bool BoardIsPosible(int[,] board, List<Move> choices) { - throw new NotImplementedException(); - - bool isImposible = false; + if (choices.Count == 0) //if there are no choices then the board is imposible + return false; - List<int[]> locations = new List<int[]>(); + List<(int, int)> emptyLocations = new List<(int, int)>(); for (int i = 0; i < board.GetLength(0); i++) + { for (int j = 0; j < board.GetLength(1); j++) { - if(board[i,j] == emptySpace) - locations.Add([i,j]); + if (board[i, j] == emptySpace) + emptyLocations.Add((i, j)); //add all the empty locations to the list } + } - foreach (Move m in choices) + // Verify each empty location has a valid move + foreach (Move move in choices) { - foreach (int[] i in locations) + if (emptyLocations.Contains((move.x, move.y))) { - if (m.x == i[0] && m.y == i[1]) - continue; + emptyLocations.Remove((move.x, move.y)); + + if (emptyLocations.Count == 0) // if there are none left we can return true + return true; } } - return isImposible; + + return emptyLocations.Count == 0; // if there are none left we can return true } // get all the possible choices @@ -204,50 +211,13 @@ namespace PuzzlePlayer_Namespace for (int i = 0; i < board.GetLength(0); i++) for (int j = 0; j < board.GetLength(1); j++) { - // if the checked space is already filled in than it is not a valid move - //if (board[i, j] != emptySpace) - // continue; - - /* - // if one of the checks succeeds then it is an invalid move - if(DoAllChecks(i,j,board,checkFor)) - continue; - //*/ - // if all checks pass then add the move to the list - if(board[i, j] == emptySpace && ValidChoiceCheck(i,j,board,checkFor)) + if(board[i, j] == emptySpace && !DoAllChecks(i,j,board,checkFor)) choices.Add(new Move(i, j, checkFor)); } } return choices; } - private static bool ValidChoiceCheck(int x, int y, int[,] board, int checkFor) - { - int opposite; - if(checkFor == 0) - opposite = 1; - else - opposite = 0; - - - if (SideCheck(x, y, board, checkFor)) - { - //Debug.WriteLine("side check. return false"); - return false; - } - - if (MiddleCheck(x, y, board, checkFor)) - { - //Debug.WriteLine("middle check. return false"); - return false; - } - - if(EvenCheck(x, y, board, checkFor)) - return false; - - return true; - } - private static bool IsBoardCompletlyFilledIn(int[,] board) { for (int i = 0; i < board.GetLength(0); i++)