I need to write some methods for a game in java and one of them is int[] findStone. The method returns an array, which gives the coordinate of the element that I am searching.
The field looks like this and is defined like this: private static int[][] gamefield = new int[8][6];
So if I use the method: findStone(3)[0], it should return 0 for the x coordinate and for findStone(3)1, 2. This is the code that I wrote.
private static int[] findStone(int stone) {
int[] position = new int[2];
for(int x = 0; x < 8; x++ ){
for(int y = 0; y < 6; y++ ) {
int a = gamefield[x][y];
int i = x;
int j = y;
if(a == stone) {
position[0] = i;
position[1] = j;
}
break;
}
}
return position;
}
The problem is: The method only returns the x-coordinates for the first row corectly, for the other elements it shows me 0. Could someone explain me what I did wrong and what I should change? Please, only simple explanation. I am only at the beginning and I don't have experience in java.
Thank you :)
You probably intended to put your break clause inside the if block. The way you have it now, the break keyword has no effect. It just breaks the inner loop (with y variable), but since this block of code ends here anyway, it simply does nothing.
You're searching for a single point on your map, so when you find the stone position, you can immediately return it, as there's nothing more to do.
Moreover, you don't need additional variables, a, i and j. Using them is not wrong, but code looks clearer and is more concise without them. Have a look at this code:
private static int[] findStone(int stone) {
int[] position = new int[2];
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 6; y++) {
if (gamefield[x][y] == stone) {
position[0] = x;
position[1] = y;
return position;
}
}
}
return null; // if there's no given stone
}
Related
I am writing an AI to play Mancala and this is my method in which the AI's calculations are done by examining the outcomes of all 6 possible moves. I use the array staticBoardState to restore boardState (which stores the information about all of the holes on the board) back to its original values after each examination of move outcomes, but staticBoardState seems to be changing in odd ways even though I believe that I do not change it. I am a beginner amateur coder, so please ask questions if my code does not make sense. This is my code:
public int getBotCalc(int boardState[]) {
int[] staticBoardState = boardState;
double[] movePoints = new double[6];
int initialScore = boardState[6];
int scorePoints;
int freeTurnPoints;
double bestMovePoints;
int bestMove;
for(int f = 0; f <= 5; f++) {
boardState = staticBoardState;
int botChoice = f;
int botHole = boardState[botChoice];
boardState[botChoice] = 0;
for(int g = 0; g < botHole; g++) {
botChoice++;
if(botChoice>12) {
botChoice = 0;
}
boardState[botChoice]++;
}
if(botChoice<=5&&boardState[botChoice]==1&&boardState[12-botChoice]>=1) {
boardState[6] += boardState[12 - botChoice] + 1;
boardState[botChoice] = 0;
boardState[12 - botChoice] = 0;
}
scorePoints = boardState[6] - initialScore;
if(botChoice==6) {
freeTurnPoints = 1;
} else {
freeTurnPoints = 0;
}
movePoints[f] = scorePoints + (1.5 * freeTurnPoints);
}
bestMovePoints = movePoints[0];
bestMove = 0;
for(int f = 1; f <= 5; f++) {
if(movePoints[f]>bestMovePoints) {
bestMovePoints = movePoints[f];
bestMove = f;
}
}
boardState = staticBoardState;
return bestMove;
}
Any help is greatly appreciated.
It looks like you're confusing value-type assignment with reference assignment. When you write
staticBoardState = boardState
what happens is that staticBoardState simply holds a reference to the array in memory that boardState is also already referring to. Not they both refer to the same array in memory, which is why staticBoardState is apparently being modified through the use of boardState. What you need to do to fix this is allocate staticBoardState as a new array and explicitly copy its contents, for example using a boardState.clone(), and perform similar copying each time you want to restore your boardState.
So for this pset I'm doing (for a Candy Crush clone), I have to write a method that checks for any possible matches in the row of a board that the chosen point is on. The method found would check to the right of the chosen point, and return an array of matching points to the chosen point. Within the given code, the getRowBools function is supposed to generate a boolean array with true or false depending on whether the points are the same as the chosen one. Then, the method would find the length of trues after the chosen one, then this length should determine the length of a new point array. Following that, the method is supposed to place all of the relevant points to the new array. However, I don't quite understand how to modify the point values in a way that works.
public static Point[] buildPossibleMatchRow(Point p, Board b) {
int x = p.x;
int y = p.y;
boolean[] matches = b.getRowBools(new Point(x,y));
int amtcorrectx = 0;
for (int i=0; i < matches.length; i++)
{
if (matches[i]) {
amtcorrectx++;
}
}
Point[] returnVals = new Point[amtcorrectx];
returnVals[0] = p;
for (int i=0; i < returnVals.length; i++)
{
x++;
}
return returnVals;
}
Here's the code I have so far, but I'm sure that there's something wrong with the for loop at the end. Is there anything that I'm missing?
I don't quite understand your question, but looking at your code maybe you meant to accomplish something like this?
public static Point[] buildPossibleMatchRow(Point p, Board b) {
int x = p.x;
int y = p.y;
boolean[] matches = b.getRowBools(new Point(x,y));
int amountCorrect = 0;
for (int i=0; i < matches.length; i++) {
if (matches[i])
amountCorrect++;
}
Point[] result = new Point[amountCorrect];
for (int i = 0; i < result.length; i++)
result[i] = new Point(x + i, y);
return returnVals;
}
I had some code that calculates powers, by calling square, cube and hypercube methods. Currently the cube method calls the square method in the program, and then the hypercube method calls the cube method. I want to replace the calls to cube and hypercube with calls to the power method, but I'm completely stuck.
Here's the original code which worked.
public int square( int x ){
int i = ( x*x );
return i;
}
public int cube( int x ){
int i = (x * square(x) );
return i;
}
public int hypercube( int x ){
int i = (x * cube(x) );
return i;
}
public int power(int x, int n){
int k;
if (n==2){
k = square(x);
}
else if (n==3){
k = cube(x);
}
else if (n==4){
k = hypercube(x);
}
else if (n==1){
k = x;
}
else {
k = 1;
for (int i = 0; i < n; i++) {
k *= x;
}
}
return k;
}
Now like I said I want to replace the calls in the cube and hypercube methods with calls to the power method, then I still have calls to square, cube etc in the power method. So I want to remove calls to these methods entirely since I no longer need them. Its really bugging me.
This is what I have so far but its giving me StackOverFlowError.
public int square( int x, int n ){
int i = power( x, n );
return i;
}
public int cube( int x, int n ){
int i = power(x , n );
return i;
}
public int hypercube( int x, int n ){
int i = power(x , n );
return i;
}
public int power(int x, int n){
int k;
if (n==2){
k = square(x, n);
}
else if (n==3){
k = cube(x, n);
}
else if (n==4){
k = hypercube(x, n);
}
else if (n==1){
k = x;
}
else {
k = 1;
for (int j = 0; j < n; j++) {
k *= x;
}
}
return k;
}
First off, as you've recognized this is a very bad way of going about things. So anybody else reading this, apart from the usual call to avoid reinventing the wheel (unless it's for educational purposes) don't implement your exponentiation methods this way!
That being said, the reason you're getting a stack overflow (so appropriate) is that you have a circular definition. The simplest way to see this is trying to track down how power works by hand. Let's say I want to run power(3, 2). What happens? Well power(3, 2) recognizes this as an instance of n == 2 and so goes to the square method. However, the square method relies on the power method to get things done and then you repeat ad infinitum. Hence you get function calls piling up on your stack until you run out of space.
P.S. Incidentally, if you are looking at implementing integer exponentiation for personal edification, you might want to look into repeated squaring. It makes your code much faster (a logarithmic number of multiplication operations as opposed to a linear number).
It looks to me that there is an infinite cycle going on here.
If n=2, then power calls sqaure which in turn calls power and n doesn't change either.
You get StackOverFlowError usually when you deal with infinities.
power(x,n) must be independent of cube or square if you want to get rid of those.
So I need to take a 2D array do calculations to each elements and transfer that into another 2D array while using the values to the "left" "right" "up" and "down" of the current element. If the current element is on the edge (x = 0, y = 0, x = array.length , y = array.length) I will get an array out of bounds error. I want to create a for loop that deals with each of those cases but I don't know how to do it. A sample of my code is
private void buildE(int[][] array, int y, int x)
{
int up = array[y - 1][x];
int down = array[y + 1][x];
int left = array[y][x - 1];
int right = array[y][x + 1];
if(up == 0){
buildETopRow(array);
}
E will be my new array. This method does not work because y does not equal 0, it just doesn't exist but I can't set ints to null either. In the case of an out of bounds error I need the element (up, down, left, or right) that is out of bounds to equal the current element. Is there a way I can still use a for loop for this or do I need to do something else?
If I read this correctly you want to effectively treat the difference of an element on the edge with an element off the edge as 0. If that's true I would write four methods right(), left(), up() and down(), with down() shown below as an example:
/*
* Return the difference between an element an the element below it
*/
public void down(int x, int y) {
if (y == array.length - 1) {
\\ on the bottom edge
return 0;
}
return array[y][x] - array[y + 1][x];
}
And inside your loop you'd calculate:
up(x,y) + down(x,y) + right(x,y) + left(x,y)
or whatever calculation it is you need to sum up.
The easiest way it to surround your array with a border region. So that your x dimension is really width+2.
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
int realWidth = 10;
int realHeight = 10;
int[][] in = new int[(realWidth+2)][(realHeight+2)];
int[][] out = new int[(realWidth+2)][(realHeight+2)];
for (int j = 1;j<realHeight+1;j++)
{
for (int i = 1;i<realWidth+1;i++)
{
int top = in[j-1][i];
int bottom = in[j+1][i];
int left= in[j][i-1];
int right = in[j][i+1];
out[j][i] = operation(top,bottom,left,right);
}
}
}
public static int operation (int top,int bottom,int left,int right)
{
return top+bottom+left+right;
}
}
I'm not totally sure what your question is, but (1) the usual structure for traversing a 2D array is to use nested for loops (one inside the other), and (2) when you want wrap-around counters (e.g. 2, 3, 0, 1, 2, ...) use the remainder operator %.
int numRows = theArray.length;
int numCols = theArray[0].length;
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
int right = theArray[(j+1) % numCols];
int down = theArray[(i+1) % numRows];
int left = theArray[(j+numCols-1) % numCols];
int up = theArray[(i+numRows-1) % numCols];
/* right, down, left, and up will be the elements to the right, down,
left, and up of the current element. Npw that you have them, you can
process them however you like and put them in the other array. */
}
}
What the remainder operator A%B does is sets A back to zero once it gets as large as B. Since B is the size of your array, that's exactly when it is too large and will cause an IndexOutOfBounds error. Note: That's not how % works but it's an ok way to think of what it does. To find out more about it you can google it, I found an ok explanation here.
I have a multidimentional array, as:
private static ArrayList [] [] pVTable = new ArrayList [35] [12];
My first try to initialize it was:
for (ArrayList[] x : pVTable) {
for (ArrayList y : x) {
y = new ArrayList<TableValue>();
}
}
which didn't work.
I ended up doing it more manually, as in:
for ( int i = 0; i < pVTable.length; i++) {
for ( int j = 0; j < pVTable[0].length; j++) {
pVTable [i] [j] = new ArrayList<TableValue>();
}
}
which works fine.
Although I have a solution, I was wondering why the first (more elegant) piece of code doesn't do the same job?
In the first snippet, if we strip away the syntactic sugar of the foreach operator (:), the code translates to:
for (int xIndex = 0; xIndex < pVTable.length; xIndex++) {
ArrayList[] x = pVTable[xIndex];
for (int yIndex = 0; yIndex < x.length; yIndex++) {
ArrayList y = x[yIndex];
y = new ArrayList<TableValue>();
}
}
As you can see, nothing is ever assigned to the actual array – only to the temporary y variable.
In the first example your code although modifies y does not change x.
You are mixing ArrayList (part of collections api) with Arrays, which is rather confusing (for me anyway)
I would suggest something like this instead :
List<Point> myShape = new ArrayList<Point>;
Where point contains two ints representing X and Y.
The scope of the first is incorrect. y is just a placeholder variable. Changing that doesn't change the underlying object, just the object that y refers to. You can see the same problem in the following code snippet:
public static int x = 2;
public static void foo(int y) {
y = 3;//does nothing outside of foo
}
public static void main(String[] args) {
System.out.println(x);//prints 2
foo(x);
System.out.println(x);//prints 2, x hasn't changed.
}