Array from recursive call being overwritten - java

We're making a program to solve an asterisk sudoku via a recursive approach with back tracking.
The solveIt method calls the solve method which is the recursive method. grid is declared before to be a 9x9 2D array that contains the puzzle to be filled in. If there is one solution, the program must print out the completed puzzle however if there are more solutions it must only print out the number of possible solutions.
Question is: Inside of solve, print(); works just fine and prints out the complete puzzle. However outside of the method it prints out the empty initial puzzle. Why is this? We cannot figure out why a separate variable (h in this case) also gets randomly overwritten when solve completes.
int[][] h;
int solutionCounter = 0;
void solve() {
int[] next = findEmptySquare();
if (!(next[0] == -1 && next[1] == -1)) {
if (grid[next[0]][next[1]] == 0) {
for (int i = SUDOKU_MIN_NUMBER; i <= SUDOKU_MAX_NUMBER; i++) {
if (!(givesConflict(next[0], next[1], i))) {
//fills in the puzzle
grid[next[0]][next[1]] = i;
//go to next number
solve();
}
}
grid[next[0]][next[1]] = 0;
}
} else {
//print(); here it works just fine
solutionCounter++;
h = grid.clone();
}
}
void solveIt() {
solve();
if (solutionCounter > 1) {
System.out.println(solutionCounter);
} else {
grid = h.clone();
print(); //here it prints the empty puzzle
}
}

Solution
The .clone() method seems to simply reference h to grid. So h points to grid and takes on its values leading to the problem we were having above.
Therefore the following solution was implemented:
//copy the grid into h.
for (int x = 0; x < 9; x++) {
for (int y = 0; y < 9; y++) {
h[x][y] = grid[x][y];
}
}
More information on clone():
https://www.geeksforgeeks.org/clone-method-in-java-2/

Related

algorithm visualization: implementing insertion sort without loops but with variable increments everytime a function is called

I'm building a sorting algorithm visualizer in processing (extension of java with extra libraries for visualization) and i'm very much stuck on this problem which I think others will be able to help me solve.
In processing there is a function called draw() that is being called 60 times each second. It's here that I want to execute, each time draw() is called, one step of the insertion algorithm. I already implemented it with a bubble sort. (see code below).
updateBubble() is being called in draw() and 'colors' is the name of the arraylist I use to keep the different values of colors to sort.
picture to get a better understanding:
[![visualisation algorithm preview][1]][1]
...
int j = 0
...
void updateBubble() {
bubble.sort(j);
j++;
if (i<bubble.colors.size()) {
if (j >= bubble.colors.size()-i-1) {
j = 0;
i++;
}
} else {
bubble.sorted = true;
}
}
and here is the function in the class BubbleSort (bubble is an object of this class)
void sort(int j) {
if (j<colors.size()-1) {
if (colors.get(j) > colors.get(j+1))
{
int temp = colors.get(j);
colors.set(j, colors.get(j+1));
colors.set((j+1), temp);
}
}
}
This way I was able to slow down the visualization process to the the pace of the framerate which I can control myself without using loops which would execute the sorting algorithm immediately. Now I also wanted to make a similar implementation for the insertion sort algorithm but i feel like i'm stuck because I don't seem to be able to use a similar implementation that works or there might be a better way to do this?
What I have at the moment executes it immediately as expected, without being able to see the process.
void updateInsertion() {
insertion.sort();
}
void sort() {
int n = colors.size();
for (int i = 1; i < n; ++i) {
int key = colors.get(i);
int j = i - 1;
while (j >= 0 && colors.get(j) > key) {
colors.set(j+1, colors.get(j));
j = j - 1;
}
colors.set(j+1, key);
}
}
this is what i got now: which is still wrong but is getting closer and clearifies what i'm trying to reach, making a function that only works with increments and if statements instead of whiles and fors so each different step is being executed with each call of the method.
// i resembles for loop variable
if (i<insertion.colors.size()) {
if (j<0 || insertion.colors.get(j) <= insertion.colors.get(i)) { // negative check to go out of while loop
insertion.colors.set(j+1, keap);
if(notSortedYet()){
i++;
keap = insertion.colors.get(i);
j = i - 1;
}
} else { // resembles being in the while loop
insertion.colors.set((j+1), insertion.colors.get(j));
j = j - 1;
}
}
}
EDIT: I fixed it and you can find my solution beneath :) everytime updateInsertion() is called, my code will execute exact one step in the algorithm! thanks to everyone who put effort into commenting, I dont know if this is best practise, so keep me updated on that if you want!
void updateInsertion() {
// i resembles for loop variable
if (i<insertion.colors.size()) {
if (j>=0 && insertion.colors.get(j) > firstUnsorted) {
int temp = insertion.colors.get(j+1);
insertion.colors.set((j+1), insertion.colors.get(j));
insertion.colors.set(j,temp);
j = j - 1;
} else {
insertion.colors.set(j+1, firstUnsorted);
if (i<insertion.colors.size()-1) {
i++;
}
firstUnsorted = insertion.colors.get(i);
j = i - 1;
}
}
}
I love this project.
Processing also have a millis() method which returns how many milliseconds were spent since you've started your sketch. I sometimes use it to time my animations, which could come in handy right here. Here's an implementation of a timer class:
class Delay {
int limit;
Delay (int l) {
limit = millis() + l;
}
boolean expired () {
return (millis() > limit);
}
}
I suggest that you use this class instead of tweaking the FPS. By using the Delay to slow down your implementation of the sort, you're letting the computer work at it's own rhythm and only draw a new frame when you need it. Like this (excuse the parts where I say "do stuff"):
Delay holdTheFrame = new Delay(1);
void draw() {
if(holdTheFrame.expired()) {
holdTheFrame = new Delay(500); // half a second before the next frame
// Advance one step forward in your sorting
// Draw the visualization of the data
}
}
You can fine tune at what pace your data is sorted and only paint it when it changes. It's win-win!
Have fun!
EDIT
To help you with the implementation, here's an example one. You can copy and paste this code in an empty Processing sketch and it'll run as-is. To make things easier on my side I print to console instead of using the graphical display, but you should be able to get what I'm doing.
The secret here is that my sorting algorithm have been subtly modified so they instead always run only ONE sorting step when I call them. See for yourself:
int _numberOfItems = 10;
int _sortingStep = 0;
IntList _bubbleList = new IntList();
boolean _bubbleListSorted = false;
IntList _selectionList = new IntList();
IntList _insertionList = new IntList();
Delay _delay = new Delay(1);
void setup() {
for (int i=0; i<_numberOfItems; i++) {
_bubbleList.append((int)random(10, 99));
}
for (int i=0; i<_numberOfItems; i++) {
_selectionList.append((int)random(10, 99));
}
for (int i=0; i<_numberOfItems; i++) {
_insertionList.append((int)random(10, 99));
}
}
void draw() {
if (_delay.expired()) {
_delay = new Delay(500);
// sort one step with every algo you want to display
if (!_bubbleListSorted) {
singleStepBubbleSort(_bubbleList);
}
if (_sortingStep < _numberOfItems) {
singleStepSelectionSort(_selectionList, _sortingStep);
singleStepInsertionSort(_insertionList, _sortingStep);
}
_sortingStep++;
// update the display (I'm printing to console instead for simplicity)
for (int i : _bubbleList) {
print(i + " ");
}
print(" | ");
for (int i : _selectionList) {
print(i + " ");
}
print(" | ");
for (int i : _insertionList) {
print(i + " ");
}
print("\n");
}
}
// An "single-step" implementation of Insertion Sort
void singleStepInsertionSort(IntList list, int step) {
int k = list.get(step);
int j = step - 1;
while (j >= 0 && list.get(j) > k) {
list.set(j+1, list.get(j));
j = j - 1;
}
list.set(j+1, k);
}
// An "single-step" implementation of Bubble Sort
void singleStepBubbleSort(IntList list) {
int temp;
boolean swapped = false;
for (int i=0; i<list.size()-1; i++)
{
if (list.get(i) > list.get(i + 1))
{
// swap arr[j] and arr[j+1]
temp = list.get(i);
list.set(i, list.get(i+1));
list.set(i+1, temp);
swapped = true;
}
}
if (!swapped) {
_bubbleListSorted = true;
}
}
// An "single-step" implementation of Selection Sort
void singleStepSelectionSort(IntList list, int step)
{
int min_idx = step;
for (int j = step+1; j < list.size(); j++) {
if (list.get(j) < list.get(min_idx)) {
min_idx = j;
}
}
int temp = list.get(min_idx);
list.set(min_idx, list.get(step));
list.set(step, temp);
}
class Delay {
int limit;
Delay (int l) {
limit = millis() + l;
}
boolean expired () {
return (millis() > limit);
}
}
Let me know if you have questions.
MORE EDITS:
Every swap of an insertion sort means many, many swaps. It's a real pain because this algorithm is kinda complicated to stop in it's tracks.
Luckily, I don't care. Thinking outside the box, I opted instead to create a class dedicated to sort an array while recording how to sort it, then be able to play it back "as if it was happening in real time". take a look:
int numberOfItems = 10;
int sortingStep = 0;
Delay delay = new Delay(1);
ManagedSelectionSort managedSelectionSort; // I created a class just to manage this madness
void setup() {
IntList list = new IntList();
for (int i=0; i<numberOfItems; i++) {
list.append((int)random(10, 99)); // some random numbers to sort later
}
managedSelectionSort = new ManagedSelectionSort(list); // take a look at the instantiation of this class
print("Step " + String.format("%02d", sortingStep) + ": ");
printArray(managedSelectionSort.list);
print("\n");
}
void draw() {
if (delay.expired()) {
delay = new Delay(100); // i put a very short delay, you'll probably want to tweak this
managedSelectionSort.sortOneStep(); // this is not what it seems
sortingStep++;
print("Step " + String.format("%02d", sortingStep) + ": ");
printArray(managedSelectionSort.list);
print("\n");
}
}
// this class is where the magic happens
// we'll sort the array all at once while recording every move
// then we'll play back those moves on a copy of the array
class ManagedSelectionSort {
IntList list, hiddenList; // list is the "official" list, while hiddenList is where the heavy lifting happens
ArrayList<SwapIndex> swapList; // this is where I record how to sort the array
ManagedSelectionSort(IntList baseList) { // this way I can instantiate several similar objects with the same list
list = new IntList();
hiddenList = new IntList();
swapList = new ArrayList<SwapIndex>();
for (int i : baseList) {
// both lists have the same initial numbers
list.append(i);
hiddenList.append(i);
}
// as soon as this object is instantiated, it knows how it'll sort the array
// because it already did...
hiddenSort();
}
// this method plays the moves which were recorded earlier according to the current sortingStep
// the swapList array was filled with every swap needed to sort the array, one by one
// now it's just a matter of playing them back on a copy of the initial array
void sortOneStep() {
if (sortingStep < swapList.size()) {
swap(list, swapList.get(sortingStep).index1, swapList.get(sortingStep).index2);
}
}
// this is the real implementation of the insertion sort
void hiddenSort()
{
for (int i=1; i<hiddenList.size(); i++) {
int j = i;
while (j>0 && hiddenList.get(j) < hiddenList.get(j-1)) {
swap(hiddenList, j, j-1, true); // swap is a class specific helper method, it swaps the numbers and also records the move
j--;
}
}
}
// this is an overload, i could have done without but it's confortable
void swap(IntList list, int index1, int index2) {
swap(list, index1, index2, false);
}
void swap(IntList list, int index1, int index2, boolean recordMove) {
// the swap first
int temp = list.get(index1);
list.set(index1, list.get(index2));
list.set(index2, temp);
// if the method is set on 'record', it adds this move to the swapList array
if (recordMove) {
swapList.add(new SwapIndex(index1, index2));
}
}
}
// this class could have been a struct, but I like to start in OOP right from the bat in case things gets complicated
class SwapIndex {
int index1;
int index2;
SwapIndex(int index1, int index2) {
this.index1 = index1;
this.index2 = index2;
}
}
// this method is just an helper method to print to console
void printArray(IntList list) {
for (int i : list) {
print(i + " ");
}
}
class Delay {
int limit;
Delay (int l) {
limit = millis() + l;
}
boolean expired () {
return millis() > limit;
}
}
This should solve your initial problem, if I understood it right this time!
One way to achieve this is via a some sort of stored state. Below is at a high level what I'm talking about.
// Starts the procedure. Must be called before draw().
void init() {
state = "forLoop";
i = 1;
n = colors.size();
}
// Single iteration of a loop.
void draw(){
switch(state) {
case "forLoop":
doForBody();
break;
case "whileLoop":
doWhileLoopBody();
break;
...
}
}
// Executes everything in the while loop and the one or two things
// just after it.
void doWhileLoopBody() {
if (isThisIterationOfWhileDone()) {
// Get out of the while loop and prepare for the next iteration of for.
// A better way to what I'm doing on the next couple lines here would
// be to introduce an additional state (ex: "postWhile") that would
// execute just after this method and would handle the colors.set(),
// incrementing i, etc.
state = "forLoop";
colors.set(j+1, key);
i++;
return;
}
// update colors, value of j, etc...
}
// Executes everything before the while loop.
void doForLoopBody() {
if (isThisIterationOfForDone()) {
state = "END";
return;
}
// update colors, get values of key and j initialized, etc
// switch to processing the body of the while loop
state = "whileLoop";
}

How to prevent string overlap on a 2D array?

I'm making battleships and I've currently come across an issue where my ships overlap. I've tried to incorporate an if statement that will judge whether it can be placed. Here's an example of me placing two ships of length 3 down.
public static void PlaceCruiser(String[][] board) {
ThreadLocalRandom random = ThreadLocalRandom.current();
int timesplaced = 0;
int size = 3;
while (timesplaced < 2) {
int randomcruisercheck =(int)(Math.random()*2);
if (randomcruisercheck == 0) {
int column = random.nextInt(0,9);
int row = random.nextInt(0,7);
if (row + 2 < 11 && board[row][column] == "." && board[row + 1][column] == "." && board[row + 2][column] == ".") {
for(int i = 0; i<size; i++)
{
board[row+i][column] = "#";
}
System.out.println(board[row][column]);
}
timesplaced++;
}
else if (randomcruisercheck == 1) {
int column = random.nextInt(0,9);
int row = random.nextInt(0,7);
if (column + 2 < 11 && board[row][column] == "." && board[row][column + 1] == "." && board[row][column + 2] == ".") {
for (int i = 0; i<size; i++)
{
board[row][column + i] = "#";
}
System.out.println(board[row][column]);
}
timesplaced++;
}
}
}
Basically, I use "#" to represent a ship in a 10x10 2D array of ".". I feel like the if statement about if the row or column plus 1 then plus 2 is a dot i.e a free space, a ship will be generated but this does not seem to be the case. Can anyone help me out?
Your code works well, you only need to take care of the indexes and initialize the board:
public class Main {
public static String[][] board;
public static void main(String[] args) {
PlaceCruiser pc = new PlaceCruiser();
board = new String[10][10];
// Initialize the board
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
board[i][j]=".";
}
}
pc.placeCruiser(board);
// Show thew board
for (int i=0;i<10;i++) {
for (int j=0;j<10;j++) {
System.out.print(board[i][j]);
}
System.out.println();
}
}
}
Result:
..........
..###.....
..........
..........
....#.....
....#.....
....#.....
..........
..........
..........
Also check that your initial position is not already "#".
Stylistical remarks:
if you use ThreadLocalRandom for generating position, you should also use it for other randomness (in other words: (int)(Math.random()*2) could rather be random.nextBoolean(), because actually a boolean could decide if ship should be horizontal or vertical)
nextInt(0,x) is just a longer variant of nextInt(x).
Actual bugs:
due to a presumably copy-paste issue, column (0-"9") and row (0-"7") are generated in the same way in both cases, making it possible to index out of the array when placing a vertical ship
which you seem to have noticed, but fixed it with that row + 2 < 11 check which has two problems in itself:
when row+2 ends up being 10 (which is <11), that is an invalid index (valid indices are 0...9)
as row stays between 0 and "7", there will not be horizontal ships in the last few rows
nextInt(a,b) generates numbers a...b-1, so it will not generate b itself
as the other answer points out string comparison with == generally and usually does not work, use equals()
Generally I would suggest having a single check+placement function, which can deal with an entire rectangle (given position+size). Also, I switched to array of characters, that simplifies both comparisons and printing.
boolean tryPlace(int x,int y,int width,int height) {
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
if(board[y+i][x+j]!='.') {
return false; // ship can not be placed
}
}
}
// if we reach here, ship can be placed
for(int i=0;i<height;i++) {
for(int j=0;j<width;j++) {
board[y+i][x+j]='#';
}
}
return true; // ship placed successfully
}
This routine could be called to place a pair of 3-long ships this way:
board=new char[10][10];
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
board[i][j]='.';
int size=3;
int amount=2;
while(amount>0) {
if(random.nextBoolean()) {
// horizontal
if(tryPlace(random.nextInt(10-size+1),random.nextInt(10),size,1)){
amount--; // one placed
}
} else {
// vertical
if(tryPlace(random.nextInt(10),random.nextInt(10-size+1),1,size)){
amount--; // one placed
}
}
}
// and a 4x2 mothership
while(!(random.nextBoolean()
?tryPlace(random.nextInt(7),random.nextInt(9),4,2)
:tryPlace(random.nextInt(9),random.nextInt(7),2,4)
));
for(int i=0;i<10;i++)
System.out.println(board[i]); // char[] has special overload for print/ln()
Test: https://ideone.com/DjYqjB
However, when I was a kid we had a rule that ships could not match, there had to be empty space (or a border of the board) around them. If you need that, tryPlace() could check a larger block, and put the ship into the middle of it. Also, a usual trick of implementing board games is that you can keep a larger array in the memory than what you will actually display. So instead of fighting with "check if field is empty or it is outside the board", it is simpler to have a 12x12 board, and place ships into the middle 10x10 portion of it:
boolean tryPlaceWithBorder(int x,int y,int width,int height) {
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
if(board[y+i][x+j]!='.')
return false; // ship can not be placed
// if we reach here, ship can be placed
for(int i=1;i<height-1;i++)
for(int j=1;j<width-1;j++)
board[y+i][x+j]='#';
return true; // ship placed successfully
}
and modified usage:
board=new char[12][12];
for(int i=0;i<12;i++)
for(int j=0;j<12;j++)
board[i][j]='.';
int size=3;
int amount=2;
while(amount>0) {
if(random.nextBoolean()) {
// horizontal
if(tryPlaceWithBorder(random.nextInt(12-size-1),random.nextInt(10),size+2,3))
amount--; // one placed
} else {
// vertical
if(tryPlaceWithBorder(random.nextInt(10),random.nextInt(12-size-1),3,size+2)){
amount--; // one placed
}
}
}
// and a 4x2 mothership
while(!(random.nextBoolean()
?tryPlaceWithBorder(random.nextInt(7),random.nextInt(9),6,4)
:tryPlaceWithBorder(random.nextInt(9),random.nextInt(7),4,6)
));
for(int i=1;i<11;i++)
System.out.println(String.valueOf(board[i],1,10));
Test: https://ideone.com/LXAD7T

How to avoid stackoverflow error for n = 8 in N Rooks problem

I want to solve N Rooks problem in N x N board using recursion with max N = 8. My code works fine for N = 2, 3, 4, 5, 6, 7. But when N = 8 it gives so many possible results starting with the first row of 1 0 0 0 0 0 0 0 then gives stackoverflow error before checking other possible results starting with the first row of 0 1 0 0 0 0 0 0.
I know about general recursion like fibonacci series, factorial, etc. and I can trace them down. Then I came across a new form of recursion called backtracking recursion. Then I sarted to learn the logic behind this form of recursion and read some pseudocode algorithms. Acually this form of recursion seemed to me a little bit harder to construct than normal recursion.
public class NRooks {
/**
* In this code r = which row, c = which column.
* lastY method just returns column c of last placed rook in
* a given row r in order to remove it.
* row.length, col.length, board.length have no special meaning. They all
* equal to the dimension of board N.
* main() method always initiates first row(r = 0). Therefore in main()
* method r remains 0 and c changes as you can see in putRook(0, i).
* So solve() method always begins from second row(r = 1).
*/
private static int found = 0;
private static int[][] board;
private static int[] row;
private static int[] col;
public static void putRook(int r, int c) {
board[r][c] = 1;
row[r] = 1;
col[c] = 1;
}
public static void removeRook(int r, int c) {
board[r][c] = 0;
row[r] = 0;
col[c] = 0;
}
public static boolean isValid(int r, int c) {
if (row[r] == 0 && col[c] == 0) return true;
return false;
}
public static void showBoard() {
for (int r = 0; r < board.length; r++) {
for (int c = 0; c < board.length; c++) {
System.out.print(board[r][c] + " ");
}
System.out.println();
}
System.out.println();
}
public static int lastY(int r) {
for (int j = 0; j < board.length; j++) {
if (board[r][j] == 1) return j;
}
return -1;
}
public static boolean solve(int r, int c) {
int last;
if (r == 0) return false;
if (r == col.length) {
found++;
/**
* When I dont include below printline statement my code
* works fine until N = 7 then gives SO error.
* But When I include this print statement in order
* to print number of results my code works fine until
* N = 6 then gives SO error
*/
//System.out.println("Found: " + found);
showBoard();
r--;
last = lastY(r);
removeRook(r, last);
c = last + 1;
}
for (int j = c; j < row.length; j++) {
if (isValid(r, j)) {
putRook(r, j);
return solve(r + 1, 0);
}
}
last = lastY(r - 1);
removeRook(r - 1, last);
return solve(r - 1, last + 1);
}
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
board = new int[n][n];
row = new int[n];
col = new int[n];
for (int i = 0; i < row.length; i++) {
boolean finished; // not important
putRook(0, i);
finished = solve(1, 0);
if (finished) System.out.println("============"); // ignore this too
}
}
}
Stackoverflow points to the lines that contain recursive calls to solve() method.
Note: I know only C like syntax of java and basic data abstraction. I wrote this code with this level of my Java.
I want to solve this problem and N queens problem myself.
Because there are so many solutions to these problems out there, both mathematically and algorithmically. And I am not interested in advanced Java data abstraction things right now.
I only want some advice about my code snippet above something like
Your backtracking algorithm is not efficient. (so straightfoward)
You need to use some Java data abstraction things to solve this problem efficiently.
You need to use another form of recursion like tail recursion (I heard about this too.)
....
The main issue why you're getting Stack Overflow error is the way your recursion is structured. The moment solve is invoked in the main method, it keeps recursing deeper and deeper; in fact, all of its invocations form a single several-thousand-calls-deep chain. For n=7, there are 3193 nested calls (I added a counter to check this). For n=8, it performs about 5k recursive calls before overflowing stack on my machine - I guess stack size is rather small by default.
Thus, to get this to work for higher values of n, you need to restructure your recursion in a way that doesn't perform all the recursive calls as a single chain. I could argue that your current solution isn't really backtracking because it never actually backtracks. Let me illustrate what backtracking means on a simpler problem. Let's say you want to print all binary strings of length n=3 ("000" through "111") programmatically, without relying on knowing the value of n. An implementation for this could be something like this:
def build_binary_string(current_prefix, chars_left):
if chars_left == 0:
print current_prefix
return
build_binary_string(current_prefix + 'a', chars_left - 1)
build_binary_string(current_prefix + 'b', chars_left - 1)
build_binary_string("", 3)
The interesting thing (backtracking!) happens at the moment when build_binary_string is invoked with arguments ("00", 1):
build_binary_string("000", 0) is invoked, prints "000" and returns immediately
we are back into build_binary_string("00", 1) function call, right about to execute build_binary_string(current_prefix + 'b', chars_left - 1)
build_binary_string("001", 0) is invoked, prints "001" and returns immediately
That point when control flow returned from build_binary_string("000", 0) to build_binary_string("00", 1) and it chose to make another function call was backtracking. Note that the depth of recursion never exceeded 3.
I cannot test your code as I do not have some of your methods, but is the int j = c supposed to be int j = r?
for (int j = c; j < row.length; j++) {
if (isValid(row, col, r, j)) {
putRook(b, row, col, r, j);
return solve(b, row, col, r + 1, 0);
}
}
Inside of this line you are passing 0 to c then declaring j=c in the for loop conditions so j < row.length will be true every time. I do not know what your isValid() is though.
return solve(b, row, col, r + 1, 0);
EDIT: I see now the c is being declared in the if block above, but if that if block does not get executed this should be an infinite loop afterward. Maybe check to see if r == col.length is executing correctly.

2048 change check method java

I am trying to write a 2048 game in java. I am trying to make it so it checks if the board has been changed, and if it was changed it will add to the move counter and add a number to the board. Otherwise it should not do anything. I am running into a bug where the method that checks if it was changed returns true every time and I can't seem to figure out why.
This is my isChecked method which should return true if the board has been changed and false otherwise.
public boolean isChanged(int [][]copy,int [][]orig){
if(copy.length!=orig.length){
System.out.print("INVALID MOVE");
return false;
}
for(int i=0;i<copy.length;i++){
for(int j=0;j<copy[i].length;j++){
if(copy[i][j]!=orig[i][j]) {
System.out.print("INVLAID MOVE");
return false;
}
}
}
System.out.println("VALID MOVE");
moves++;
return true;
}
Below are the method that handle left movement, combination, etc. the ones for up down and right are basically the same just with minor changes to change the direction so I decied not to include them in this post as I did not feel they were necessary
public void shiftLeft() {
for (int x = 0; x < board.length; x++) {
for (int y = board[x].length-1; y>0; y--) {
if (board[x][y -1] == 0 && board[x][y] != 0) {
board[x][y - 1] = board[x][y];
board[x][y] = 0;
if(y!=board[x].length-1)
y+=1;
}
}
}
}
public void combineLeft() {
for (int x = 0; x < board.length; x++) {
for (int y =board[x].length-2; y >=0; y--) {
if(board[x][y]==board[x][y+1]){
board[x][y]*=2;
board[x][y+1]=0;
}
}
}
}
public void left(){
int [][] copy=board.clone();
shiftLeft();
shiftLeft();
combineLeft();
shiftLeft();
if(isChanged(copy,board)==true)
addNum();
}
addNum() is simply a function that adds a number to a random empty position on the board. board is the class variable(these are all in the same class) which is a 2d int array which represents the game board.
Check the ischanged function. You are returning false if the corresponding values are not equal. Actually that means you are returning false if the board is not changed.
Or just do this:
if(copy[i][j]==orij[i][j]) //here I just replaced “!=“ with “==“
return false;
Also like #Talik said use deep copy
try using:
Arrays.copyOf(..)
I think clone just copies the reference on the arrays of the board into a new array. So every time you change board, you change the clone
other options are as seen here:
How to clone a multidimensional array in java?
a deep copy method
public static int[][] deepCopyIntMatrix(int[][] input) {
if (input == null)
return null;
int[][] result = new int[input.length][];
for (int r = 0; r < input.length; r++) {
result[r] = input[r].clone();
}
return result;
}
and cloning each row in the array manually

How would I represent a 1D array into a 2D in the case of the 8 Queens Puzzle

So I have this basic N Queen Program solver.
It is made so that it gives all the possible solutions in 1 Array. In other words, if I get an array with values : {5,3,2,1,7,8,5,3}, it would mean that the first index represent the row and the value of that index its column.
My issue with this program is that I have tried to "graphically" represent a chessboard with the solution of that array on it. The method "printTable" is supposed to convert that 1D array into a 2D array following the rules I have explained. I then tried to to implement that method into the QueenSolve method. This is where it gets nasty.
I have tried the printTable method and it works perfectly on its own, however when I use it with the QueenSolve method, It doesn't give me the expected result.
I must have done something wrong with the array. If you compile this code below, you will see that the first solution to the 8 Queens puzzle is fine, however as you go along, you will see that some Queens start to go on top of each other, and in the end it is really messy.
I was just wondering if there was a solution to my problem. I understand that there must be an issue revolving around the result array. I tried to find some ways of dealing with that by storing the result array (aka one solution) with an array list and then go one from there, however I would get some different results.
If anyone could just have a look through this program and have it compile. I would appreciate any sort of help.
Thanks!
import java.util.Arrays;
import java.util.ArrayList;
public class NQueens {
static int[] result;
private int board[][]=new int[8][8];
private int N =8;
private int u=0;
public boolean QueenChecker(int x, int y) {
for (int i = 0; i < x; i++) {
if ((result[i] == y) || (Math.abs(i - x) == Math.abs(result[i] - y))) {
return false;
}
}
return true;
}
public void QueenSolve(int x) {
for (int i = 0; i < result.length; i++) {
if (QueenChecker(x, i)) {
result[x] = i; // place the queen at this position.
if (x == result.length - 1) {
printTable(result,N);
}
QueenSolve(x + 1);
}
}
}
public void printTable(int result[], int N)
{
for(int s=0;s<result.length;s++){
for (int u=0;u<result.length;u++)
{
board[s][result[s]]=1;
}
for(int j=0;j<result.length;j++){
if(board[s][j]==1)
System.out.print("Q");
else
System.out.print("*" );
}
System.out.println();//"\n");
}
}
public void AllSolutions(int j)
{
System.out.println("Solution : "+ j);
printTable(result,N);
System.out.println();
}
public static void main(String[] args) {
int n = 8;
result = new int[n];
NQueens i = new NQueens();
i.QueenSolve(0);
}
}
One problem you have is that you are never clearing your board.
A quick 'n dirty solution to your problem is to make sure at the beginning of your print method that you get a "fresh" board.
public void printTable(int result[], int N)
{
// Clear the board.
board = new int[8][8];
for(int s=0;s<result.length;s++){
for (int u=0;u<result.length;u++)
{
board[s][result[s]]=1;
}
for(int j=0;j<result.length;j++){
if(board[s][j]==1)
System.out.print("Q");
else
System.out.print("*" );
}
System.out.println();//"\n");
}
// Line at the end to separate the different boards from one another.
System.out.println("---------------------");
}
This is just an obvious problem I spotted right away. There might be more - I didn't check thoroughly. And the solution I'm offering is not best practice but rather just a quick 'n dirty one. Once you have it working as you expect, I suggest you head over to https://codereview.stackexchange.com/ to ask how you can improve your code.

Categories