Added functionality to allow for a board to be generated and check if the board is solvable.

This commit is contained in:
Jonathan Turner 2024-02-03 14:21:37 -05:00
parent 945ef8fff6
commit e98ad869e8
5 changed files with 168 additions and 5 deletions

View File

@ -3,6 +3,10 @@ package Assignments.A1;
// Potentially will be changed to an UI Implementation with JavaFX if time permits. // Potentially will be changed to an UI Implementation with JavaFX if time permits.
import Assignments.A1.managers.BoardGenerator;
import Assignments.A1.models.Board;
import Assignments.A1.models.Piece;
/** /**
* Board will be used to save locations in a 2D array. * Board will be used to save locations in a 2D array.
* *
@ -16,6 +20,24 @@ package Assignments.A1;
*/ */
public class Driver { public class Driver {
public static void main(String[] args) {
Board board = BoardGenerator.generateBoard();
System.out.println(board);
System.out.println(BoardGenerator.isSolvable(board));
Piece[] pieces = new Piece[9];
pieces[0] = new Piece(0,7);
pieces[1] = null;
pieces[2] = new Piece(2,5);
pieces[3] = new Piece(3,1);
pieces[4] = new Piece(4,2);
pieces[5] = new Piece(5,4);
pieces[6] = new Piece(6,6);
pieces[7] = new Piece(7,3);
pieces[8] = new Piece(8,8);
board = new Board(pieces);
System.out.println(BoardGenerator.isSolvable(board));
}
} }

View File

@ -1,5 +1,95 @@
package Assignments.A1.managers; package Assignments.A1.managers;
import Assignments.A1.models.Board;
import Assignments.A1.models.Piece;
import java.util.*;
/**
* This class is used to create and check boards.
*
* @author Jonathan Turner
* @version Spring 2024
*/
public class BoardGenerator { public class BoardGenerator {
/**
* Generates a random 8-Puzzle that is always solvable.
*
* @precondition none
* @postcondition none
*
* @return a board that is solvable.
*/
public static Board generateBoard() {
Integer[] values = {1, 2, 3, 4, 5, 6, 7, 8};
List<Integer> random = new ArrayList<>(Arrays.asList(values));
Collections.shuffle(random);
Random gen = new Random();
int spaceLoc = gen.nextInt(9);
Piece[] pieces = new Piece[9];
for (int curr = 0; curr < values.length; curr++) {
if (curr < spaceLoc) {
pieces[curr] = new Piece(curr,random.get(curr));
} else {
pieces[curr+1] = new Piece(curr+1,random.get(curr));
}
}
// Checks if the board is solveable.
Board generated = new Board(pieces);
if (isSolvable(generated)) {
return generated;
} else { // If not it swaps the last two values (ignoring the space)
if (spaceLoc == 8) {
pieces[7].setLocation(6);
pieces[6].setLocation(7);
} else if (spaceLoc == 7) {
pieces[8].setLocation(6);
pieces[6].setLocation(8);
} else {
pieces[7].setLocation(6);
pieces[6].setLocation(7);
}
generated = new Board(pieces);
}
// Puzzle is now solvable.
return generated;
}
/**
* Checks if the board is solvable by checking the number of inversions.
* If the number of inversions is even, it is solvable, if not it is not solvable.
*
* @precondition board != null
* @postcondition none
*
* @param board the board being checked
* @return if the board has even inversion, True
* if not, False
*/
public static boolean isSolvable(Board board) {
if (board == null) {
return false;
}
// Holds the number of inversions
int inversions = 0;
Piece[] ordered = board.getPiecesInOrder();
// Counts the number of inversions
for (int index = 0; index < 8; index++) {
for (int invers = index+1; invers < 8; invers++) {
if (ordered[index].getValue() > ordered[invers].getValue()) {
inversions++;
}
}
}
return (inversions % 2 == 0);
}
} }

View File

@ -1,6 +1,7 @@
package Assignments.A1.models; package Assignments.A1.models;
import java.util.Arrays; import java.util.Arrays;
import java.util.Random;
/** /**
* This class keeps track of the current state (whether in permutation or not) of the board. * This class keeps track of the current state (whether in permutation or not) of the board.
@ -45,6 +46,21 @@ public class Board {
} }
} }
/**
* Constructor used to create a board with a pre-provided piece list.
*
* @precondition pieces == 9
* @postcondition a board is created with given locations
*
* @param pieces the provided state.
*/
public Board(Piece[] pieces) {
if (pieces.length != 9) {
throw new IllegalArgumentException("The pieces list must be size 9.");
}
this.pieces = pieces;
}
/** /**
* Checks the status of a place on the board. If the location is taken or not. * Checks the status of a place on the board. If the location is taken or not.
@ -195,10 +211,10 @@ public class Board {
if (this.getClass() != o.getClass()) { if (this.getClass() != o.getClass()) {
return false; return false;
} }
Board other = (Board) o; Piece[] other = ((Board) o).getPiecesInOrder();
for (int i = 0; i < 9; i++) { Piece[] ordered = this.getPiecesInOrder();
if (this.pieces[i].getValue() != other.pieces[i].getValue() for (int curr = 0; curr < ordered.length; curr++) {
|| this.pieces[i].getLoc() != other.pieces[i].getLoc()) { if (ordered[curr] != other[curr]) {
return false; return false;
} }
} }
@ -213,7 +229,11 @@ public class Board {
public String toString() { public String toString() {
String result = ""; String result = "";
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
result += i + " "; if (pieces[i] == null) {
result += 0 + " ";
} else {
result += pieces[i] + " ";
}
if ((i+1) % 3 == 0) { if ((i+1) % 3 == 0) {
result += "\n"; result += "\n";
} }

View File

@ -1,11 +1,16 @@
package Assignments.A1.models; package Assignments.A1.models;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author Jonathan Turner * @author Jonathan Turner
* @version Spring 2024 * @version Spring 2024
*/ */
public class EightPuzzle { public class EightPuzzle {
private List<Board> boards = new ArrayList<>();
} }

View File

@ -60,6 +60,21 @@ public class Piece {
this.setLoc(newLoc); this.setLoc(newLoc);
} }
/**
* Should only be used when creating the board to set its location.
*
* @precondition location is valid
* @postcondition new location set
*
* @param newLoc the new location
*/
public void setLocation(int newLoc) {
if (invalidLocation(newLoc)) {
throw new IllegalArgumentException("The location should be valid.");
}
this.loc = newLoc;
}
/** /**
* Gets the location of the piece. * Gets the location of the piece.
* *
@ -110,6 +125,17 @@ public class Piece {
return board.isTaken(desiredLoc); return board.isTaken(desiredLoc);
} }
/**
* Turns any string call of the class to just its value.
* @precondition none
* @postcondition none
* @return the value of the piece.
*/
@Override
public String toString() {
return String.valueOf(this.value);
}
/* Private Methods Below. End of Java Docs. */ /* Private Methods Below. End of Java Docs. */
/* Sets the location for both Moving and Initialization. */ /* Sets the location for both Moving and Initialization. */