import java.util.*; /** * CS 211 Assignment 1 Solution (IntPuzzle.java) * The IntPuzzle class implements the 8-puzzle using a single int. * @author Kiri Wagstaff, wkiri@cs.cornell.edu */ public class PuzzleAsInt implements IPuzzle { /** * Represents the blank tile */ public static final int BLANK = 9; /** * Constants representing certain column and row indices */ private final int LEFT = 0, RIGHT = 2, TOP = 0, BOTTOM = 2; /** * Integer implementation of the puzzle */ private int puzzleState; /** * Integer representing the solved state of the puzzle */ private final int solvedState = 987654321; /** * Keeps track of where the blank is */ private int brow, bcol; /** * Constructor: initializes the puzzle to the solved configuration */ public PuzzleAsInt() { resetPuzzle(); } /** * Local helper method that resets the puzzle * to its initial (solved) configuration */ public void resetPuzzle() { puzzleState = solvedState; brow = BOTTOM; bcol = RIGHT; } /** * Checks whether the puzzle is in the solved state * @return true if the puzzle is in a solved state; otherwise, false */ public boolean isSolved() { // Check for any out-of-place tiles. return (puzzleState == solvedState); } /** * Moves a tile in the specified direction, if possible * @param dir character indicating direction (N/S/E/W) * (case-sensitive) * @return true if the move was successful; otherwise, false */ public boolean move(char dir) { int bindex = 3*brow + bcol; // index of the blank int index = 0, t = 0; switch (dir) { case 'N': if (brow == BOTTOM) return false; // no tile to move north // Swap the blank and what's right below it index = 3*(brow+1) + bcol; t = tile(brow+1, bcol); brow++; break; case 'S': if (brow == TOP) return false; // no tile to move south // Swap the blank and what's right above it index = 3*(brow-1) + bcol; t = tile(brow-1, bcol); brow--; break; case 'E': if (bcol == LEFT) return false; // no tile to move east // Swap the blank and what's to the left of it index = 3*brow + bcol-1; t = tile(brow, bcol-1); bcol--; break; case 'W': if (bcol == RIGHT) return false; // no tile to move west // Swap the blank and what's to the right of it index = 3*brow + bcol+1; t = tile(brow, bcol+1); bcol++; break; default : return false; } // Update puzzle state puzzleState -= t * (int)Math.pow(10,index); // remove the tile puzzleState -= BLANK * (int)Math.pow(10,bindex); // remove the blank puzzleState += t * (int)Math.pow(10,bindex); // add the tile puzzleState += BLANK * (int)Math.pow(10,index); // add the blank return true; } /** * Scrambles the puzzle by making a series of random moves */ public void scramble() { resetPuzzle(); for (int i=0; i<100; i++) { // Get a random value from 0 to 3 int r = (int)(Math.random()*4); switch (r) { case 0: move('N'); break; case 1: move('S'); break; case 2: move('E'); break; case 3: move('W'); break; } } } /** * Sets the puzzle to Sam Loyd's configuration */ public void samLoyd() { resetPuzzle(); // Swap the 7 and 8 puzzleState -= 7 * (int)Math.pow(10,6); // remove the 7 puzzleState -= 8 * (int)Math.pow(10,7); // remove the 8 puzzleState += 7 * (int)Math.pow(10,7); // add the 7 puzzleState += 8 * (int)Math.pow(10,6); // add the 8 } /** * Returns the value of the tile at (row, col); * outputs an error if (row, col) is an invalid address (returns -1). * @param row integer index of the tile's row * @param col integer index of the column's row * @return the value of tile at (row, col) or -1 for error */ public int tile(int row, int col) { // Check the inputs; return -1 for invalid inputs. if (row < TOP || row > BOTTOM || col < LEFT || col > RIGHT) { System.out.println("Error: (" + row + ", " + col + ") is not a valid tile location."); return -1; } int index = 3*row + col; return (puzzleState/(int)Math.pow(10,index))%10; } /** * Displays the current state of an PuzzleAsInt */ public void display() { // IntPuzzles use '9' to represent blank for (int i=0; i<3; i++) { int t1 = tile(i,0); int t2 = tile(i,1); int t3 = tile(i,2); System.out.println("[" + (t1 == BLANK ? " " : (t1 + " ")) + (t2 == BLANK ? " " : (t2 + " ")) + (t3 == BLANK ? " ]" : (t3 + "]"))); } } }