So the code below is an NQueens program that gives the correct true or false return of whether NQueens is possible with the given variable (ie if it is 3, then is it possible for a 3x3 board). What I'm having trouble with is finding out how many different possibilities there are for it. For example in a 4x4 there are 2 possibilities, so it should return true, (which it already does) and 2. I am not sure where to put this counter method or change the code so that it keeps going after one possibility.
Any advice?
package model;
public class NQueensModel
{
private int myNumsQueen;
private int myPossibilities;
private boolean[][] myBoard;
private static NQueensModel myModel = new NQueensModel(4);
public static void main (String[] args) {
System.out.println(myModel.solvePuzzle());
}
public NQueensModel(int nQueens)
{
myNumsQueen = nQueens;
myPossibilities=0;
myBoard = new boolean[myNumsQueen][myNumsQueen];
}
public boolean solvePuzzle()
{
return this.solvePuzzle(0);
}
private boolean solvePuzzle(int ncolumn)
{
if(ncolumn>myNumsQueen-1)
{
return true;
}
int i;
for( i =0; i<myNumsQueen;i++)
{
if(this.isSafeMove(i, ncolumn)==true)
{
this.placeQueen(i,ncolumn);
System.out.println(i + " " + ncolumn);
if(this.solvePuzzle(ncolumn+1)==true)
{
return true;
}
this.removeQueen(i, ncolumn);
}
}
return false;
}
private boolean isSafeMove(int row, int col)
{
if(this.checkLowerDiag(row, col)==true ||this.checkUpperDiag(row, col)==true ||this.checkLeft(row,col)==true)
{
return false;
}
else
{
return true;
}
}
private boolean checkUpperDiag(int row, int col)
{
if(row==0)
{
return false;
}
else
{
for(int i=row, j = col; i>=0 && j>=0; i--, j--)
{
if(myBoard[i][j]==true)
{
return true;
}
}
return false;
}
}
private boolean checkLowerDiag(int row, int col)
{
if(col==0 )
{
return false;
}
else
{
for(int i = row, j = col; i<myNumsQueen && j>=0; i++, j--)
{
if(myBoard[i][j]==true)
{
return true;
}
}
return false;
}
}
private boolean checkLeft(int row, int col)
{
if(col==0)
{
return false;
}
else
{
for(int i = col; i>=0; i--)
{
if(myBoard[row][i]==true)
{
return true;
}
}
return false;
}
}
private boolean placeQueen(int row, int col)
{
myBoard[row][col] = true;
return true;
}
private boolean removeQueen(int row, int col)
{
myBoard[row][col] = false;
return false;
}
// public String toString()
// {
//
// }
}
Below is some sudo code of one possible solution. It keeps a running count of all the valid solutions you have discovered thus far. When a new solution is discovered you add it to the count and return. This will complete until all possible solutions are discovered.
public int solvePuzzle(int solutionCount, int col){
if(isValidSolution())
return solutionCount + 1;
else if(solutionFails())
return solutionCount;
else {
for(/*Every position you want to check in this col*/){
solutionCount = solvePuzzle(solutionCount, col + 1);
}
return solutionCount;
}
}
Related
First of all there is a lot of code because i really don't know where my issue is, I do apologise!
I'm making a program that solves a varying size puzzle for eg (3x3 with 0-8) The zero represents a blank tile the objective is to move the the blank tile around until the goal state is reached. At the moment I am using Depth First Search to solve the puzzle. Netbeans returns a 'OutOfMemory' error when i run the program however if I change the goal state so it only requires one move to complete it displays the solution. Below is my code, I've only added some of the classes because I don't want this post being ridiculously long. Please let me know if you require the other classes
EDIT: Inserted wrong code for board class
Depth First Search Class
package npuzzle;
import java.util.ArrayList;
import java.util.Stack;
public class DFSearch {
public static void search(int[][] initial, int[][] goal, int rows, int columns)
{
Board board = new Board(initial, goal, rows, columns, "");
Node root = new Node(board);
Stack<Node> stack = new Stack<Node>();
stack.add(root);
performSearch(stack, board);
}
public static void performSearch(Stack<Node> s, Board board)
{
int searchCount = 1;
while (!s.isEmpty())
{
Node tNode = (Node) s.pop();
//if not goal state
if (!tNode.getCurrentState().isGoalState())
{
ArrayList<State> tChildren = tNode.getCurrentState().gChildren();
for (int i = 0; i < tChildren.size(); i++)
{
Node newNode = new Node(tNode, tChildren.get(i), tNode.getGCost() + tChildren.get(i).findCost(), 0);
if(!isRepeatedState(newNode))
{
s.add(newNode);
}
}
searchCount++;
}
else
{
tNode.getCurrentState().printState();
System.exit(0);
//PRINTING OF DIRECTIONS
}
}
System.out.println("Error! No solution found!");
}
private static boolean isRepeatedState(Node c)
{
boolean returnVal = false;
Node checkNode = c;
while(c.getParent() != null && !returnVal)
{
if (c.getParent().getCurrentState().equals(checkNode.getCurrentState()))
{
returnVal = true;
}
c = c.getParent();
}
return returnVal;
}
}
Board Class
package npuzzle;
import java.util.ArrayList;
import java.util.Arrays;
public class Board implements State
{
private int PUZZLE_SIZE = 0;
private int outOfPlace = 0;
private int rows;
private int columns;
private int[][] GOAL;
private int[][] currentBoard;
private String directions = "";
public Board(int[][] initial, int[][] goal, int N, int M, String direction)
{
currentBoard = initial;
GOAL = goal;
rows = N;
columns = M;
PUZZLE_SIZE = rows*columns;
directions = direction;
setOutOfPlace();
}
#Override
public boolean isGoalState() {
if (Arrays.deepEquals(currentBoard, GOAL))
{
return true;
}
return false;
}
#Override
public ArrayList<State> gChildren() {
ArrayList<State> children = new ArrayList<State>();
int[] blanktile = getBlankTile();
int[] newblanktile = Arrays.copyOf(blanktile, blanktile.length);
if (blanktile[0] != 0) {
newblanktile[0]--;
Swap(newblanktile, blanktile, children, "up");
newblanktile = Arrays.copyOf(blanktile, blanktile.length);
}
if (blanktile[1] != 0) {
newblanktile[1]--;
Swap(newblanktile, blanktile, children, "left");
newblanktile = Arrays.copyOf(blanktile, blanktile.length);
}
if (blanktile[0] != (this.rows - 1)) {
newblanktile[0]++;
Swap(newblanktile, blanktile, children, "down");
newblanktile = Arrays.copyOf(blanktile, blanktile.length);
}
if (blanktile[1] != (this.columns - 1)) {
newblanktile[1]++;
Swap(newblanktile, blanktile, children, "right");
newblanktile = Arrays.copyOf(blanktile, blanktile.length);
}
return children;
}
#Override
public double findCost() {
return 1;
}
#Override
public void printState() {
System.out.println(directions);
}
#Override
public boolean equals(State s) {
if (Arrays.deepEquals(currentBoard, ((Board) s).getCurrentBoard()))
{
return true;
}
else
return false;
}
private void setOutOfPlace() {
int i = 0;
int j = -1;
do
{
if (j == (columns - 1)) {j = 0; i++;}
else {j++;}
if (currentBoard[i][j] != GOAL[i][j])
{
outOfPlace++;
}
} while (((i+1)*(j+1)) < PUZZLE_SIZE);
}
private int[] getBlankTile()
{
int i = 0;
int j = -1;
int[] blanktile = {0,0};
do
{
if (j == (columns - 1)) {j = 0; i++;}
else {j++;}
if (currentBoard[i][j] == 0) {
blanktile[0] = i;
blanktile[1] = j;
}
} while (((i+1)*(j+1)) < PUZZLE_SIZE);
return blanktile;
}
public int getOutOfPlace()
{
return outOfPlace;
}
private int[][] copyBoard(int[][] state)
{
int[][] returnArray = new int[rows][columns];
for (int i = 0, j = 0; i*j < PUZZLE_SIZE; i++, j++)
{
returnArray[i] = Arrays.copyOf(state[i], state[i].length);
}
return returnArray;
}
private void Swap(int[] nbt, int[] bt, ArrayList<State> children, String direction) {
int[][] cpy = copyBoard(currentBoard);
int temp = cpy[nbt[0]][nbt[1]];
cpy[nbt[0]][nbt[1]] = currentBoard[bt[0]][bt[1]];
cpy[bt[0]][bt[1]] = temp;
children.add(new Board(cpy, this.getGOAL(), this.getRows(), this.getColumns(), (this.getDirections() + direction + ", ")));
}
public int getPUZZLE_SIZE() {
return PUZZLE_SIZE;
}
public int getRows() {
return rows;
}
public int getColumns() {
return columns;
}
public int[][] getGOAL() {
return GOAL;
}
public int[][] getCurrentBoard()
{
return currentBoard;
}
public String getDirections()
{
return directions;
}
}
I am trying to create a clone of myBoard[][] because right now when I try to return it I get all false values which can't be right.
Where exactly would I clone it, and how, so that I would get a copy of a myBoard[][] with legitimate values instead of all false? I am trying to return it at the bottom with public boolean[][] getBoard()
package model;
public class NQueensModel
{
private int myNumsQueen;
public int myPossibilities=0;
private boolean[][] myBoard;
private boolean[][] myGridBoard;
public static void main (String[] args) {
//...
}
public NQueensModel(int nQueens)
{
myNumsQueen = nQueens;
myPossibilities=0;
myBoard = new boolean[myNumsQueen][myNumsQueen];
}
public boolean solvePuzzle()
{
return solvePuzzle(0);
}
private boolean solvePuzzle(int ncolumn)
{
if(ncolumn>myNumsQueen-1)
{
myPossibilities++;
}
int i;
for( i =0; i<myNumsQueen;i++)
{
if(this.isSafeMove(i, ncolumn)==true)
{
this.placeQueen(i,ncolumn);
if(this.solvePuzzle(ncolumn+1)==true)
{
return true;
}
this.removeQueen(i, ncolumn);
}
}
return false;
}
private boolean doIt(int county)
{
if(county>0)
{
return true;
}
else
{
return false;
}
}
private boolean isSafeMove(int row, int col)
{
if(row <0 || row>=myNumsQueen || col<0 || col>=myNumsQueen)
{
return false;
}
else if(this.checkLowerDiag(row, col)==true ||this.checkUpperDiag(row, col)==true ||this.checkLeft(row,col)==true)
{
return false;
}
else
{
return true;
}
}
private boolean checkUpperDiag(int row, int col)
{
if(row==0)
{
return false;
}
else
{
for(int i=row, j = col; i>=0 && j>=0; i--, j--)
{
if(myBoard[i][j]==true)
{
return true;
}
}
return false;
}
}
private boolean checkLowerDiag(int row, int col)
{
if(col==0 )
{
return false;
}
if(row==myNumsQueen-1){
return false;
}
else
{
for(int i = row, j = col; i<myNumsQueen && j>=0; i++, j--)
{
if(j>=myNumsQueen)
{
return false;
}
else if(myBoard[i][j]==true)
{
return true;
}
}
return false;
}
}
private boolean checkLeft(int row, int col)
{
if(col==0)
{
return false;
}
else
{
for(int i = col; i>=0; i--)
{
if(i>=myNumsQueen)
{
return false;
}
else if(myBoard[row][i]==true)
{
return true;
}
}
return false;
}
}
private boolean placeQueen(int row, int col)
{
if(col>=myNumsQueen)
{
return false;
}
myBoard[row][col] = true;
return true;
}
private boolean removeQueen(int row, int col)
{
myBoard[row][col] = false;
return false;
}
public int getPossibilities(){
return myPossibilities;
}
public boolean[][] getBoard()
{
for(int i = 0; i<5; i++)
{
for(int j = 0; j<5; j++)
{
System.out.println("myBoard : " +myBoard[i][j]);
}
}
return myBoard;
}
}
Well, if you're just looking to create a cloned array, you would have to build it by iterating over the old array and copying the values over:
for (int i = 0; i < oldArray.length; ++i)
for (int j = 0; j < oldArray[0].length; ++j)
newArray[i][j] = oldArray[i][j];
As you are using native types you can use clone().
public static boolean[][] clone2DArray(boolean [][] array){
// this clone is a shallow copy
boolean[][] newArray =(boolean[][]) array.clone();
//now you need to clone each array cause still referring to the same
for(int i=0;i<array.length;i++){
newArray[i]=Arrays.copyOf(array[i],array[i].length);
//newArray[i]=(boolean[])array[i].clone(); this is valid too
}
return newArray;
}
Read more in Arrays#copyOf()
I'm using java and am trying to make a program that uses recursion to solve the NQueens puzzle. The problem is it is giving me true when it shouldn't be (for example 3 should return false because you can NQueen a 3x3 grid). I have looked through everything multiple times but I cannot find where things go wrong. Anyone have any idea?
package model;
public class NQueensModel
{
private int myNumsQueen;
private boolean[][] myBoard;
private static NQueensModel myModel = new NQueensModel(3);
public static void main (String[] args) {
System.out.println(myModel.solvePuzzle());
}
public NQueensModel(int nQueens)
{
myNumsQueen = nQueens;
myBoard = new boolean[myNumsQueen][myNumsQueen];
}
public boolean solvePuzzle()
{
return this.solvePuzzle(myNumsQueen);
}
private boolean solvePuzzle(int ncolumn)
{
if(ncolumn>myNumsQueen)
{
return true;
}
int i;
for( i =0; i<myBoard.length;i++)
{
if(this.isSafeMove(i, ncolumn)==true)
{
myBoard[i][ncolumn-1]=true;
if(this.solvePuzzle(ncolumn+1)==true)
{
return true;
}
myBoard[i][ncolumn]=false;
}
}
return false;
}
private boolean isSafeMove(int row, int col)
{
for(int i=0; i<myBoard[row].length; i++)
{
if(myBoard[row][i]==true)
{
return false;
}
}
for(int i = 0; i<myBoard.length; i++)
{
if(myBoard[i][col-1]==true)
{
return false;
}
}
if(this.checkLowerDiag(row, col)==true)
{
return false;
}
if(this.checkUpperDiag(row, col)==true)
{
return false;
}
if(this.checkLeft(row,col)==true)
{
return false;
}
else
{
return true;
}
}
private boolean checkUpperDiag(int row, int col)
{
if(row==0)
{
return true;
}
else if(col==myBoard[0].length)
{
if (myBoard[row-1][col-2]==true)
{
return true;
}
else
{
return false;
}
}
else if(myBoard[row-1][col-2]==true || myBoard[row-1][col]==true)
{
return true;
}
else
{
return false;
}
}
private boolean checkLowerDiag(int row, int col)
{
if(col==1 && myBoard[row][col]==true)
{
return true;
}
else if(col == myBoard[0].length)
{
if(myBoard[row+1][col-2]==true)
{
return true;
}
else
{
return false;
}
}
else if(row == myBoard.length)
{
return true;
}
else if(myBoard[row+1][col-2]==true || myBoard[row+1][col]==true)
{
return true;
}
else
{
return false;
}
}
private boolean checkLeft(int row, int col)
{
if(myBoard[row][col-1]==true)
{
return true;
}
else
{
return false;
}
}
private boolean placeQueen(int row, int col)
{
myBoard[row][col] = true;
return true;
}
private boolean removeQueen(int row, int col)
{
myBoard[row][col] = false;
return false;
}
// public String toString()
// {
//
// }
}
I'm having some issues implementing backtracking for solving a maze, the issue I'm having is that if the player gets to a dead end, it doesn't go back to where it have another solution. In the case i developed just by coincidence at first it worked because of the order of the methods, but if i put that the player moves first east, it reaches a dead end and doesn't backtrack. Here is the code:
import java.util.ArrayList;
public class Laberinto {
int posicionX = 0;
int posicionY = 0;
int largo = 6;
int ancho = 6;
int solX = 5;
int solY = 4;
boolean[][] cordenadas = new boolean[largo][ancho];
int[] bloqueadasX = {1,2,3,4,5,5,0,2,3,4,5,0,2,3,4,5,3,0,1,5};
int[] bloqueadasY = {0,0,0,0,0,1,2,2,2,2,2,3,3,3,3,3,4,5,5,5};
public ArrayList<Coordenada> recorridas = new ArrayList<Coordenada>();
public Laberinto(int xo,int yo) {
posicionX = xo;
posicionY = yo;
recorridas.add(new Coordenada(posicionX,posicionY));
}
public void recorrer() {
if(posicionX==solX && posicionY == solY) {
System.out.println("Solucion encontrada");
}
else {
if(este(posicionX,posicionY)) recorrer();
if(norte(posicionX,posicionY)) recorrer();
if(sur(posicionX,posicionY)) recorrer();
if(oeste(posicionX,posicionY)) recorrer();
volver(new Coordenada(posicionX,posicionY));
}
}
public void armarLaberinto() {
for(int i=0;i<ancho;i++) {
for(int j=0;j<largo;j++) {
cordenadas[j][i] = estaBloqueada(j,i);
}
}
}
public boolean estaBloqueada(int x,int y) {
for(int i=0;i<bloqueadasX.length;i++) {
if(x==bloqueadasX[i] && y==bloqueadasY[i]) {
return true;
}
}
return false;
}
public boolean norte(int x,int y) {
if(dentroTablero(x,y-1)) {
if(!yaRecorrido(new Coordenada(x,y-1))) {
if(estaBloqueada(x,y-1)) {
return false;
}
posicionY = posicionY-1;
recorridas.add(new Coordenada(x,y));
return true;
}
return false;
}
return false;
}
public boolean sur(int x,int y) {
if(dentroTablero(x,y+1)) {
if(!yaRecorrido(new Coordenada(x,y+1))) {
if(estaBloqueada(x,y+1)) {
return false;
}
posicionY = posicionY+1;
recorridas.add(new Coordenada(x,y));
return true;
}
return false;
}
return false;
}
public boolean este(int x,int y) {
if(dentroTablero(x+1,y)) {
if(!yaRecorrido(new Coordenada(x+1,y))) {
if(estaBloqueada(x+1,y)) {
return false;
}
posicionX = posicionX+1;
recorridas.add(new Coordenada(x,y));
return true;
}
return false;
}
return false;
}
public boolean oeste(int x,int y) {
if(dentroTablero(x-1,y)) {
if(!yaRecorrido(new Coordenada(x-1,y))) {
if(estaBloqueada(x-1,y)) {
return false;
}
posicionX = posicionX-1;
recorridas.add(new Coordenada(x,y));
return true;
}
return false;
}
return false;
}
public boolean dentroTablero(int x, int y) {
if((x >=0 && x<=ancho) && (y>=0 && y<=largo) ) {
return true;
}
return false;
}
public boolean yaRecorrido(Coordenada a) {
for(int i=0;i<recorridas.size();i++) {
if(recorridas.get(i).getX() == a.getX() && recorridas.get(i).getY() == a.getY()) {
return true;
}
}
return false;
}
public void volver(Coordenada a) {
recorridas.remove(a);
}
public void bloqueadas() {
armarLaberinto();
for(int i=0;i<ancho;i++) {
for(int j=0;j<largo;j++) {
if(!cordenadas[j][i]) {
if(j==solX && i==solY) {
System.out.print("M");
}
else {
System.out.print(" ");
}
}
else {
System.out.print("◘");
}
}
System.out.println();
}
}
public void mostrarRecorrido() {
armarLaberinto();
for(int i=0;i<ancho;i++) {
for(int j=0;j<largo;j++) {
if(!cordenadas[j][i]) {
if(j==solX && i==solY) {
System.out.print("M");
}
else {
if(yaRecorrido(new Coordenada(j,i))) {
System.out.print("•");
}
else {
System.out.print(" ");
}
}
}
else {
System.out.print("◘");
}
}
System.out.println();
}
}
public static void main(String[] args) {
Laberinto laberinto = new Laberinto(0,0);
laberinto.armarLaberinto();
laberinto.bloqueadas();
laberinto.recorrer();
laberinto.mostrarRecorrido();
System.out.println(laberinto.posicionX);
System.out.println(laberinto.posicionY);
}
}
One possible bug is you have a global for your position. This would confuse your search a lot, once the first call fails to find the solution. Try to keep posicionX,posicionY as local to that function if possible.
So I'm trying to run my pacman project as a jar(also tried runnable) and I just get the error message you see in the title. It runs perfectly fine in eclipse/netbeans, but whilst cleaning/building i see the warnings:
Note: C:\Users\Lucas\Documents\Eclipse\PackMan\src\game\packman\GameData.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
The main class is correct and assigned. Does anybody know what I'm doing wrong?
Here is my GameData class
public class GameData {
int mazeNo;
CopyOnWriteArrayList<Position> pills;
CopyOnWriteArrayList<Position> powerPills;
public MoverInfo packman;
public GhostInfo[] ghostInfos = new GhostInfo[4];
public int score;
Maze[] mazes;
boolean dead = false;
boolean win = false;
public GameData() {
mazes = new Maze[4];
// load mazes information
for (int m=0; m<4; m++) {
mazes[m] = new Maze(m);
}
setMaze(mazeNo);
}
private void setMaze(int m) {
packman = new MoverInfo(mazes[m].packmanPos);
for (int g=0; g<4; g++) {
ghostInfos[g] = new GhostInfo(mazes[m].ghostPos);
}
pills = new CopyOnWriteArrayList((List<Position>)(mazes[m].pills.clone()));
powerPills = new CopyOnWriteArrayList((List<Position>)(mazes[m].powerPills.clone()));
}
public void movePackMan(int reqDir) {
if (move(reqDir, packman)) {
packman.curDir = reqDir;
} else {
move(packman.curDir, packman);
}
}
private int wrap(int value, int incre, int max) {
return (value+max+incre)%max;
}
private boolean move(int reqDir, MoverInfo info) {
// current position of packman is (row, column)
int row = info.pos.row;
int column = info.pos.column;
int rows = mazes[mazeNo].rows;
int columns = mazes[mazeNo].columns;
int nrow = wrap(row, MoverInfo.DROW[reqDir], rows);
int ncol = wrap(column, MoverInfo.DCOL[reqDir], columns);
if (mazes[mazeNo].charAt(nrow, ncol) != '0') {
info.pos.row = nrow;
info.pos.column = ncol;
return true;
}
return false;
}
public void update() {
if (pills.contains(packman.pos)) {
pills.remove(packman.pos);
score += 5;
} else if (powerPills.contains(packman.pos)) {
powerPills.remove(packman.pos);
score += 50;
for (GhostInfo g:ghostInfos) {
g.edibleCountDown = 500;
}
}
for (GhostInfo g:ghostInfos) {
if (g.edibleCountDown > 0) {
if (touching(g.pos, packman.pos)) {
// eat the ghost and reset
score += 100;
g.curDir = g.reqDir = MoverInfo.LEFT;
g.pos.row = mazes[mazeNo].ghostPos.row;
g.pos.column = mazes[mazeNo].ghostPos.column;
g.edibleCountDown = 0;
}
g.edibleCountDown--;
} else {
if (touching(g.pos, packman.pos)) {
dead = true;
}
}
}
// level is cleared
if (pills.isEmpty() && powerPills.isEmpty()) {
mazeNo++;
if (mazeNo < 4) {
setMaze(mazeNo);
} else if (mazeNo == 5) {
win = true;
} else {
// game over
dead = true;
}
}
}
private boolean touching(Position a, Position b) {
return Math.abs(a.row-b.row) + Math.abs(a.column-b.column) < 3;
}
public void moveGhosts(int[] reqDirs) {
for (int i=0; i<4; i++) {
GhostInfo info = ghostInfos[i];
info.reqDir = reqDirs[i];
if (move(info.reqDir, info)) {
info.curDir = info.reqDir;
} else {
move(info.curDir, info);
}
}
}
public int getWidth() {
return mazes[mazeNo].width;
}
public int getHeight() {
return mazes[mazeNo].height;
}
public List<Integer> getPossibleDirs(Position pos) {
List<Integer> list = new ArrayList<>();
for (int d=0; d<4;d++) {
Position npos = getNextPositionInDir(pos, d);
if (mazes[mazeNo].charAt(npos.row, npos.column) != '0') {
list.add(d);
}
}
return list;
}
private Position getNextPositionInDir(Position pos, int d) {
int nrow = wrap(pos.row, MoverInfo.DROW[d], mazes[mazeNo].rows);
int ncol = wrap(pos.column, MoverInfo.DCOL[d], mazes[mazeNo].columns);
return new Position(nrow, ncol);
}
}