Checking if Element Exists in Boolean Array - java

I took a programming class, and I'm revisiting old programs that I did not quite get right. This one is a Game Of Life program, and I have a question about code cleanup.
I need to make sure that an array element is in bounds before checking whether its neighbor's boolean value is true or false. I have a statement to check if firstGen[0][0]'s top-left (up one row, left one column) is in bounds. Is there an easier or more elegant way to check if an element is in bounds or to restrict the element checks to the boundaries of a given array without using four && conditionals per if statement?
Note that I have only changed the first if statement thus far, so there may be errors elsewhere. I also excluded the boundary checks for the other neighbors.
public static boolean[][] generation(boolean[][] firstGen)
{
int length = firstGen.length;
boolean[][] newGen = new boolean[length][length];
for (int j = 0; j < firstGen[0].length; j++)
{ for (int i = 1; i < firstGen.length; i++)
{
int count = 0;
if ((i-1 >= 0) && (i-1 < length) && (j-1 >= 0) && (j-1 < length)) //top-left element exists
{ if (newGen[i-1][j-1] == true) count++; } //increment `count` if top-left element is true
if ((newGen[i][j] == false) && (count == 3)) newGen[i][j] = true;
else if ((newGen[i][j] == true) && (count == 1)) newGen[i][j] = false;
else if ((newGen[i][j] == true) && (count > 3)) newGen[i][j] = false;
else break;
}
}
return newGen;
}

If i and j are in bounds, then you know for sure that i - 1 < length and j - 1 < length are both true.
Also:
i - 1 >= 0 can be written i > 0
if (condition == true) can be rewritten if (cond)
So you could replace:
if ((i-1 >= 0) && (i-1 < length) && (j-1 >= 0) && (j-1 < length)) //top-left element exists
{ if (newGen[i-1][j-1] == true) count++; } //increment `count` if top-left element is true
by:
//increment `count` if top-left element is true
if (i > 0 && j > 0 && newGen[i-1][j-1]) count++;

That's the best way I can think of to check if its out of bounds, but an alternative method in general, and one that I think gives programs like the Game of Life more exciting outcomes, is adding periodic boundaries. Basically this means that if you walk off one edge, you end up on the other side (like in pac-man). It sounds complicated, but really all it takes is the % function, which returns the remainder of division between the two numbers given.
So:
27 % 5 = 2;
So for adding periodic boundries you would update x and y positions like this:
x = (x + xStep + horizontalSize) % horizontalSize;
y = (y + yStep + verticalSize) % verticalSize;
Where xStep and yStep are +1 or -1 depending on what direction you want to go. (this works nicely with a for loop) The addition of the size is to make sure you go below zero when you get close to borders.
Then you never have to worry about messy border conditions, everything simply overlaps. No need to check each and every border. I hope this makes sense. Please ask for clarification if not. I've used this more for random walker programs but the idea is the same.

Related

Java while(condition doesn't reach)?? Why

Why is it when I do this
while(word.charAt(left) == word.charAt(right) && left >= 0 && right < word.length()){
left--;
right++;
}
its says in the while conditions "left >= 0 && right < word.length()" condition doesn't reach, but when I do it like this
while(left >= 0 && right < word.length() && word.charAt(left) == word.charAt(right)){
left--;
right++;
}
The conditions are met.
Is there an order for while(loop conditions)???
The order does matter as conditions are checked from left to right. You're getting that message because if the previous condition evaluates to true, then those two conditions
left >= 0 && right < word.length()
will always evaluate to true. You probably want the latter (since you would want to check all the conditions).

How does one put a ternary operator inside the parenthesis of a for loop

I've recently learnt ternary operators and was practising them by making some old code i wrote a while back nicer. When trying to do this to a for loop in many different ways I can't seem to figure out how to do it. Ive tried:
for (hotbarFirst ? (x = 0; x < mc.player.inventoryContainer.getInventory().size(); x++) :
(x = mc.player.inventoryContainer.getInventory().size(); x > 0; x--)) {
and
for (hotbarFirst ? (x = 0) : (x = mc.player.inventoryContainer.getInventory().size());
hotbarFirst ? (x < mc.player.inventoryContainer.getInventory().size()) : (x > 0);
hotbarFirst ? (x++) : (x--)){
}
The first way gives me unexpected token errors and the second one gives me not a statement errors. It seems like I should be able to do this in some way or another, so am I just approaching it wrong or is there another way to do this without making two for loops.
(ignore the functions, they're for a game I made the mod in)
(Also incase you didnt notice I'm trying to iterate over a set of numbers two either back to front or front to back depedning on whether the bool is true or false)
original code:
public static int getItem(Item itemofChoice, boolean hotbarFirst) {
if (mc.player == null) return -1;
for (int x = 0; x < mc.player.inventoryContainer.getInventory().size(); x++) {
if ((x == 0 || x == 5 || x == 6 || x == 7 || x == 8)) continue;
ItemStack s = mc.player.inventoryContainer.getInventory().get(x);
if (s.isEmpty()) continue;
if (s.getItem().equals(itemofChoice)) return x;
}
return -1;
}
Im trying to make it iterate the opposite way if the bool param is true
Here is one way to do it:
int size = mc.player.inventoryContainer.getInventory().size();
for (int x = (hotbarFirst ? 0 : size-1); (hotbarFirst ? x < size : x >= 0) ; x += (hotbarFirst ? 1 : -1)) {
...
}

Time and space complexity of recursion DFS when finding path in a maze

The question is : a man is looking for a target(which is marked as 9) in a 2D array, where 0 represents walls and 1 represents roads. The method should find if the man can find the target or not.
I came up with the solution using DFS easily, but got stuck when trying to find out the time and space complexity of my code.
public boolean find(int[][] grid) {
if(grid == null || grid.length == 0 || grid[0].length == 0 || grid[0][0] == 0) return 0;
return helper(grid,0,0);
}
private boolean helper(int[][] grid,int x, int y) {
if(x >= 0 && x < grid.length && y >= 0 && y < grid[0].length) {
if(grid[x][y] == 0) return false;
else if(grid[x][y] == 9) return true;
else if(grid[x][y] == 1) {
grid[x][y]=2;
return helper(grid,x,y-1) || helper(grid,x+1,y) || helper(grid,x,y+1) || helper(grid,x-1,y);
}
else return false;
}
else return false;
}
I think the time and space complexity is O(mn), but I am not sure.
Generally speaking, DFS has a time complexity of O(m + n) and a space complexity of O(n), where n is the number of locations you can be in and m is the total number of connections between locations (if you're familiar with graph theory, n is the number of nodes and m is the number of edges). In your case, if you have a grid whose size is w × h, then n = wh (there's one place you can be for each grid location) and m ≤ 4wh (since each location is adjacent to at most four other locations). This means that the runtime will be O(wh) and the space complexity will be O(wh) as well.

Board Game Capturing Pieces

I am creating a boardgame which has two different coloured pieces, black and red.
If a player surrounds the opponents pieces with his own, either horizontally or vertically, the pieces are removed. Here are some pictures to demonstrate this:
My board is a simple 2d integer array, with values of 0, 1 or 2 depending on whether the space is empty, has a red piece or a black piece.
This is the code I have come up with so far, however I am getting issues with out of bounds errors and it also does not account for capturing more than one piece.
static final int EMPTY = 0, BLACK = 1, RED = 2, ROW = 9, COLUMN = 9;
board = new int[ROW][COLUMN];
public void captureRedPieces() {
for(int i = 0; i < ROW; i++) {
for(int j = 0; j < COLUMN; j++) {
if(i <= ROW - 2) {
if(board[i][j] == 1 && board[i + 1][j] == 2 && board[i + 2][j] == 1) {
board[i + 1][j] = EMPTY;
}
}
if(i <= COLUMN - 2) {
if(board[i][j] == 1 && board[i][j + 1] == 2 && board[i][j + 2] == 1) {
board[i][j + 1] = EMPTY;
}
}
}
}
}
Could anyone help me come up with a better solution for capturing pieces?
You are testing whether i <= ROW - 2, but then you are using i+2 as an index for your check. This means that if i is 7, which is equal to ROW - 2 and passes your if test, then i+2 will be 9, which is out of bounds because the array only goes 0 to 8.
So you should correct this to i < ROW - 2 rather than <=.
Also, you have this code:
if(i <= COLUMN - 2) {
if(board[i][j] == 1 && board[i][j + 1] == 2 && board[i][j + 2] == 1) {
board[i][j + 1] = EMPTY;
}
}
This should be a condition on j, not on i - and it has to be fixed in the same way I told you about i - < instead of <=.
Note: since your rules state that a "surrounding" state is a capture only after the surrounding color makes a move, perhaps you should change your approach: you should only check the position where black made a move, to match with positions around it. Of course, you'll still have to make sure you don't go out of bounds. Your current approach might mark places that are "surrounded" since previous moves, and that would be wrong per the rules.
So your method should be declared like so:
public void captureRedPieces(int blackMoveRow, int blackMoveCol )
Probably you have to replace i <= COLUMN - 2 with j <= COLUMN - 2. Seems that capturing occurs after the new move. If you know the exact position of the new piece, then no need to iterate over the whole board. You just need to check nearby pieces in the same row and in the same column where the new piece was placed.

Finding smallest neighbour in a 2D array

I have some code that is supposed to find the smallest of the 8 neighboring cells in a 2D array. When this code runs, the smallest is then moved to, and the code run again in a loop. However when it is run the code ends up giving a stack overflow error as it keeps jumping between two points. This seems to be a logical paradox as if Y < X then X !< Y. So it think it is my code at fault, rather than my logic. Here's my code:
private Point findLowestWeight(Point current) {
float lowest = Float.MAX_VALUE;
Point ret = new Point(-1, -1);
LinkedList<Point> pointList = new LinkedList<Point>();
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (!(i == 0 && j == 0)) {
if ((current.x + i >= 0 && current.x + i <= imageX - 2)
&& (current.y + j >= 0 && current.y + j <= imageY - 2)) {
pointList.add(new Point(current.x + i, current.y + j));
}
}
}
}
for (Point p : pointList){
if (map[p.x][p.y] < lowest){
lowest = map[p.x][p.y];
ret = p;
}
}
return ret;
}
You need a stopping case.
find the smallest of the 8 neighboring cells in a 2D array. When this code runs, the smallest is then moved to, and the code run again in a loop
is a fine way to start but says nothing about stopping.
Do you care about the value of the current cell? If so you need to check 9 not 8. If you simply want to move down hill then you need to check where you've been or any flat multi-cell valley will put you into an infinite loop. Consider only moving if moving down.
If you truly don't care where you are then even a single cell valley will put you into an infinite loop as you bounce in and out of it. In which case you'd need some other stopping condition. Consider stopping after imageX * imageY iterations.
Do you move even if the smallest neighbour is greater than the value in the center?
Example:
2 2 2 2
2 0 1 2
2 2 2 2
You start with center cell 0. The smallest neighbour is 1. If you move to 1, the smallest neighbour is 0. You can continue endless.
Probably you should not move, if the smallest neighbour is greater than the current cell.

Categories