private static void explore(int delay) { GemPuzzleForm oGemPuzzleForm = GemPuzzleForm.getInstance(); PuzzleState currentState; int[] tmpValues = new int[Constants.InvisibleValue]; oGemPuzzleForm.Invoke(new System.Windows.Forms.MethodInvoker(() => { for (int i = Constants.MinimumValue; i < Constants.InvisibleValue; i++) { tmpValues[i] = oGemPuzzleForm.gemButtons[i].Value; } })); currentState = new PuzzleState(tmpValues); while (Solver.Position < (Solver.SolutionMoves.Length - 1)) { currentState = new PuzzleState(currentState, Solver.SolutionMoves[++Solver.Position]); Solver.updateTiles(currentState); Thread.Sleep(delay); } oGemPuzzleForm.Invoke(new System.Windows.Forms.MethodInvoker(() => { oGemPuzzleForm.ControlButtons = true; })); }
/// <summary> /// Given a state, it calculates a new state randomly. /// </summary> /// <param name="state">The state containing the next possible and valid moves.</param> /// <returns>A state created randomly from a given state.</returns> public static PuzzleState SetNextStateRandomly(PuzzleState state) { PuzzleState tmpState; Random nextMove = new Random(DateTime.Now.Millisecond); int index = nextMove.Next(0, state.ValidMoves.Length); tmpState = new PuzzleState(state.Values, state.ValidMoves[index]); return(tmpState); }
private static void updateTiles(PuzzleState state) { GemPuzzleForm.getInstance().Invoke(new System.Windows.Forms.MethodInvoker(() => { for (int j = Constants.MinimumValue; j < Constants.InvisibleValue; j++) { GemPuzzleForm.getInstance().gemButtons[j].Value = state.Values[j]; } })); }
private static void shuffleTiles() { GemPuzzleForm oGemPuzzleForm = GemPuzzleForm.getInstance(); Solver.StartNode = Solver.getCurrentState(); for (int i = 0; i < 50; i++) { Solver.StartNode = PuzzleState.SetNextStateRandomly(Solver.StartNode); Solver.updateTiles(Solver.StartNode); Thread.Sleep(100); } }
/// <summary> /// This constructor is used when it is only necessary to create a copy ot the current state in the puzzle. /// </summary> public PuzzleState(PuzzleState state) { this.NonVisiblePosition = state.NonVisiblePosition; this.Values = new int[state.Values.Length]; state.Values.CopyTo(this.Values, 0); this.LastMove = state.LastMove; this.Heuristic1 = state.Heuristic1; this.Heuristic2 = state.Heuristic2; this.Cost = state.Cost; this.PreviousMoves = new List<byte>(state.PreviousMoves); this.ValidMoves = new byte[state.ValidMoves.Length]; state.ValidMoves.CopyTo(this.ValidMoves, 0); }
/// <summary> /// This constructor is used when it is only necessary to create a copy ot the current state in the puzzle. /// </summary> public PuzzleState(PuzzleState state) { this.NonVisiblePosition = state.NonVisiblePosition; this.Values = new int[state.Values.Length]; state.Values.CopyTo(this.Values, 0); this.LastMove = state.LastMove; this.Heuristic1 = state.Heuristic1; this.Heuristic2 = state.Heuristic2; this.Cost = state.Cost; this.PreviousMoves = new List <byte>(state.PreviousMoves); this.ValidMoves = new byte[state.ValidMoves.Length]; state.ValidMoves.CopyTo(this.ValidMoves, 0); }
private static int searchInList(List <PuzzleState> list, PuzzleState state) { int index = -1; for (int i = 0; (i < list.Count) && (index == -1); i++) { if (list[i].IsEqualTo(state)) { index = i; } } return(index); }
/// <summary> /// This constructor creates a new state, and updates cost, heuristic, none visible position, etc. /// </summary> /// <param name="state">This is the parent node</param> /// <param name="nextMovePosition">This is the position in the array that actually creates the new state.</param> public PuzzleState(PuzzleState state, byte nextMovePosition) { this.Values = new int[Constants.InvisibleValue]; state.Values.CopyTo(this.Values, 0); this.LastMove = state.NonVisiblePosition; this.NonVisiblePosition = nextMovePosition; this.Values[this.LastMove] = this.Values[nextMovePosition]; this.Values[nextMovePosition] = Constants.InvisibleValue; this.Heuristic1 = getHeuristic1(); this.Heuristic2 = getHeuristic2(); this.Cost = state.Cost + 1; this.PreviousMoves = new List<byte>(state.PreviousMoves); this.PreviousMoves.Add(nextMovePosition); this.setValidMovements(); }
/// <summary> /// This constructor creates a new state, and updates cost, heuristic, none visible position, etc. /// </summary> /// <param name="state">This is the parent node</param> /// <param name="nextMovePosition">This is the position in the array that actually creates the new state.</param> public PuzzleState(PuzzleState state, byte nextMovePosition) { this.Values = new int[Constants.InvisibleValue]; state.Values.CopyTo(this.Values, 0); this.LastMove = state.NonVisiblePosition; this.NonVisiblePosition = nextMovePosition; this.Values[this.LastMove] = this.Values[nextMovePosition]; this.Values[nextMovePosition] = Constants.InvisibleValue; this.Heuristic1 = getHeuristic1(); this.Heuristic2 = getHeuristic2(); this.Cost = state.Cost + 1; this.PreviousMoves = new List <byte>(state.PreviousMoves); this.PreviousMoves.Add(nextMovePosition); this.setValidMovements(); }
/// <summary> /// Checks if two states have the same value arrangement (the tiles). /// </summary> /// <param name="state"></param> /// <returns></returns> public bool IsEqualTo(PuzzleState state) { bool equals = false; if ((state.Heuristic2 == this.Heuristic2) && (state.Heuristic1 == this.Heuristic1)) { equals = true; for (int i = Constants.MinimumValue; (i < Constants.InvisibleValue) && equals; i++) { if (state.Values[i] != this.Values[i]) { equals = false; } } } return(equals); }
private static PuzzleState getCurrentState() { GemPuzzleForm oGemPuzzleForm; PuzzleState state; int[] currentArray = new int[Constants.InvisibleValue]; oGemPuzzleForm = GemPuzzleForm.getInstance(); oGemPuzzleForm.Invoke(new System.Windows.Forms.MethodInvoker(() => { for (int i = Constants.MinimumValue; i < Constants.InvisibleValue; i++) { currentArray[i] = oGemPuzzleForm.gemButtons[i].Value; } })); state = new PuzzleState(currentArray); return(state); }
private static PuzzleState getBestNodeFromOpenList() { PuzzleState bestState; int index = 0; if (Solver.OpenList.Count > 1) { for (int i = 1; i < Solver.OpenList.Count; i++) { if ((Solver.OpenList[i].GetFofN()) < Solver.OpenList[index].GetFofN()) { index = i; } } } bestState = new PuzzleState(Solver.OpenList[index]); Solver.OpenList.RemoveAt(index); return(bestState); }
private static int searchInList(List<PuzzleState> list, PuzzleState state) { int index = -1; for (int i = 0; (i < list.Count) && (index == -1); i++) { if (list[i].IsEqualTo(state)) { index = i; } } return index; }
private static void main() { while (true) { switch (Solver.Action) { case Actions.Shuffling: Solver.shuffleTiles(); Solver.Action = Actions.None; break; case Actions.Solving: Solver.findSolution(); Solver.Action = Actions.Solved; break; case Actions.Solved: GemPuzzleForm.getInstance().Invoke(new System.Windows.Forms.MethodInvoker(() => { GemPuzzleForm.getInstance().Moves.Text = "Total Moves: " + (Solver.GoalNode.PreviousMoves.Count - 1).ToString(); })); Solver.SolutionMoves = new byte[Solver.GoalNode.PreviousMoves.Count]; Solver.GoalNode.PreviousMoves.CopyTo(Solver.SolutionMoves); Solver.Position = 0; Solver.Action = Actions.Explore; break; case Actions.GoToStart: PuzzleState state; if (Solver.Position > 0) { state = Solver.getCurrentState(); while (Solver.Position > 0) { state = new PuzzleState(state, Solver.SolutionMoves[--Solver.Position]); Solver.updateTiles(state); Thread.Sleep(100); } } Solver.Action = Actions.Waiting; break; case Actions.GoBackward: if (Solver.Position > 0) { state = Solver.getCurrentState(); state = new PuzzleState(state, Solver.SolutionMoves[--Solver.Position]); Solver.updateTiles(state); } Solver.Action = Actions.Waiting; break; case Actions.Explore: Solver.explore(500); Solver.Action = Actions.Waiting; break; case Actions.GoForward: if (Solver.Position < (Solver.SolutionMoves.Length - 1)) { state = Solver.getCurrentState(); state = new PuzzleState(state, Solver.SolutionMoves[++Solver.Position]); Solver.updateTiles(state); } Solver.Action = Actions.Waiting; break; case Actions.GoToEnd: Solver.explore(100); Solver.Action = Actions.Waiting; break; default: // Do nothing. break; } } }
private static PuzzleState getCurrentState() { GemPuzzleForm oGemPuzzleForm; PuzzleState state; int[] currentArray = new int[Constants.InvisibleValue]; oGemPuzzleForm = GemPuzzleForm.getInstance(); oGemPuzzleForm.Invoke(new System.Windows.Forms.MethodInvoker(() => { for (int i = Constants.MinimumValue; i < Constants.InvisibleValue; i++) { currentArray[i] = oGemPuzzleForm.gemButtons[i].Value; } })); state = new PuzzleState(currentArray); return state; }
private static PuzzleState getBestNodeFromOpenList() { PuzzleState bestState; int index = 0; if (Solver.OpenList.Count > 1) { for (int i = 1; i < Solver.OpenList.Count; i++) { if ((Solver.OpenList[i].GetFofN()) < Solver.OpenList[index].GetFofN()) { index = i; } } } bestState = new PuzzleState(Solver.OpenList[index]); Solver.OpenList.RemoveAt(index); return bestState; }
/// <summary> /// Algorithm A* /// f(n) = h(n) + g(n). /// Where: /// n: is the current state. /// f: is the function that decides which state is going to be explored. /// h: is the heuristic (the distance from the current state to the goal state. /// g: is the cost to get from the start state to the current state n. /// </summary> private static void findSolution() { List<PuzzleState> successorNodes; int index; bool notIgnore; int nodesVisited = 0; // 1. Create a node containing the goal state (Solver.GoalNode). // 2. Create a node containing the start state (Solver.StartNode) Solver.StartNode = Solver.getCurrentState(); // 3. Put the start node on the OpenList. Solver.OpenList.Add(Solver.StartNode); // 4. While OpenList is not empty. while (Solver.OpenList.Count > 0) { // 5. Get the node off the open list with the lowest f and call it current node (Solver.CurrentNode). Solver.CurrentNode = Solver.getBestNodeFromOpenList(); // 6. If Solver.CurrentNode is the same state as Solver.GoalState we have found the solution; break from the while loop if (Solver.GoalNode.IsEqualTo(Solver.CurrentNode)) { Solver.GoalNode = new PuzzleState(Solver.CurrentNode); Solver.CurrentNode = null; nodesVisited = Solver.ClosedList.Count + 1; Solver.OpenList.Clear(); Solver.ClosedList.Clear(); } else { // 7. Generate each state that can come after CurrentNode. successorNodes = new List<PuzzleState>(Solver.CurrentNode.ValidMoves.Length); for (int i = 0; i < Solver.CurrentNode.ValidMoves.Length; i++) { successorNodes.Add(new PuzzleState(Solver.CurrentNode, Solver.CurrentNode.ValidMoves[i])); } foreach (PuzzleState state in successorNodes) { // 8. For each successor node of current node: // 9. If successor node is on the Open List but the existing one is a good or better, then disscard this successor and continue. notIgnore = true; index = Solver.searchInList(Solver.OpenList, state); if (index > -1) { if (state.GetFofN() < Solver.OpenList[index].GetFofN()) { // 9.1 Remove occurrances of successor node from Open List. Solver.OpenList.RemoveAt(index); } else { notIgnore = false; } } // 10. If successor node is on the Closed List but the existing one is a good or better, then disscard this successor and continue. index = Solver.searchInList(Solver.ClosedList, state); if (index > -1) { if (state.GetFofN() < Solver.ClosedList[index].GetFofN()) { // 10.1 Remove occurrances of successor node from Closed List. Solver.ClosedList.RemoveAt(index); } else { notIgnore = false; } } // 11. Add successor node to the Open List. if (notIgnore) { Solver.OpenList.Add(state); } } // 14. Add CurrentNode to the Closed List. Solver.ClosedList.Add(new PuzzleState(Solver.CurrentNode)); nodesVisited = Solver.ClosedList.Count; } GemPuzzleForm.getInstance().Invoke(new System.Windows.Forms.MethodInvoker(() => { GemPuzzleForm.getInstance().Nodes.Text = "Nodes Visited: " + nodesVisited.ToString(); })); } }
/// <summary> /// Given a state, it calculates a new state randomly. /// </summary> /// <param name="state">The state containing the next possible and valid moves.</param> /// <returns>A state created randomly from a given state.</returns> public static PuzzleState SetNextStateRandomly(PuzzleState state) { PuzzleState tmpState; Random nextMove = new Random(DateTime.Now.Millisecond); int index = nextMove.Next(0, state.ValidMoves.Length); tmpState = new PuzzleState(state.Values, state.ValidMoves[index]); return tmpState; }
/// <summary> /// Checks if two states have the same value arrangement (the tiles). /// </summary> /// <param name="state"></param> /// <returns></returns> public bool IsEqualTo(PuzzleState state) { bool equals = false; if ((state.Heuristic2 == this.Heuristic2) && (state.Heuristic1 == this.Heuristic1)) { equals = true; for (int i = Constants.MinimumValue; (i < Constants.InvisibleValue) && equals; i++) { if (state.Values[i] != this.Values[i]) { equals = false; } } } return equals; }