Java creation of a spiral [duplicate] - java
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Looping in a spiral
I'm creating a program to populate a 3 by 3 matrix. I want to result in something looking like this
5 4 3
6 1 2
7 8 9
As you have probably noticed it is a spiral.
Now the algorithm I'm using is this: I have a 2-d array where the values represent the coordinates of the number. First I assign that every number coordinate in this array will have a value of 10. Then starting at 9 I decrease my x coordinate and assign the value of the coordinate to currentnum - 1 until it reaches the end or its value is not 10; Then I do the same thing except I increase the value of Y; Then decrease the value of x; Then of Y;
The reason I assign 10 to every number is so like it acts as a road for my program. Since current num will never exceed 9. If the value of a square is 10 it is like a green light. If it is not 10 meaning a value has been assigned to that square it breaks out of it.
Here is my code, please note it is written in Java
public class spiral {
/**
* #param args
*/
public static void main(String[] args) {
int spiral [] [] = new int[3][3];
for(int i = 0; i <= 2; i++){
for(int j = 0; j <= 2; j++){
spiral[i][j] = 10;
}
}
//0 is x value, 1 is y value
spiral[0][0] = 9;
int x = 1;
int y = 1;
int counter = 1;
int currentnum = 9;
int gridsquare = 3;
for(int i = 0; i <= 8; i++){
if(counter == 5){
counter = 1;
}
if(counter == 1){
System.out.println(x + " " + y);
for(int j = 0;j <= 1;j++){
if(spiral[x][y] == 10){
spiral[x][y] = currentnum;
currentnum--;
x += 1;
}
else{
y += 1;
break;
}
}
}
if(counter == 2){
for(int k = 0; k <= 0; k++){
System.out.print(x + " " + y);
if(spiral[x][y] == 10){
spiral[x][y] = currentnum;
currentnum--;
y += 1;
}
else{
x -= 1;
break;
}
}
}
if(counter == 3){
for(int z = 0; z <= 0; z++){
if(spiral[x][y] == 10){
spiral[x][y] = currentnum;
currentnum--;
x -= 1;
}
else{
y -= 1;
break;
}
}
}
if(counter == 4){
for(int b = 0; b <= 0; b++){
if(spiral[x][y] == 10){
spiral[x][y] = currentnum;
currentnum--;
y -= 1;
}
else{
x += 1;
break;
}
}
}
counter++;
}
System.out.print(currentnum);
}
}
I'm getting this error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at spiral.main(spiral.java:44)
Since I'm new to Java would someone please suggest a posible fix for this. Also if you see any problems with my algorithm please do inform me.
You do not need to pre-fill with 10: zero works just as well.
I think the best approach to solving the spiral is to think of how you do it manually: start in a corner, and go horizontally until you hit non-zero or an edge of the array. Then you turn right. Stop when the current number goes past N*N.
Now let's look at what each part of the algorithm means:
Starting in the corner means setting x=0 and y=0.
Going in a straight line means x=x+dx, y=y+dy, where either dx or dy is zero, and dy or dx is 1 or -1.
Turning right means assigning dx to dy and -dy to dx.
Here is how it looks in the code:
int current = 1;
// Start in the corner
int x = 0, y = 0, dx = 1, dy = 0;
while (current <= N*N) {
// Go in a straight line
spiral[x][y] = current++;
int nx = x + dx, ny = y + dy;
// When you hit the edge...
if (nx < 0 || nx == N || ny < 0 || ny == N || spiral[nx][ny] != 0) {
// ...turn right
int t = dy;
dy = dx;
dx = -t;
}
x += dx;
y += dy;
}
You've incremented x or y to 3 which is past the end of one of your arrays.
Step through your program with the debugger or add System.out.println statements before each if (counter) to find out where you're doing this.
Related
How to find circumference and area of a 2D shape whose indices are given as 0 or 1 in a 2D array?
Given a 2D array of size 20x20 whose values resemble a 2D shape, for example a square or rectangle: public static int[][] rectangle= { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; I would like to find its circumference and area in an algorithm that does the following: Finds the nearest (1) point starting from the center (point[10][10]). Uses the nearest (1) point as a starting point to iterate over all the remaining 1s to count the circumference. calculates the number of zeros enclosed by the circumference to calculate the area Now below is where I am currently at; the "guess" method calculates the nearest (1) point and executes the "count" method which then calculates the circumference. public static void guess() { boolean found = false; if(!found) { int y = 10; for(int x = 10; x <= 20; x++) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y++]==1) { rectangle[x][y] = 2; found = true; break; } } } if(!found) { int y = 10; for(int x = 10; x >= 0; x--) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y--]==1) { rectangle[x][y] = 2; found = true; break; } } } if(!found) { int x = 10; for(int y = 10; y <= 20; y++) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y++]==1) { rectangle[x][y] = 2; found = true; break; } } } if(!found) { int x = 10; for(int y = 10; y >= 0; y--) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y--]==1) { rectangle[x][y] = 2; found = true; break; } } } for(int i = 0; i < 20; i++) { for(int j = 0; j < 20; j++) { if(rectangle[i][j] == 2) { Count(i, j); break; } } } } public static void Count(int x, int y) { public int circumf; int tx = x; int ty = y; for(int c = 40; c >=0; c--) { if((c/2)-1<0 || x>=20 || x<0 || y>=20 || y<0) break; if(rectangle[x][(int) (c/2)-1]==1 || rectangle[(int) (c/2)-1][y]==1 || rectangle[x++][y]==1 || rectangle[x][y++]==1 || rectangle[x--][(int) (c/2)-1]==1 || rectangle[(int) (c/2)-1][y--]==1 || rectangle[x--][y]==1 || rectangle[x][y--]==1) { circumf++; } } x = tx; y = ty; for(int c = 0; c <=40; c++) { if((c/2)>=20 || x>=20 || x<0 || y>=20 || y<0) break; if(rectangle[x][(int) (c/2)]==1 || rectangle[(int) (c/2)][y]==1 || rectangle[x++][y]==1 || rectangle[x][y++]==1 || rectangle[x--][(int) (c/2)]==1 || rectangle[(int) (c/2)] [y--]==1 || rectangle[x--][y]==1 || rectangle[x][y--]==1) { circumf++; } } System.out.print(circumf); Now, the guess method calculates the nearest point correctly, however the count method doesn't correctly counts the circumference which is close to 70 in the above example. As for the area calculating algorithm, I still didn't quite figure it out. The above code isn't the most brilliant or organized thing I know, but any help would be really appreciated!
Suppose you find the nearest one at index [i][j]. You need to check the nearest values in a cross pattern since your object is a rectangle. For example you are in the middle one in the left edge of the rectangle: 0 1 0 0 1 0 0 1 0 You check were the 1's "continue" finding thus the edge direction. There are 2 possible outcomes either [x-1][y]=[x][y]=[x+1][y] or [x][y-1]=[x][y]=[x][y+1]==1 So,you found that the edge is vertical. Continue iterating through this verical line until the condition [x][y-1]==1 is false. Then do the same thing for the horizontal line. Now for the 0's count you could store the index i,j of all the corners while you are doing the above check.If you know their positions and the size of the array is fixed you can calculate the 0's like: 0's area = [(DL_corner_index - 1) - (UL_corner_index + 1)] x [(UR_corner_index - 1) - (UL_corner_index + 1)] int rectangle[10][10] ={ {0,0,0,0,0,0,0,0,0,0}, {0,1,1,1,1,1,1,1,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0} }; //calculating area of zeros with known corner coordinates //you have stored the coordinates in variables like this int UL_X=1,UR_X=8; int UL_Y=1,DL_Y=8; int area = ((UR_X-1) - UL_X)*((DL_Y-1)-UL_Y); cout<<area; //36 }
Programming a battleships ship placing algorithm(java)
So im programming a battleships game, and im trying to place ships on a board. I can get it to place the ship going left and going down from the starting point but cant get it going down or left. I understand my method overall is in-effeicient. public static int[][] SetUserBoard(int[][] board) { int x; int y; y = 0; for (int z = 0; z < 10; z++) { String gridv; gridv = ""; int direction; System.out.println("Set the Position for Ship no. " + (z+1)); Scanner s1 = new Scanner(System.in); System.out.println("Enter the grid column(A-H):"); gridv = s1.nextLine(); if (gridv.equals("A")) { y = 0; } if (gridv.equals("B")) { y = 1; } if (gridv.equals("C")) { y = 2; } if (gridv.equals("D")) { y = 3; } if (gridv.equals("E")) { y = 4; } if (gridv.equals("F")) { y = 5; } if (gridv.equals("G")) { y = 6; } if (gridv.equals("H")) { y = 7; } System.out.println("Enter the y co=ordinate: "); x = s1.nextInt(); x -= 1; System.out.println("Enter the direction of the ship 0-3(0=down,1=right,2=up,3=left): "); direction = s1.nextInt(); if(z == 0) { //placing 4 unit ship in first increment if(direction == 0 && x < 5){ //vertical placement - down for(int i=0; i < 4; i++) { board[x][y] = 0; x += 1; } } if(direction == 1 && y < 5) { //horizontal placement - right for(int i=0; i < 4; i++) { board[x][y] = 0; y += 1; } } if(direction == 2 && x > 3 ) { //vertical placement - up for(int i=0; i < 4; i++) { board[x][y] = 0; x -= 1; } } if(direction == 3 && y > 3) { //horizontal placement - left for(int i=0; i < 4; i++) { board[x][y] = 0; y -= 1; } } } ...if(z > 0 && z < 3) { //placing 3 unit ships in 2nd and 3rd increment.... return board; } if you ignore the bottom part, and focus on the if z=0 part as that's which part i'm using to test this with my most updated try. Originally I had an indexing error which I managed to solve but now all the program does is run as usual except when moving onto the next one the board isn't updated and is still empty. So im stumped as to what logic to use for up/left.
For diagonal changes, you need to alter both i and j as you traverse the ship. For instance: UP_LEFT = 4 ... ship_len = 4 ... if(direction == UP_LEFT && y > ship_len-1 && x > ship_len-1) { // SE-NW placement for(int i=0; i < ship_len; i++) { board[x][y] = 0; y -= 1; x -= 1; } }
JAVA - Check if value is not in other index 2D array
Im stuck on this part of a school project where I have to get the shortest route between two co-ordinates (Traveling Salesman Problem). I made a litle something here to get the co-ords of the nearest neighbour, but a few co-ords have the same closest neighbour, and I dont want that. I thought of something to clear that issue, but it isn't working, and I can't figure out why. distance is the current distance between the current position and every other. shortestDistance kind of speaks for itself I think. locations[20][3] is a 2D array in which I store the Xco-ord, the Yco-ord and the nearest neighbour for each co-ord. X is in [x][0], Y in [x][1] and neighbour in [x][2] for(int i = 0; i < 20; i++){ int shortestDistance = 100; int distance; //Looking for nearest neighbour 20 times for(int j = 0; j < 20; j++){ //Looking for the closest neighbour here distanceX = locations[i][0] - locations[j][0]; distanceY = locations[i][1] - locations[j][1]; //To prevent a negative distance: if(distanceX < 0){ distanceX = distanceX * -1; } if(distanceY < 0){ distanceY = distanceY * -1; } //Add distance distance = distanceX + distanceY; //If current distance is shorter then the shortestdistance, to prevent it does'nt see itself as 'neighbour' and to prevent another co-ord has the same neighbour, which happens in isOk(); if(distance < shortestDistance && distanceX + distanceY != 0 && isOk(j)){ shortestDistance = distance; locations[i][2] = j; } } } Function isOk is: private boolean isOk(int j){ boolean result = false; for(int i = 0; i < 20; i++){ if(locations[i][2] == j){ result = false; } else{ result = true; } } return result; } So, I what I'm asking is what I am doing wrong? I still get some items(in 20 * 10 storage) that have the same item as its nearest neighbour.
You probably have to initialize the neighbors to something that will be ok for your isOK method. A such value is, for instance, -1. for(int i = 0; i < 20; i++) locations[i][2] = -1; The isOk contains also a small mistake. The loop should be stopped when j has been found as neighbor of another location: private boolean isOk(int j){ for(int i = 0; i < 20; i++){ if (locations[i][2] == j) return false; } return true; }
Maze not working?
code: Array is a predefined boolean array that I made, and val is the length of the array (it is a square). I use it as a starting point, rather than using a random value import java.util.*; import javax.swing.*; public class Main { public void main() { String Val = JOptionPane.showInputDialog("Enter the number of rows/columns"); int x = Integer.parseInt(Val); boolean mazeArch[][] = new boolean [x][x]; BoundariesDeclared(mazeArch, x); generateMaze(mazeArch, x); convertArray(mazeArch, x); } public void printArray(String Array[][]) // Prints out the array { for (int i =0; i < Array.length; i++) { for (int j = 0; j < Array.length; j++) { System.out.print(" " + Array[i][j]); } System.out.println(""); } } public void convertArray(boolean Array[][], int z) { String RealArray[][] = new String [z][z]; for(int x = 0; x < Array.length; x++) { for(int y = 0; y < Array.length; y++) { if(Array[x][y] == true) { RealArray[x][y] = "*"; } if(Array[x][y] == false) { RealArray[x][y] = " "; } } } printArray(RealArray); } public void BoundariesDeclared(boolean Array[][], int y) { for(int x = 0; x < Array.length; x++) Array[0][x] = true; for (int x = 0; x < Array.length; x++) Array[x][0] = true; for (int x = 0; x < Array.length; x++) Array[x][Array.length-1] = true; for (int x = 0; x < Array.length; x++) Array[Array.length-1][x] = true; } public void generateMaze(boolean Array[][], int val) { Stack<Integer> StackX = new Stack<Integer>(); Stack<Integer> StackY = new Stack<Integer>(); int x = val / 2; // Start in the middle int y = val / 2; // Start in the middle StackX.push(x); StackY.push(y); while(!StackX.isEmpty()) { Array[x][y] = true; // is Visited x = StackX.peek(); y = StackY.peek(); if(Array[x][y+1] == false) { StackX.push(x); StackY.push(y+1); y = y + 1; } else if(Array[x][y-1] == false) { StackX.push(x); StackY.push(y-1); y = y - 1; } else if(Array[x+1][y] == false) { StackX.push(x+1); StackY.push(y); x = x+1; } else if(Array[x-1][y] == false) { StackX.push(x-1); StackY.push(y); x = x-1; } else { StackX.pop(); StackY.pop(); } } } } Whenever I print the results, I only get stars, which mean that every single boolean is set to true. I understand my error, because I am visiting every spot the result will be that they are all set to true. But what can i do to fix this? I think I have the concept correct, just not the application. I previously asked the question and was told that I need to make two Arrays (1 for walls, another for visiting) but how would I apply this as well?
You didn't mention what are you trying to do. So not much we can help. What is this maze doing? What's your input? What's your expected result? Add this line and debug yourself. public void generateMaze(boolean Array[][], int val) { Stack<Integer> StackX = new Stack<Integer>(); Stack<Integer> StackY = new Stack<Integer>(); int x = val / 2; // Start in the middle int y = val / 2; // Start in the middle StackX.push(x); StackY.push(y); while (!StackX.isEmpty()) { Array[x][y] = true; // is Visited x = StackX.peek(); y = StackY.peek(); if (Array[x][y + 1] == false) { StackX.push(x); StackY.push(y + 1); y = y + 1; } else if (Array[x][y - 1] == false) { StackX.push(x); StackY.push(y - 1); y = y - 1; } else if (Array[x + 1][y] == false) { StackX.push(x + 1); StackY.push(y); x = x + 1; } else if (Array[x - 1][y] == false) { StackX.push(x - 1); StackY.push(y); x = x - 1; } else { StackX.pop(); StackY.pop(); } convertArray(Array, val); // add this line } }
The solution is still the same as when you last posted this question - you need to have two arrays -one that is true for every place in the maze that is a wall - the maze's tiles -one that starts all false - the solver's tiles The solver can move onto a tile only if both arrays are false at that point, and sets the second array (the solver's tiles) to true while leaving the first array (the maze's tiles) alone.
This is not a 'coding' bug, per say. You simply don't know what behavior you want. Try commenting out the line where you generate the maze. Run your program with 6 as a parameter. You get: * * * * * * * * * * * * * * * * * * * * What kind of maze is this? Where is the exit? Again, this is not a coding issue, this is a design flaw. Of course if you start within the bounds of this maze, you will visit all of the squares!
I'm not clear what do you expect in your output exactly, but I can see where the issue is. In your generateMaze() method you are travelling like in spiral mode which ends up touching each and every node in the end. Like suppose you have 5x5 array, you travel and make true like (boundaries are already true) [2,2]->[2,3]->[3,3]->[3,2]->[3,1]->[2,1]->[1,1]->[1,2]->[1,3] you start from middle, you start visiting and take turns just before you find already true (boundary or visited), and it covers all the nodes
Java Contaning box Seems to get bigger and Bigger
I am writing a bouncing ball class (I'm just starting to use Java) and it works but it looks like every time the ball hits an edge the containing box gets bigger Code for the bounce trigger int i = 0; int j = 0; int k = 0; double x = 3; double y = 3; while(i < 200){ if(j == 0){ x += 2; } else { x -= 2; } if(k == 0){ y += 4; } else { y -= 4; } if(thisEye.getX() > 400){ j = 1; } if(thisEye.getX() < 0) { j = 0; } if(thisEye.getY() > 200){ k = 1; } if(thisEye.getY() < 0) { k = 0; } Color someShade = rGen.nextColor(); // var for the color of the eyes Color someOtherShade = rGen.nextColor();// var for the color of the pupules moveThis(thisEye,x,y,someShade); // Go over all the shapes with the same X,Y offset - var x,y moveThis(thisPupul,x,y,someOtherShade); moveThis(thisEye2,x,y,someShade); moveThis(thisPupul2,x,y,someOtherShade); moveThis(face,x,y,rGen.nextColor()); moveThis(nose,x,y,rGen.nextColor()); pause(150.0); // wait for next cycle to slow down the images //i++; this was to see if it just got farther off with each loop, it dose. } } private void moveThis(GOval subject, double x, double y, Color newShade){ subject.setFillColor(newShade); subject.move(x, y); } the 'face' will bounce off the right spot once then each time it bounces it gets farther and farther off the screen tell is so far of the it only is on screen for a short time then off the other side tell it comes back on screen for a bit. I marked it as home work but I'm a html/php coder in the day and am just using the iTunesU Stanford videos at night. but I'm trying to learn so pointers would be great.
The problem could be (though very unlikely) with your theEye.getX() and theEye.getY() method. What if you change your boundary condition check from if(thisEye.getX() > 400){ j = 1; } if(thisEye.getX() < 0) { j = 0; } if(thisEye.getY() > 200){ k = 1; } if(thisEye.getY() < 0) { k = 0; } TO if(x > 400){ j = 1; } if(x < 0) { j = 0; } if(y > 200){ k = 1; } if(y < 0) { k = 0; } Otherwise, please post the complete source code so we can see where else could the problem be.