// TODO: // new private Sate goalState, initialState // why actually put NPuzzleState in here? //private NPuzzleState<int[]> goalState, initialState; // against, just use State instead of NPuzzleState<int[]> // State should have a State property public NPuzzleProblem(NPuzzleState <int[]> goal, NPuzzleState <int[]> initial) { //! both goal and initial should be the same length //! goal should be a valid goal state (positive integers 1 through size in order //! initial should be an acceptableState (even number of inversions, //! not including inversions with the largest //! element in the state, which = size //! string error = "State empty"; bool errorFlag = false; if (!EqualStateLengths(goal.State, initial.State)) { error = "Goal state length and initial state length differ"; errorFlag = true; } else if (!ValidStateLength(goal.State)) { error = "The length of a state should be equal to the square of an integer."; errorFlag = true; } else if (!ValidGoalState(goal.State)) { error = "Invalid goal state. It should be the positive integers from 1 to n, where n is the size of the puzzle"; errorFlag = true; } else if (!ValidInitialState(initial.State)) { error = "Invalid initial state. It should contain all positive integers from 1 to n, where n is the size of the puzzle, and contain an even number of inversions when not comparing elements to the largest element of size n"; errorFlag = true; } if (errorFlag) { NPuzzleUtils.InvalidNPuzzleStatesException ex = new NPuzzleUtils.InvalidNPuzzleStatesException(error); throw ex; } double sqrt = Math.Sqrt(goal.State.Length); size = goal.State.Length; dimension = (int)sqrt; GoalState = goal; InitialState = initial; }
// TODO: again, NPuzzleState return type instead of int[] public override NPuzzleState <int[]> Result(NPuzzleState <int[]> s, int action) { int[] state = s.State; int[] newState = new int[state.Length]; int emptyIndex; state.CopyTo(newState, 0); emptyIndex = GetEmptyIndex(state); if (emptyIndex == -1) { NPuzzleUtils.MissingEmptyElementException ex = new NPuzzleUtils.MissingEmptyElementException(state.Length.ToString()); throw ex; } if (AcceptableAction(state, emptyIndex, action)) { if (action == 1) { NPuzzleUtils.Swap(newState, emptyIndex, emptyIndex + 1); } else if (action == -1) { NPuzzleUtils.Swap(newState, emptyIndex, emptyIndex - 1); } else if (action == -2) { NPuzzleUtils.Swap(newState, emptyIndex, emptyIndex + dimension); } else { NPuzzleUtils.Swap(newState, emptyIndex, emptyIndex - dimension); } } else { String msg = String.Format("You entered an invalid action: {0} for the state {1}", action, state.ToString()); NPuzzleUtils.ResultAcceptableActionException ex = new NPuzzleUtils.ResultAcceptableActionException(msg); throw ex; } return(new NPuzzleState <int[]>(newState)); }
/*! * Get all the actions possible in a givens state. * First, we must locate the index of the 'empty' * space in the 'board' (array), which in this case * is equal to 'size'. * * We can determine the possible actions by the direction the * 'empty' space can be moved: up, down, left or right * We'll use the following conventions: * * up : 2 * down: -2 * left: -1 * right: 1 * * */ // TODO: use State instead of int[] public override List <int> Actions(NPuzzleState <int[]> s) { int[] state = s.State; int emptyIndex = GetEmptyIndex(state); if (emptyIndex == -1) { NPuzzleUtils.MissingEmptyElementException ex = new NPuzzleUtils.MissingEmptyElementException(state.Length.ToString()); throw ex; } List <int> actions = new List <int>(); //! if emptyIndex is in the rightmost column, //! then adding one to it will be divisible by dimension if ((emptyIndex + 1) % dimension != 0) { actions.Add(1); } //! if emptyIndex is in the leftmost column, //! it can be divided by dimension //! Anything not in the leftmost column can be moved left, or - 1 if (emptyIndex % dimension != 0) { actions.Add(-1); } //! if emptyIndex is greater than or equal to dim, it //! must not be in the first row, and hence //! can be moved up, or 2 if (emptyIndex >= dimension) { actions.Add(2); } if (emptyIndex < size - dimension) { actions.Add(-2); } return(actions); }
public override bool GoalTest(NPuzzleState <int[]> state) { if (GoalState.Equals(state)) { return(true); } else { return(false); } /* * if (GoalState.State.Length != state.State.Length) * { * return false; * } * for(int i = 0; i < state.State.Length; i++) * { * if (GoalState.State[i] != state.State[i]) return false; * } * return true;*/ }
public bool Equals(NPuzzleState <int[]> s) { //Console.WriteLine("in NPuzzleState<int[]> equals"); if (Object.ReferenceEquals(s.State, null)) { return(false); } if (Object.ReferenceEquals(this.State, s.State)) { return(true); } if (this.State.GetType() != s.State.GetType()) { return(false); } int l = s.State.Length; if (this.State.Length != l) { return(false); } for (int i = 0; i < l; i++) { if (s.State[i] != this.State[i]) { return(false); } } return(true); }
public override int PathCost(int cost, NPuzzleState <int[]> state1, int action, NPuzzleState <int[]> state2) { return(cost + 1); }