Implement the Solver class. The point of the solver class is the solve method which takes a board/puzzle configuration represented as a 2D array of bytes and returns a byte array containing a minimal sequence of moves that will lead to the solved board. The 2D array of bytes is “triangular” and represents a valid board configuration. Namely, the 2D array has 5 rows (0 – 4) and the size of every row is 1 more than its index.The array contains one 0, five 1s, four 2s and five 3s. The solve method then returns an array of bytes representing a minimal sequence of moves that solves the puzzle. In other words, if the numbers from the returned array are used in order as inputs to the move method on the Board object representing the initial configuration, the resulting board configuration represents the solved board. If the input to the solve method is a board configuration that is already solved, then solution requires no moves and an array of size 0 must be returned. package p1; import java.util.Arrays; import java.util.Random; public class Board { private static final Random rand = new Random(); private byte[][] board; /** * Construct a puzzle board by beginning with a solved board and then * making a number of random moves. Note that making random moves * could result in the board being solved. * * @param moves the number of moves to make when generating the board. */ public Board(int moves) { board = new byte[][]{{1}, {2, 3}, {4, 5, 6}, {7, 8, 9, 0}}; for (int i = 0; i < moves; i++) { randomMove(); } } /** * Construct a puzzle board using a 2D array of bytes to indicate the contents * of the cells in the triangle. * * @param b a "triangular array" with 5 rows where row 0 has 1 * cell, row 1 has 2 cells, etc. */ public Board(byte[][] b) { board = Arrays.copyOf(b, b.length); } public void printBoard() { for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { if (board[i][j] == 0) { System.out.print(" "); } else { System.out.print(board[i][j] + " "); } } System.out.println(); } } /** * Returns the byte at a particular grid position. * * @param row the row to look at * @param col the col to look at * @return the byte at a particular grid position */ public byte cellContents(int row, int col) { return board[row][col]; } /** * Makes a move on the board by swapping the 0 with one * of the items in a neighboring cell. The board is * left unchanged if the move is not valid. * * @param dir the direction in which the 0 should move * @return {@code true} if the move was valid and {@code false} * if it wasn't */ public boolean move(byte dir) { int[] zeroPos = findZeroPosition(); int targetRow = zeroPos[0]; int targetCol = zeroPos[1]; switch (dir) { case 1: // Move up-left targetRow--; targetCol--; break; case 2: // Move up-right targetRow--; break; case 3: // Move down-left targetRow++; break; case 4: // Move down-right targetRow++; targetCol++; break; default: return false; // Invalid direction } if (isValidPosition(targetRow, targetCol)) { byte temp = board[zeroPos[0]][zeroPos[1]]; board[zeroPos[0]][zeroPos[1]] = board[targetRow][targetCol]; board[targetRow][targetCol] = temp; return true; } else { return false; } } /** * Determines if the board is solved * * @return {@true} if the board is solved and {@code false} otherwise. */ public boolean isSolved() { int counter = 1; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { if (board[i][j] != 0 && board[i][j] != counter) { return false; } counter++; } } return true; } private int[] findZeroPosition() { int[] zeroPos = new int[2]; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { if (board[i][j] == 0) { zeroPos[0] = i; zeroPos[1] = j; return zeroPos; } } } return null; } private boolean isValidPosition(int row, int col) { return row >= 0 && row < board.length && col >= 0 && col < board[row].length; } private void randomMove() { byte randomDirection = (byte) (rand.nextInt(4) + 1); move(randomDirection); } }

icon
Related questions
Question

Implement the Solver class. The point of the solver class is the solve method which takes a board/puzzle configuration represented as a 2D array of bytes and returns a byte array containing a minimal sequence of moves that will lead to the solved board. The 2D array of bytes is “triangular” and represents a valid board configuration. Namely, the 2D array has 5 rows (0 – 4) and the size of every row is 1 more than its index.The array contains one 0, five 1s, four 2s and five 3s. The solve method then returns an array of bytes representing a minimal sequence of moves that solves the puzzle. In other words, if the numbers from the returned array are used in order as inputs to the move method on the Board object representing the initial configuration, the resulting board configuration represents the solved board. If the input to the solve method is a board configuration that is already solved, then solution requires no moves and an array of size 0 must be returned.

package p1;

import java.util.Arrays;
import java.util.Random;

public class Board {

    private static final Random rand = new Random();
    private byte[][] board;

    /**
     * Construct a puzzle board by beginning with a solved board and then
     * making a number of random moves. Note that making random moves
     * could result in the board being solved.
     *
     * @param moves the number of moves to make when generating the board.
     */
    public Board(int moves) {
        board = new byte[][]{{1}, {2, 3}, {4, 5, 6}, {7, 8, 9, 0}};

        for (int i = 0; i < moves; i++) {
            randomMove();
        }
    }

    /**
     * Construct a puzzle board using a 2D array of bytes to indicate the contents
     * of the cells in the triangle.
     *
     * @param b a "triangular array" with 5 rows where row 0 has 1
     *          cell, row 1 has 2 cells, etc.
     */
    public Board(byte[][] b) {
        board = Arrays.copyOf(b, b.length);
    }

    public void printBoard() {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == 0) {
                    System.out.print(" ");
                } else {
                    System.out.print(board[i][j] + " ");
                }
            }
            System.out.println();
        }
    }

    /**
     * Returns the byte at a particular grid position.
     *
     * @param row the row to look at
     * @param col the col to look at
     * @return the byte at a particular grid position
     */
    public byte cellContents(int row, int col) {
        return board[row][col];
    }

    /**
     * Makes a move on the board by swapping the 0 with one
     * of the items in a neighboring cell. The board is
     * left unchanged if the move is not valid.
     *
     * @param dir the direction in which the 0 should move
     * @return {@code true} if the move was valid and {@code false}
     * if it wasn't
     */
    public boolean move(byte dir) {
        int[] zeroPos = findZeroPosition();

        int targetRow = zeroPos[0];
        int targetCol = zeroPos[1];

        switch (dir) {
            case 1: // Move up-left
                targetRow--;
                targetCol--;
                break;
            case 2: // Move up-right
                targetRow--;
                break;
            case 3: // Move down-left
                targetRow++;
                break;
            case 4: // Move down-right
                targetRow++;
                targetCol++;
                break;
            default:
                return false; // Invalid direction
        }

        if (isValidPosition(targetRow, targetCol)) {
            byte temp = board[zeroPos[0]][zeroPos[1]];
            board[zeroPos[0]][zeroPos[1]] = board[targetRow][targetCol];
            board[targetRow][targetCol] = temp;
            return true;
        } else {
            return false;
        }
    }

    /**
     * Determines if the board is solved
     *
     * @return {@true} if the board is solved and {@code false} otherwise.
     */
    public boolean isSolved() {
        int counter = 1;
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] != 0 && board[i][j] != counter) {
                    return false;
                }
                counter++;
            }
        }
        return true;
    }

    private int[] findZeroPosition() {
        int[] zeroPos = new int[2];
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == 0) {
                    zeroPos[0] = i;
                    zeroPos[1] = j;
                    return zeroPos;
                }
            }
        }
        return null;
    }

    private boolean isValidPosition(int row, int col) {
        return row >= 0 && row < board.length && col >= 0 && col < board[row].length;
    }

    private void randomMove() {
        byte randomDirection = (byte) (rand.nextInt(4) + 1);
        move(randomDirection);
    }
}

package p2;
import java.util.Arrays;
public class Solver {
public Solver() {
// TODO
// This constructor will be called once and then
// solve will be called multiple times. So if
// you want to do some preprocessing ONCE before
// solve is called, you can do it here.
}
public byte[] solve (byte[][] start) {
// TODO
// The 2D array start will have the same format as
// the Board constructor from p1 so you can reuse
// your Board class from p1, although you might
// need to make some modifications to it.
}
//
// This method should return a minimal sequence of
// moves that would change the given board to the
// solved board.
throw new Runtime Exception ("Not implemented");
Transcribed Image Text:package p2; import java.util.Arrays; public class Solver { public Solver() { // TODO // This constructor will be called once and then // solve will be called multiple times. So if // you want to do some preprocessing ONCE before // solve is called, you can do it here. } public byte[] solve (byte[][] start) { // TODO // The 2D array start will have the same format as // the Board constructor from p1 so you can reuse // your Board class from p1, although you might // need to make some modifications to it. } // // This method should return a minimal sequence of // moves that would change the given board to the // solved board. throw new Runtime Exception ("Not implemented");
Expert Solution
steps

Step by step

Solved in 3 steps

Blurred answer