I've been learning some Java in my spare time and I'm a beginner, so I'm very sorry if I don't understand some simple concepts. I've been trying to make a "Robot" move around an already made map. I've been trying to make lines of a text file into multiple arrays (ie. moving forward, turning left, turning right). Then, I've been trying to use values in those arrays to make the robot move. Basically, if the text file says:
1 0 0
0 1 0
0 0 1
So the first line is for moving, the second is for turning left and the third is for turning left. This is supposed to make the robot move, and then not turn. Then it moves on to the next column and doesn't move, turns left, and doesn't turn right. I'm trying to make sure it works no matter how long the code is. I'm able to put it into three arrays correctly, but I'm having trouble with this for loop. When the loop executes and the values are all 1's or above, it works perfectly. However, if any value is a 0, it completely exits the loop and the robot doesn't move. Any help or advice would be appreciated! Thank you!
Code is below:
public static void robotMove(Robot x) throws Exception {
for (int i = 0; i < movedata.length; i++) {
int y = movedata[i];
int s = leftdata[i];
int j = rightdata[i];
for (int a = 0; a < movedata.length; a++) {
if (y == 0) {
//asking what to put here
}
else {
again.Move(x, y);
}
if (s == 0) {
//asking what to put here
}
else {
again.Left(x, s);
}
if (j == 0) {
//asking what to put here
}
else {
again.Right(x, j);
}
}
}
Assuming that movedata, leftdata and rightdata are the 3 arrays of same size corresponding to each line of your example, without knowing what again is but assuming it is the object handling the .Move(), .Left() and Right() actions made on the Robot x, I think the following should be enough:
public static void robotMove(Robot x) throws Exception {
for (int i = 0; i < movedata.length; i++) {
if (y != 0) {
again.Move(x, movedata[i]);
}
if (s != 0) {
again.Left(x, leftdata[i]);
}
if (j != 0) {
again.Right(x, rightdata[i]);
}
}
}
You can loop just once through movedata, I've removed the second nested loop.
If the value is 0, you do not want to do anything. Hence you don't need an else part for that, just put code in the if value != 0.
From a code perspesctive, it would be cleaner if instead of having some if taking care that the value is not 0, you may implement the "inaction" directly in the methods .Move(), .Left() and .Right().
Related
I began developing a "Spaceship vs Comets" style game last week and now I have come to a stop.
The purpose of the game is to shoot the comets before they pass your ship. You make the comets explode by firing at them. Simple idea!
However, sometimes when I play I get the "IndexOutOfBounds" error. It almost always appears when I haven't fired for a while (The size of my shots ArrayList is 0) and when I then fire and it collides it crashes.
So I have some kind of error in my code, but I really can't see it. I now hope that one of you might see why this accurs and save me from further "IndexOutOfBounds" errors! :)
Here is the part of the code that fails, including the functions that I use to move the comets and shots:
GAME CLASS
if(!Game.player.getShots().isEmpty() && !comet.getComets().isEmpty()) { //Om de är tomma så ignorera
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()) {
for(int y = 0; y < comet.getComets().size(); y++) { //Comets Y
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x)) && !comet.getComets().isEmpty() && !Game.player.getShots().isEmpty()) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
}
}
}
}
}
//Comet spawn timer
comet.addComets();
//Move the comets and shots!
Game.player.moveShots();
comet.moveComets();
repaint();
COMET CLASS
public ArrayList<Rectangle> getComets() {
return comets;
}
public void moveComets() {
if(!comets.isEmpty()) {
for(int x = 0; x < comets.size(); x++) {
comets.get(x).x -= cometSpeed;
}
}
}
PLAYER CLASS (Shots are in this class)
public void fire() {
shots.add(new Rectangle(x + player.width, y + 23, shotWidth,shotHeight));
}
public ArrayList<Rectangle> getShots() {
return shots;
}
public void moveShots() {
if(!shots.isEmpty()) {
for(int x = 0; x < shots.size(); x++) {
shots.get(x).x += fireSpeed;
}
}
}
Keep in mind that comets and shots are both "ArrayList out of the object Rectangle"
I will provide screenshots of error and a picture of the game below!
The error line is marked in the code above, the if statement should block it from crashing (I thought).
Thanks in advance! All help is appreciated! :)
You should change the order at the if statement to avoid it from evaluate one part of it.
You should change your condition to:
if( x < Game.player.getShots().size() && comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
That's because you're removing a shot and inside the comets for when the shoot is removed at the next comet iteration it will throw IndexOutOfBounds as the array no longer have the shot you're checking at the if, so you'll need to check again for the x existing on shots.
You can also do it at the for, you check for both conditions and you let the intersect as only check at the if.
A better performance if would be:
if(!Game.player.getShots().isEmpty() || !comet.getComets().isEmpty()) {
//if one of them is empty, won't be intersections
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
for(int y = 0; y < comet.getComets().size() && x < Game.player.getShots().size(); y++) {
//Comets Y only if the shoot still available
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
y = 0; // if you don't set the y = 0 the next shoot (as you removed the x, getShots.get(x) would be the x + 1 shoot) will only evaluate for the comets after y, won't evaluate the firsts comets at the array.
}
}
}
}
Try to adjust here if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()). You are checking for comet array twice.
Let me know if it works.
Is this code multithreaded?
I am also wondering why you are verifying comet.getComets().isEmpty() so many times.
My guess is that you are manipulating the ArrayList in some other part of your code. Reason I think this is because you are checking the size of the list multiple times and because within the for loop you are only deleting in the end, so that should not be the problem.
For instance if you run this method at two threads at the same time, the ArrayList can be checked at one point, but can reduce after checking the size. then when for instance the size was 10, but became 9, but you still try to delete x with value 10, you will get the out of bounds error.
So, I'm creating a game, and when the user's player hits a location(There are many), I want it to be game over.
I have two ArrayLists like this.
ArrayList<Integer> ex = new ArrayList<Integer>(), ey = new ArrayList<Integer>();
And the 'bad' square (which the user dies if they hit it) appear after they've gotten a powerup, so there are Integers added on often.
I've trying to do a for loop to loop through the size(shown below), but that doesn't work as i only selects the latest one, obviously.
for(int i = 0; i < ex.size() - 1; i++) {
if(x.get(0)==ex.get(i) && y.get(0) == ey.get(i)){
gameover = true;
}
}
If I just loop through the whole arrayList like this
(int i : ex)
Then it gives me this(below) error upon starting the game:
Exception in thread "Animation Thread" java.lang.IndexOutOfBoundsException: Index: 10, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at snakegame.SnakeGame.draw(SnakeGame.java:113)
at processing.core.PApplet.handleDraw(PApplet.java:2386)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
at processing.core.PApplet.run(PApplet.java:2256)
at java.lang.Thread.run(Thread.java:745)
So, is there anyway to store all the numbers of the ArrayList in one variable?
You are getting confused with the semantics of the "enhanced for"
for(int i = 0; i < ex.size() - 1; i++) {
puts into i the values 0, 1, 2... up to ex.size()-1. i works as the index
for(int i : ex) {
puts into i the values ex.get(0), ex.get(1). It is the content.
In the second case, the logic should be
int j = 0;
for (int i : ex) {
if(x.get(0) == i && y.get(0) == ey.get(j)){
..
}
j++;
}
In this case the enhanced for makes little sense.
If it helps you visualize, thing that with enhanced for, the variable must be always of the type of the array / iterator (in this case, it just happens that you can autooutbox Integer to int)
From what I understand, you have an x,y grid in which there are coordinates that cause the user to die. As your user moves through the grid, you want to check whether or not the square they're currently on is a bad square.
Instead of two ArrayLists, it might be better to store it as a multidimensional array.
class Grid {
private int[][] spaces;
public Grid(int xdim, int ydim) {
spaces = new int[xdim][ydim];
for (int x=0; x<xdim; x++) {
for (int y=0; y<ydim; y++) {
spaces[x][y] = 0;
}
}
}
private void addBadSpace(int x, int y) {
spaces[x][y] = 999;
}
private boolean isBadSpace(int x, int y) {
return (spaces[x][y] != 0);
}
}
Whether you take this approach depends on the size of your application and your grid. The multidimensional array will be very quick, but will take up a lot of space in memory. If it's a sparse matrix (i.e. very few 'bad' spaces exist) and your grid is very large, there are more efficient approaches.
To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.
I am trying to write quick sort in java. But getting a stack over flow error for very small set of inputs. In the createArray function I am taking input by the Scanner object.
Please somebody help me in this.
public class quickSort {
static int[] ar;
int number;
public static void main(String args[]) {
CreatingArray ca = new CreatingArray();
ar = ca.createArray();
ca.printArray(ar);
int len = ar.length;
sort(0,(len-1));
System.out.println("");
System.out.println("Array after QuickSort:");
ca.printArray(ar);
}
public static void sort(int l,int h) {
int i=l;
int j=h;
int temp =0;
int pivot = ar[(l + (l+h)/2)];
while(i <= j) {
while(ar[i] < pivot) {
i++;
}
while(ar[j] > pivot) {
j--;
}
if (i<=j) {
temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
i++;
j--;
}
}
if(l<j){
sort(l,j);
}
if(i<h) {
sort(i,h);
}
}
}
int pivot = ar[(l + (l+h)/2)];
This line is wrong. It only gets the center point when l == 0. If, say, l == 4 && h == 7 (e.g. the upper half of an 8-element array), you get 4 + (4+7)/2 which is 9 and thus outside the bounds. You really want l + (h-l+1)/2.
The first thing that can happen because of this is ArrayIndexOutOfBoundsException, but you never get that because you always recurse on the lower partition first and run into the second problem. Swap the two ifs at the end of the function to see this in action.
The second thing that can happen is that, because pivot is not actually an element in the range [i, j], the element search at the start of the loop can go crazy. In particular, pivot could be a very small value that is smaller than any in the range. The i search will terminate immediately (leaving i == l the way it started), while the j search will run way beyond i, which means the if won't be entered either, i still doesn't change, and the main loop terminates. Because i is unchanged, i<h is still true (assuming l<h was), and you enter the recursive call with exactly the same arguments you just had, which means the next call will do exactly the same thing as the current one, ending in infinite recursion.
I think your recursive calls don't end... debug your code with very small input - say 3 numbers... check when and how sort() is being called..
At the moment, I have this:
do{
if (i < y){ //y is a constant
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
else {
break;
}
} while (!endline.equals(null)); // endline is changed during each loop cycle
With this loop, and the inputs I have, endline can not be null; this renders the while loop breaking condition redundant. When I try and convert this loop to a for loop, I get a misplaced construct error from Eclipse.
i.e:
for (i < y) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search(); }
Whilst, the while loop I have works, it seems like bad practice to me.
Any suggestions? Thanks.
If you don't need to check endLine, you can still use a while loop:
while (i < y) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
If you also need to check endLine:
while (i < y && !endline.equals(null)) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
Note: the difference between do / while (your initial code) and while { } is that in the first case the loop is always run at least once. With a while { }, it is not run at all if the condition is not true at the beginning. That is the same behaviour as a for loop (won't run if the condition is false before the loop).
If you want to use a for loop, you need to have all three parts of a standard for. Since you have two conditions, they need to be both included in the condition part:
for ( ; i < y && !endline.equals(null); ) {
ObsHandler.obsPartsHandler();
ObsHandler.search();
}
You probably have some initialization code for i, like i=0, which could also go into the initialization section of the for loop. Otherwise, if all you have is a set of conditions to check without some array or list you are iterating, while or do is really the better fit.
A while loop seems like the natural choice for your code. I would just simplify it to:
do {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
} while (i < y && !endline.equals(null)); // endline is changed during each loop cycle
or, if you need to check the conditions before:
while (i < y && !endline.equals(null)) {
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
for (boolean start=true;(start || endline != null) && i < y;){
start=false;
ObsHandler.obsPartsHandler(); //increment i twice
ObsHandler.search();
}
(startendline != null) is only tested the second time.
i < y is only tested the first time.