I have done all the code right and stuck with this silly thing: I cannot mange to stop the print when the previous generation is the same as the new...so when the prints pattern is the same as the previous pattern it should stop.
I need to copy the board before calling 'step' and then compare the new and copied boards, and only print if it has changed
i need is to create a new variable just like i did board[], then to make a nested loop like the one in print, and inside do newboard[y][x] = board[y][x]
Please help me with this i cannot stop the print it always keep printing.
please show me your syntax
void step(int board[][WIDTH], int rows) {
int x, y;
int neighbors[HEIGHT][WIDTH];
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
neighbors[y][x] = count_neighbors(board, rows, y, x);
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
if (board[y][x] == 1) { /* Currently alive */
if (neighbors[y][x] < 2)
board[y][x] = 0; /* Death by boredom */
else if (neighbors[y][x] > 3)
board[y][x] = 0; /* Death by overcrowding */
}
else { /* Currently empty */
if (neighbors[y][x] == 3)
board[y][x] = 1;
}
}
You just have to track changes. Rather trivial to do and far less work (execution/memory wise) than copying and comparing the whole array:
int step(int board[][WIDTH], int rows) { // now returns a bool
int x, y;
int neighbors[HEIGHT][WIDTH];
int changed = 0; // save changes
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
neighbors[y][x] = count_neighbors(board, rows, y, x);
for (y = 0; y < rows; y++)
for (x = 0; x < WIDTH; x++)
if (board[y][x] == 1) { /* Currently alive */
if (neighbors[y][x] < 2)
{
board[y][x] = 0; /* Death by boredom */
changed = 1; // change happened
}
else if (neighbors[y][x] > 3)
{
board[y][x] = 0; /* Death by overcrowding */
changed = 1; // change happened
}
}
else { /* Currently empty */
if (neighbors[y][x] == 3)
{
board[y][x] = 1;
changed = 1; // change happened
}
}
return changed; // return the status (changed yes/no?)
}
int main(void) {
int board[HEIGHT][WIDTH];
init(board, HEIGHT);
while (1) {
print(board, HEIGHT, WIDTH);
if(step(board, HEIGHT) == 0) // no change
break; // leave the loop
}
return 0;
}
Edit:
If wanted, you could as well count the actual changes (instead of just saying yes/no) and return the number of changes. Could would stay almost the same.
Related
I wrote a function where a 1-dimensional array (int8_t tabelle1[768]) is transferred into a 2-dimensional array (int8_t tabelle[24][32]).
I now want to find a "Hotspot" in the 2-dimensional array. A "Hotspot" is an 2x2 block in the array (can be located anywhere) where each value of the block has to be equal or over 30.
My Problem is now that my program is not going into my if statement.
The "Checkpoint" is not being printed.
The function:
bool Hotspotberechnung(int8_t tabelle1[768],int8_t tabelle2[24][32])
{
int i=0, j=0, x=0, y=0;
for(j=0; j<24; j++) //Transfer from 1D into 2D
{
for(i=0; i<32; i++)
{
tabelle2[j][i] = tabelle1[(j*32)+i];
}
}
for(y=0; y<24; y++) //search for hotspot
{
for(x=0; x<32; x++)
{
if(tabelle2[y][x]>=30)
{
printf ("1\n"); // checkpoint
if(tabelle2[y][x+1]>=30)
{
if(tabelle2[y+1][x]>=30)
{
if(tabelle2[y+1][x+1]>=30)
{
for(j=0; j<24; j++)
{
for(i=0; i<32; i++)
{
printf("%d.%d=%d\n",j+1,i+1,tabelle2[j][i]);
}
}
printf ("Hotspot!");
return true;
}
else
return false;
}
else
return false;
}
else
return false;
}
else
return false;
}
}
return 0;
}
It never reaches the print, because one of your many returns ends the function much sooner than you think. Specifically the one in the else of the then wich contains the print.
Use a debugger and you will see that.
Alternatively put a print next to each else, make sure to use {} for that. Also put a print after the call to the shown function.
for(y=0; y<24; y++) //search for hotspot
{
for(x=0; x<32; x++)
{
if(tabelle2[y][x]>=30)
{
/* this is not reached for y=0 and x=0, i.e. first */
printf ("1\n"); // checkpoint
/* much code deleted */
}
else
return false;
/* this is reached first,
end of the function,
end of the loop,
no printing ever */
}
}
A few things ...
The kernal width/height is 2, so we have to stop short of the array width/height or we'll go beyond the end of the array
Once we find an element that matches, we have to use that element as the upper left anchor of the 2x2 box
Here's the refactored code (it compiles, but is not tested):
#include <stdio.h>
#include <stdint.h>
#define YMAX 24
#define XMAX 32
#define BOXWID 2
#define MARG (BOXWID - 1)
int
Hotspotberechnung(int8_t tabelle1[YMAX * XMAX], int8_t tabelle2[YMAX][XMAX])
{
int i = 0,
j = 0,
x = 0,
y = 0;
// Transfer from 1D into 2D
for (j = 0; j < YMAX; j++) {
for (i = 0; i < XMAX; i++)
tabelle2[j][i] = tabelle1[(j * XMAX) + i];
}
for (y = 0; y < (YMAX - MARG); y++) {
int8_t *row = tabelle2[y];
for (x = 0; x < (XMAX - MARG); x++) {
if (row[x] < 30)
continue;
int8_t *box = &row[x];
int match = 1;
for (int yoff = 0; yoff < BOXWID; ++yoff) {
for (int xoff = 0; xoff < BOXWID; ++xoff) {
if (box[(yoff * XMAX) + xoff] < 30) {
match = 0;
break;
}
}
if (! match)
break;
}
if (! match)
continue;
for (int yoff = 0; yoff < BOXWID; ++yoff) {
for (int xoff = 0; xoff < BOXWID; ++xoff) {
int8_t val = box[(yoff * XMAX) + xoff];
printf("[%d,%d] = %d\n",y + yoff,x + xoff,val);
}
}
}
}
return 0;
}
This question already has answers here:
Returning an array using C
(8 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
C: returning local struct works but returning local array does not?
(2 answers)
Closed 1 year ago.
I'm trying to implement Game of Life in C. I'm certain I programmed the rules of the game correctly, but the cells do not update correctly when running the program. In the beginning of main, I hard-coded a glider onto the map, but it doesn't 'glide' southwest like it's supposed to. I think the source of the problem might be in the update() function, but I can't find it myself.
(This isn't homework, this is just a personal project.)
#include <stdio.h>
#include <string.h>
#define MAX_Y 10 /* height */
#define MAX_X 30 /* width */
int neighbors(int grid[MAX_Y][MAX_X], int x, int y) {
int dx, dy, dstx, dsty;
int n = 0;
for (dy = -1; dy < 2; ++dy) {
for (dx = -1; dx < 2; ++dx) {
dsty = y + dy;
dstx = x + dx;
if (dsty > 0 && dsty < MAX_Y && dstx > 0 && dstx < MAX_X) {
n += !!grid[dsty][dstx]; /* use !! so that non-zero values eval to 1 */
}
}
}
/* (n > 0) ? printf("Point (%d,%d) has %d neighbors!\n", x, y, n) : 0; */
return n;
}
int **update(int grid[MAX_Y][MAX_X]) {
int new[MAX_Y][MAX_X];
memset(new, 0, sizeof new);
int i, j, n;
for (i = 0; i < MAX_Y; ++i) {
for (j = 0; j < MAX_X; ++j) {
n = neighbors(grid, i, j);
/* alive, 2 or 3 neighbors -> alive!
* dead, 3 neighbors -> alive!
* anything else -> dead :(
*/
if (grid[i][j] && (n == 2 || n == 3))
new[i][j] = 1;
else if (!grid[i][j] && n == 3)
new[i][j] = 1;
else
new[i][j] = 0;
}
}
return new;
}
void draw(int grid[MAX_Y][MAX_X]) {
int i, j;
for (i = 0; i < MAX_Y; ++i) {
for (j = 0; j < MAX_X; ++j) {
putchar((grid[i][j]) ? '#' : '.');
/* printf("|%2d", grid[i][j]); */
}
putchar('\n');
}
}
int main(void) {
int map[MAX_Y][MAX_X];
memset(map, 0, sizeof map);
map[2][2] = 1;
map[3][2] = 1;
map[4][2] = 1;
map[4][3] = 1;
map[3][4] = 1;
printf( " Game of Life v1.0\n"
"Press ENTER to step.\n");
for (;;) {
draw(map);
memcpy(map, update(map), sizeof map);
getchar();
}
}
I made this backtracking recursive code.
this code shows every 4x4 array filled with 1, 2, 3, 4
but no duplication in every one row and line.
but this prints only one answers, what I expected is every answers.
#include <stdio.h>
#include <stdbool.h>
// initializing array
void init_arr(int arr[][4])
{
int x;
int y;
y = 0;
while (y < 4)
{
x = 0;
while (x < 4)
{
arr[y][x] = 0;
x++;
}
y++;
}
}
// check about promising correct
bool promising(int arr[][4], int x, int y)
{
int i;
i = 0;
while (i < 4)
{
if (arr[y][i] == arr[y][x] && i != x)
return (0);
i++;
}
i = 0;
while (i < 4)
{
if (arr[i][x] == arr[y][x] && i != y)
return (0);
i++;
}
return (1);
}
// recursive function
void fill_arr(int arr[][4], int x, int y)
{
int n;
if (x == 0 && y == 0)
init_arr(arr);
if (y == 4)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
printf("\n");
return ;
}
else if (x == 4)
fill_arr(arr, 0, y + 1);
else
{
n = 1;
while (n < 5)
{
arr[y][x] = n;
if (promising(arr, x, y))
fill_arr(arr, x + 1, y);
n++;
}
}
}
int main(void)
{
int arr[4][4];
fill_arr(arr, 0, 0);
return (0);
}
when I put printf in if(promising), this comes out
it looks like some variables are not initializing, but when I put init function to every other line, it getting messier.
Your fill_arr() isn't cleaning up before it leaves.
Add this line before the final brace:
arr[y][x] = 0;
I'm looking for a way to replace the continue statement in this function. The houserules state that they can't be used but I'm having difficulty implementing a replacement that doesn't cause the rest of the code to function incorrectly.
bool neighCheck (int i, int j, int a[][COLLENGTH])
{
bool neighbourOnFire;
int x, y, neighX, neighY, curreNeigh;
/* Bool set up to change after neighbours looped*/
neighbourOnFire = false;
/* The neighbours -looping from -1 -> 1 to get index of each neighbour*/
for (x = -1; x < 2; x++) {
for (y = -1; y < 2; y++) {
/* Disregards current (middle) cell*/
if ((x == 0) && (y == 0)) {
continue;
}
/* Get indexes of the neighbour we're looking at */
neighX = i + x;
neighY = j + y;
/* Checks for edges*/
if (neighX >= 0 && neighY >= 0 && neighX < ROWLENGTH
&& neighY < COLLENGTH) {
/* Get the neighbour using the indexes above */
curreNeigh = a[neighX][neighY];
/* Test to see if the neighbour is burning */
if (curreNeigh == fire) {
neighbourOnFire = true;
continue;
}
}
}
}
return neighbourOnFire;
}
The first continue; can be replaced by inverting the condition and putting the rest code inside if statement.
The second continue; can be simply removed because there are no code to execute after that.
bool neighCheck (int i, int j, int a[][COLLENGTH])
{
bool neighbourOnFire;
int x, y, neighX, neighY, curreNeigh;
/* Bool set up to change after neighbours looped*/
neighbourOnFire = false;
/* The neighbours -looping from -1 -> 1 to get index of each neighbour*/
for (x = -1; x < 2; x++) {
for (y = -1; y < 2; y++) {
/* Disregards current (middle) cell*/
if (!((x == 0) && (y == 0))) {
/* Get indexes of the neighbour we're looking at */
neighX = i + x;
neighY = j + y;
/* Checks for edges*/
if (neighX >= 0 && neighY >= 0 && neighX < ROWLENGTH
&& neighY < COLLENGTH) {
/* Get the neighbour using the indexes above */
curreNeigh = a[neighX][neighY];
/* Test to see if the neighbour is burning */
if (curreNeigh == fire) {
neighbourOnFire = true;
}
}
}
}
}
return neighbourOnFire;
}
I'm trying to write a function or method for the code. I'm really lost at how to come with the loop that print out the number born and number died in the output below.
Here is my code:
#include <stdio.h>
char grid[10][10];
// Moved this function here
int occ(int x, int y) {
int i, j, count;
char gridCopy[10][10];
// You probably are going to do this often in the future
// Make a function for it instead of having the same code often
void printGrid() {
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++)
printf("%c", grid[i][j]);
printf("\n");
}
}
You don't need gridCopy in occ function.
Please remember that array is transposed. When you access element (x,y) you need to use grid[y][x]
Below is the working code with function generateNext() which generates next state for whole grid array. This is place where you need girdCopy. Results are exactly the same as in your example.
#include <stdio.h>
#include <stdlib.h>
char grid[10][10];
int born,died,generation;
// Moved this function here
int occ(int x, int y) {
int count;
int xm1,xp1,ym1,yp1;
xm1=x-1;xp1=x+1;ym1=y-1;yp1=y+1;
if (xm1<0) // handle boundary cases - wrap around
xm1=9;
if (ym1<0)
ym1=9;
if (xp1>9)
xp1=0;
if (yp1>9)
yp1=0;
// Checking on the value of the neighboring cells
count = 0;
if (grid[ym1][x] == '*')
count++;
if (grid[ym1][xp1] == '*')
count++;
if (grid[y][xp1] == '*')
count++;
if (grid[yp1][xp1] == '*')
count++;
if (grid[yp1][x] == '*')
count++;
if (grid[yp1][xm1] == '*')
count++;
if (grid[y][xm1] == '*')
count++;
if (grid[ym1][xm1] == '*')
count++;
return count;
}
void generateNext()
{
int x,y;
char gridCopy[10][10];
born=0;died=0;
generation++;
for (y=0; y<10; y++) {
for (x=0; x<10; x++) {
gridCopy[y][x]=grid[y][x];
}
}
for (y=0; y<10; y++) {
for (x=0; x<10; x++) {
if (grid[y][x]=='*' && occ(x,y)<2)
{gridCopy[y][x]='-';died++;}
if (grid[y][x]=='*' && occ(x,y)>3)
{gridCopy[y][x]='-';died++;}
if (grid[y][x]=='-' && occ(x,y)==3)
{gridCopy[y][x]='*';born++;}
}
}
for (y=0; y<10; y++) {
for (x=0; x<10; x++) {
grid[y][x]=gridCopy[y][x];
}
}
}
// You probably are going to do this often in the future
// Make a function for it instead of having the same code often
void printGrid() {
int x, y;
for (y = 0; y < 10; y++) {
for (x = 0; x < 10; x++)
printf("%c", grid[y][x]);
printf("\n");
}
}
/*
*
*/
int main(int argc, char** argv) {
int x, y, answ;
// Setting entire grid to '-'
for (y = 0; y < 10; y++)
for (x = 0; x < 10; x++)
grid[y][x] = '-'; // No need for a variable, just use '-' directly
// Printing out grid
printf("This is the original array\n");
printGrid();
// Setting initial state
grid[5][4] = '*'; // No need for a variable, just use '*' directly
grid[5][5] = '*';
grid[5][6] = '*';
grid[4][4] = '*'; grid[3][4] = '*';
grid[4][6] = '*'; grid[3][6] = '*';
// Printing out grid
printf("This is the new array\n");
printGrid();
//printf("The number of neighbors is: %d\n", occ(3, 3));
generation=0;
answ=1;
while(answ)
{
generateNext();
printf("\n\nGeneration number %d",generation);
printf("\nBorn=%d,Died=%d\n",born,died);
printGrid();
printf("\nPrint next generation-1,Exit-0:");
scanf("%d",&answ);
}
return (EXIT_SUCCESS);
}
Counting is similar to what you have to do to print or copy the whole grid: you use the same loop(s), but at each cell, add to the appropriate counter depending on what is in it.
Alternatively, if keep counts of the number of dead and live cells, you can update those as you update the grid: if a cell changes, update the counters appropriately if the cell becomes alive or becomes dead. This can also be used if you need to report how many were born & how many died each turn.