package org.teachingextensions.logo.utils.PuzzleUtils; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Stack; /** * Represents a node in the puzzle-solving graph. Keeps track of the current puzzle arrangement and the actions * required to arrive at the current arrangement from the starting arrangement. */ public class PuzzleState implements Comparator<PuzzleState>, Comparable<PuzzleState> { private final Puzzle puzzle; private final Stack<Direction> history; public PuzzleState(Puzzle puzzle) { this(puzzle, new Stack<Direction>()); } public PuzzleState(Puzzle puzzle, Stack<Direction> history) { this.puzzle = puzzle; this.history = history; } public boolean isSolution() { return puzzle.isSolved(); } public List<PuzzleState> getBranches() { List<PuzzleState> branches = new ArrayList<>(4); int blank = puzzle.getBlankIndex(); int x = blank % 3; int y = blank / 3; for (Direction d : Direction.values()) { if (d == Direction.Left && x == 0) { continue; } if (d == Direction.Right && x == 2) { continue; } if (d == Direction.Up && y == 0) { continue; } if (d == Direction.Down && y == 2) { continue; } Stack<Direction> h = new Stack<>(); h.addAll(history); h.push(d); branches.add(new PuzzleState(puzzle.swapBlank(blank + d.getValue()), h)); } return branches; } public Iterable<Direction> getHistory() { return this.history; } public Puzzle getPuzzle() { return this.puzzle; } public int getActualCost() { return this.history.size(); } @Override public int compare(PuzzleState o1, PuzzleState o2) { return o1.getActualCost() - o2.getActualCost(); } @Override public int compareTo(PuzzleState o) { return compare(this, o); } @Override public int hashCode() { return puzzle.hashCode(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PuzzleState that = (PuzzleState) o; return puzzle.equals(that.puzzle); } @Override public String toString() { StringBuilder b = new StringBuilder(); if (!history.isEmpty()) { b.append(history.peek()); b.append(" to "); } b.append(puzzle); return b.toString(); } public int getEstimatedCost() { return puzzle.getDistanceToGoal(); } public enum Direction { Left(-1), Right(1), Up(-3), Down(3); private final int value; private Direction(int i) { this.value = i; } public int getValue() { return value; } @Override public String toString() { return "{" + super.toString() + " = " + value + '}'; } } }