Game Of Life ends quickly (Java) - multidimensional-array

I've created a basic version of the Game Of Life: each turn, the board is simulated by a 2D array of 1's and 0's, after which another class creates a drawing of it for me using the 2d array
I've read all the other questions here regarding this game, but no answer seems to work out for me....sorry if I'm beating a dead horse here.
I think I have a problem with my algorithm, thus maybe the board gets filled with the wrong amount of dead and alive cells and thus ends rather quickly (5-10 turns).
I've found an algorithm here to scan all the neighbors and even added a count = -1 in case it a cell in the grid scans itself as it's own neighbor, but I think I'm missing something here.
public static void repaint(board game, int size,int[][] alive, int[][] newGeneration)
{
int MIN_X = 0, MIN_Y = 0, MAX_X =9, MAX_Y =9, count;
for ( int i = 0; i < size; i++ )
{
for (int j = 0; j < size; j++) //here we check for each matrix cell's neighbors to see if they are alive or dead
{
count = 0;
if (alive[i][j] == 1)
count = -1;
int startPosX = (i - 1 < MIN_X) ? i : i - 1;
int startPosY = (j - 1 < MIN_Y) ? j : j - 1;
int endPosX = (i + 1 > MAX_X) ? i : i + 1;
int endPosY = (j + 1 > MAX_Y) ? j : j + 1;
for (int rowNum = startPosX; rowNum <= endPosX; rowNum++)
{
for (int colNum = startPosY; colNum <= endPosY; colNum++)
{
if (alive[rowNum][colNum] == 1)
count++;
}
}
if (alive[i][j] == 0 && count == 3) //conditions of the game of life
newGeneration[i][j] = 1; //filling the new array for the next life
if (alive[i][j] == 1 && count < 2)
newGeneration[i][j] = 0;
if (alive[i][j] == 1 && count >= 4)
newGeneration[i][j] = 0;
if (alive[i][j] == 1 && count == 3)
newGeneration[i][j] = 1;
}
}
game.setAlive(newGeneration); //we created a new matrix with the new lives, now we set it
SetupGUI(game,size); //re drawing the panel
}
}
What am I doing wrong? thanks for the help.

Related

Setting Base Cases for Recursive Function

class Solution {
//given a location on the matrix, this function recursively find the deepest possible depth, which is the length of a side of a found square
private int isSquare(int row_index, int col_index, int depth, char[][] matrix) {
int last_row = row_index + depth;
int last_col = col_index + depth;
if (row_index >= matrix.length || col_index >= matrix[0].length) {
return 0;
}
if (last_row >= matrix.length || last_col >= matrix[0].length) {
return 0;
}
for (int i = col_index; i < last_col; i++) {
if (matrix[row_index][i] != '1') {
return 0;
}
}
for (int i = row_index; i < last_row; i++ ) {
if (matrix[i][col_index] != '1') {
return 0;
}
}
return Math.max(depth, isSquare(row_index, col_index, depth + 1, matrix));
}
public int maximalSquare(char[][] matrix) {
int max = 0;
for (int row = 0; row < matrix.length; row ++) {
for (int col = 0; col <matrix[0].length; col ++) {
int curr_depth = isSquare(row, col, 1, matrix);
if (curr_depth > max) {
max = curr_depth;
}
}
};
return max * max;
}
}
Hi, I was working on LeetCode 221, and it seems like that my solution is not passing test cases with output 1, where the biggest square on the given matrix is just 1 x 1. To me it looks like those depth 1 cases are not passing the two for loops in function isSquare, which is supposed to catch 0s in the square.
I tried LC debugging tool but it did not help much, and my base cases seem fine to me. Please let me know what is going on here. For the problem, https://leetcode.com/problems/maximal-square/
One of the depth 1 test cases that I am failing is below.
Input:
[["0","1"],["1","0"]]
Output:
0
Expected:
1

Image processing in MPI

This is my attempt to code the classical smoothing pixel average algorithm in MPI. I almost got it working but something weird happens with the halo exchange as can see the lines right in the edges. I can't seem to find the bug. Am I properly exchanging halos? What section of the final array should I gather?
https://pastebin.com/4rtFnSJ5
int next = rank + 1;
int prev = rank - 1;
if (next >= size) {
next = MPI_PROC_NULL;
}
if (prev < 0) {
prev = MPI_PROC_NULL;
}
int rows = y / px;
int cols = x;
int d = 1;
for (int iter = 0; iter < TotalIter; iter++) {
for (int i = 0; i < rows + 2; i++)
for (int j = 0; j < cols + 2; j++)
for (int k = 0; k < rgb; k++)
new[i][j * rgb + k] = 0;
for (int i = 1; i < rows + 1; i++) {
int iMin = -min(d, i - 1);
int iMax = min(d, (rows + 1 - i - 1));
for (int j = 1; j < cols + 1; j++) {
int jMin = -min(d, j - 1);
int iMax = min(d, (cols + 1 - j - 1));
int counter = 0;
for (int p = iMin; p <= iMax; p++)
for (int q = jMin; q <= jMax; q++) {
counter = counter + 1;
for (int k = 0; k < rgb; k++) {
new[i][j * rgb + k] += old[i + p][(j + q) * rgb + k];
}
}
for (int k = 0; k < rgb; k++) {
new[i][j * rgb + k] -= old[i][j * rgb + k];
new[i][j * rgb + k] /= (counter - 1);
}
}
}
for (int i = 2; i < rows; i++)
for (int j = 2; j < cols; j++)
for (int k = 0; k < rgb; k++) {
old[i][j * rgb + k] = new[i][j * rgb + k];
}
MPI_Sendrecv(&old[rows][1], cols * rgb, MPI_INT, next, 1, &old[0][1],
cols * rgb, MPI_INT, prev, 1, MPI_COMM_WORLD, &status);
MPI_Sendrecv(&old[1][1], cols * rgb, MPI_INT, prev, 2, &old[rows + 1][1],
cols * rgb, MPI_INT, next, 2, MPI_COMM_WORLD, &status);
}
for (int i = 1; i< rows+1; i++)
for (int j = 1; j< cols+1; j++)
for (int k = 0; k< rgb; k++) {
buf[i-1][(j-1)*rgb+k] = old[i][j*rgb+k] ;
}
MPI_Gather(&buf[0][0], rows *cols *rgb, MPI_INT, &Finalbuffer[0][0],
rows *cols *rgb, MPI_INT, 0, MPI_COMM_WORLD);
The output looks like this when run on 8 MPI processes. I can clearly see delimiting lines. For that reason I thought I was not doing halo exchanges properly.
OK, so there are a bunch of issues here.
First, your code could only ever work with d=1 since you only swap halos of depth 1. If you want to process neighbours of distance d, you need to swap halos of depth d.
Second, you do the first halo swap after your first sweep through the arrays so you are reading junk halo data on iteration 1 - you need to do a halo swap before you start processing your arrays.
Third, when you copy back new to old you start from index 2 : you need to include all the pixels from 1 to lrows and 1 to lcols.
Finally, your logic of Imin, Imax etc seems wrong. You don't want to truncate the range at the edges in the parallel program - you need to go off the edges to pick up the halo data. I just set Imin = -d, Imax = d etc.
With these fixes the code seems to run OK, i.e. there are no obvious halo effects, but it still gives different results on different numbers of processes.
PS I was also flattered to see you used the "arraymalloc2d" code from one of my own MPI examples - http://www.archer.ac.uk/training/course-material/2018/07/intro-epcc/exercises/cfd.tar.gz ; I'm glad to see that these training codes are proving useful to people!

Collision detection is not working correctly

I have to submit a Breakout clone and I'm struggling with the collision detection of the ball and the bricks. Basically, the collision detection works, but the ball destroys the brick about 10 pixels away from the visual object. I'm checking the bounds of both objects, but I guess the problem is that the ball is a moving object and the brick is a static one.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
brick = brickArray[i][j];
if (brick == null)
continue;
areBricksLeft = true;
Bounds brickBounds = brick.getBoundsInParent();
Bounds ballBounds = ball.getBoundsInParent();
if (brickBounds.intersects(ballBounds) ) {
brick.removeBrickAt(i, j, brick, brickArray, brickPane);
didHitBrick = true;
}
}
}
Thanks for the hint I found the mistake. I replaced my condition with this:
double ballX = ball.getLayoutX() + ball.getRadius();
double ballY = ball.getLayoutY() + ball.getRadius();
if ((ballX <= brickBounds.getMaxX() - 10 && ballX >= brickBounds.getMinX() -10) &&
(ballY <= brickBounds.getMaxY() - 10 && ballY >= brickBounds.getMinY() - 10)) {
brick.removeBrickAt(i, j, brick, brickArray, brickPane);
didHitBrick = true;
}
Now it is possible to adjust the collision by substracting and adding values to the bounds.

Inside boundaries

I'm using this article to write a fluid simulation application.
I can't manage to implement the inside boundaries. As far as i know when I'm setting the boundaries (in the set_bnd function) for each cell that is inside the boundary I should calculate the average value from the adjacent non-boundary cells like this:
for (i = 0 ; i < n ; i++)
{
for (j = 0 ; j < n ; j++)
{
if (isBoundary(i,j)
{
sum = 0;
count = 0;
if (!isBoundary(i+1,j) {
sum += x[i+1][j];
}
if (!isBoundary(i-1,j) {
sum += x[i-1][j];
}
if (!isBoundary(i,j+1) {
sum += x[i][j+1];
}
if (!isBoundary(i,j-1) {
sum += x[i-1][j];
}
x[i][j] = sum / 4;
}
}
}
Unfortunately the smoke is absorbed and disappears in contact with boundary surface.
My math background is not sufficient to understand every part of the calculation, so I'll be very grateful if someone points me the right direction.
Here is some code to explain further.
insideBound is array (1 - boundary, 0 - empty, the fluid can pass trough)
#define FOR_EACH_CELL for ( i=1 ; i<=N ; i++ ) { for ( j=1 ; j<=N ; j++ ) {
void set_bnd ( int N, int b, float * x, int * insideBound )
{
int i, j;
float sum;
int count;
for ( i=1 ; i<=N ; i++ ) {
x[IX(0 ,i)] = b==1 ? -x[IX(1,i)] : x[IX(1,i)];
x[IX(N+1,i)] = b==1 ? -x[IX(N,i)] : x[IX(N,i)];
x[IX(i,0 )] = b==2 ? -x[IX(i,1)] : x[IX(i,1)];
x[IX(i,N+1)] = b==2 ? -x[IX(i,N)] : x[IX(i,N)];
}
x[IX(0 ,0 )] = 0.5f*(x[IX(1,0 )]+x[IX(0 ,1)]);
x[IX(0 ,N+1)] = 0.5f*(x[IX(1,N+1)]+x[IX(0 ,N)]);
x[IX(N+1,0 )] = 0.5f*(x[IX(N,0 )]+x[IX(N+1,1)]);
x[IX(N+1,N+1)] = 0.5f*(x[IX(N,N+1)]+x[IX(N+1,N)]);
if (!b) return;
FOR_EACH_CELL
sum = 0.0f;
count = 0;
if (insideBound[IX(i,j)] == 1)
{
if (insideBound[IX(i-1,j)] != 1)
{
count++;
sum = sum + x[IX(i-1,j)];
}
if (insideBound[IX(i+1,j)] != 1)
{
count++;
sum = sum + x[IX(i+1,j)];
}
if (insideBound[IX(i,j-1)] != 1)
{
count++;
sum = sum + x[IX(i, j-1)];
}
if (insideBound[IX(i,j+1)] != 1)
{
count++;
sum = sum + x[IX(i, j+1)];
}
if (count > 0)
{
x[IX(i,j)] = -sum / count;
} else {
x[IX(i,j)] = 0;
}
}
END_FOR
}
Per book (working):
In the first loop are set top, right, bottom and left boundary cells.
Since for them there is only one adjacent cell that is not bound the cell get its value. (I don't know why its opposite for U and the same value for V)
After the first loop, the corner boundary values are set. Here they get average values from their adjacent cells (i guess since there is no adjacent cell that is not boundary they use boundary cells).
Mine, not working properly:
if (!b) return - ignores calculations for density and updates only velocity.
The loop calculates the values for all boundary cells (again, average values from the adjacent cells that are not boundaries themselves).
I get almost realistic result from this methods, but there is big loses in the density and some bugs with too big boundaries where the fluid disappears completely.
I've managed to find a solution, here it is for potential people with the same problem
void set_bnd ( int N, int b, float * x, int * insideBound )
{
int i, j;
float sum, tmp;
int count;
for ( i=1 ; i<=N ; i++ ) {
x[IX(0 ,i)] = b==1 ? -x[IX(1,i)] : x[IX(1,i)];
x[IX(N+1,i)] = b==1 ? -x[IX(N,i)] : x[IX(N,i)];
x[IX(i,0 )] = b==2 ? -x[IX(i,1)] : x[IX(i,1)];
x[IX(i,N+1)] = b==2 ? -x[IX(i,N)] : x[IX(i,N)];
}
x[IX(0 ,0 )] = 0.5f*(x[IX(1,0 )]+x[IX(0 ,1)]);
x[IX(0 ,N+1)] = 0.5f*(x[IX(1,N+1)]+x[IX(0 ,N)]);
x[IX(N+1,0 )] = 0.5f*(x[IX(N,0 )]+x[IX(N+1,1)]);
x[IX(N+1,N+1)] = 0.5f*(x[IX(N,N+1)]+x[IX(N+1,N)]);
if (!b) return;
for ( i=1 ; i<=N ; i++ ) {
for ( j=1 ; j<=N ; j++ ) {
sum = 0.0f;
count = 0;
if (insideBound[IX(i,j)] == 1)
{
if (insideBound[IX(i-1,j)] != 1)
{
count++;
if (b == 2)
tmp = -x[IX(i-1,j)];
else
tmp = x[IX(i-1,j)];
sum = sum + tmp;
}
if (insideBound[IX(i+1,j)] != 1)
{
count++;
if (b == 2)
tmp = -x[IX(i+1,j)];
else
tmp = x[IX(i+1,j)];
sum = sum + tmp;
}
if (insideBound[IX(i,j-1)] != 1)
{
count++;
if (b == 1)
tmp = - x[IX(i, j-1)];
else
tmp = x[IX(i, j-1)];
sum = sum + tmp;
}
if (insideBound[IX(i,j+1)] != 1)
{
count++;
if (b == 1)
tmp = -x[IX(i, j+1)];
else
tmp = x[IX(i, j+1)];
sum = sum + tmp;
}
if (count > 0)
{
x[IX(i,j)] = -sum / count;
} else {
x[IX(i,j)] = 0;
}
}
}
}
}
insideBound is boolean array (0,1) which indicates the cells that are boundaries. Works with one or more boundary areas, but they should be at least 3 cells wide and high.

Changing method to be completely recursive

void merge(List<E> l, int lower, int upper) {
ArrayList<E> array = new ArrayList<E>();
for (int i = lower; i <= upper; i++)
array.add(list.get(i));
int front= 0;
int front2= (array.size() + 1) / 2;
for (int i = lower; i <= upper; i++) {
if (front2 >= array.size() ||
(first < ((array.size() + 1) / 2) &&
(array.get(first).compareTo(array.get(second)) <= 0))) {
l.set(i, array.get(front));
front++;
}// end if
else {
l.set(i, array.get(front2));
front2++;
}
}
}
This is my method. I want to change it to be completely recursive(I don't want to use for loops), but I simply don't see how. Is there a way to make this recursive or avoid using loops?

Resources