I'm trying to finish this assignment for class, but I've got a problem.It seems as though my code will always make the new generation blank, and I'm not sure why. If you could read my code, then I'd greatly appreciate it. Thanks!

// Life.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <ctime>

using namespace std;

void generation(char[][20], int);
void neighbors(char[][20], int);
void display(char[][20], char[][20], int, int);

int _tmain(int argc, _TCHAR* argv[])
{
	int x = 0;
	char board[70][20];
	char s[2][2];
	
	srand(time(NULL));

	cout << endl;
	generation(board, 70);
	

	system("pause");
	return 0;
}

void generation (char board[][20], int size)
{
	
	int x = 0;	
	int number;
	
	
	for (int x = 0; x < 20; x++) //initial configuration
	{
		for (int y = 0; y < 70; y++)
		{
			board[y][x] = ' ';
			board[10][34] = 'X';
			board[10][35] = 'X';
			board[10][36] = 'X';
			
		}
	}

	neighbors(board, 70);
	
	
}

void neighbors(char board[][20], int size)
{
	char newBoard[70][20];
	int nCount;
	int z = 1;
	/*
	Rules:
	1.	Any live cell with fewer than two live neighbours dies, as if caused by under-population.
	2.	Any live cell with two or three live neighbours lives on to the next generation.
	3.	Any live cell with more than three live neighbours dies, as if by overcrowding.
	4.	Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
	*/

	for (int x = 0; x < 20; x++)
	{
		for (int y = 0; y < 70; y++)
		{
			newBoard[x][y] = board[x][y];
			if (board[x + 1][y] == 'X')
				nCount++;
			else if (board[x - 1][y] == 'X')
				nCount++;
			else if (board[x][y + 1] == 'X')
				nCount++;
			else if (board[x][y - 1] == 'X')
				nCount++;
			if (nCount < 2 || nCount > 3) //rules 1 and 3
				newBoard[x][y] = ' ';
			else if (nCount == 2 || nCount == 3) //rule 2
				newBoard[x][y] = 'X';
			
		}
	}
	do
	{
		display(board, newBoard, 70, z);
		z++;
		system("pause");
		system("cls");
	} while(z < 51);
}

void display(char board[][20], char newBoard[][20], int size, int z)
{
	if (z == 1)
	{
		for (int x = 0; x < 20; x++)
		{ 
			for (int y = 0; y < 70; y++)
			{
				cout << board[x][y];
			}
			cout << endl;
		}
	}

	else 
	{
		for (int x = 0; x < 20; x++)
		{ 
			for (int y = 0; y < 70; y++)
			{
				cout << newBoard[x][y];
			}
			cout << endl;
		}
	}
	cout << endl;

}

Dani AI

Generated

Short diagnosis tied to the thread: the blank generations come from several interacting issues in the posted code — inconsistent row/column indexing, reading the board while writing it, out-of-bounds accesses at the edges, a neighbor counter that isn’t reset per cell, and logical/assignment mistakes when applying the rules. and spotted fragments of these; the checklist below ties those observations into concrete fixes and why each one matters.

Concrete fixes (apply in this order)

  • Pick and use one indexing convention: define const int ROWS = 20, COLS = 70; and treat the board as board[row][col] everywhere. That prevents the initial placement and later reads from talking past each other.
  • Always count neighbours from the current generation only. Use a separate write-only buffer (next/newBoard) for the computed state; never read neighbours from that buffer while computing.
  • Reset the neighbour counter for every cell: declare int n = 0; inside the inner loop so counts don’t accumulate across cells.
  • Prevent out-of-bounds reads. Either check bounds before accessing r+dr/c+dc, or implement wrap-around with modular arithmetic.
  • Use assignment (=) when setting newBoard[r][c], not equality (==). Also parenthesize compound conditions or split them into small boolean expressions so precedence won’t bite.
  • After computing newBoard, copy or swap buffers so the next generation reads the new state. Don’t repeatedly display a stale buffer.

Example pattern for counting neighbours (bounds-checked)

const int ROWS = 20, COLS = 70;
for (int r = 0; r < ROWS; ++r) {
  for (int c = 0; c < COLS; ++c) {
    int n = 0;
    for (int dr = -1; dr <= 1; ++dr)
      for (int dc = -1; dc <= 1; ++dc)
        if (dr != 0 || dc != 0) {
          int rr = r + dr, cc = c + dc;
          if (rr >= 0 && rr < ROWS && cc >= 0 && cc < COLS)
            if (board[rr][cc] == 'X') ++n;
        }
    // apply rules and assign to next[r][c] using '='
  }
}

Notes and cautions: undefined behavior from negative indices (e.g. board[-1][x]) can produce the “always blank” symptom. Switching to std::vector<string> or std::array and using swap() for double buffering simplifies copying and reduces mistakes. Running a debugger or printing n for a few sample cells will quickly confirm the neighbor-count logic.

Recommended Answers

All 4 Replies

There is a number of problems with the code. I don't know where to start.

To address your immediate question (my code will always make the new generation blank), check with the debugger (or just print out) the value of nCount. You will be surprised.

Second, your display() function is really funny. It displays the original board (once), and then goes on to display the same newBoard (which never changes anymore) for 50 times.

Third, your neighbour counting is plain wrong. In the game of life all 8 neigbours count, along with the cell itself.

Finally, when counting neighbours you have your indices backward (board defined to have first index in 0..69, and second index in 0..19), and you do step outside the board.

That's all I see with the naked eye. Maybe, there's more, but that's enough to keep you busy for now.

There is a number of problems with the code. I don't know where to start.

To address your immediate question (my code will always make the new generation blank), check with the debugger (or just print out) the value of nCount. You will be surprised.

Second, your display() function is really funny. It displays the original board (once), and then goes on to display the same newBoard (which never changes anymore) for 50 times.

Third, your neighbour counting is plain wrong. In the game of life all 8 neigbours count, along with the cell itself.

Finally, when counting neighbours you have your indices backward (board defined to have first index in 0..69, and second index in 0..19), and you do step outside the board.

That's all I see with the naked eye. Maybe, there's more, but that's enough to keep you busy for now.

1. I realize what you mean about nCount. I've fixed that now
2. My display function is supposed to display the initial configuration once, and then the new configuration afterwards. The reason that it is displaying thee same thing is because the changes haven't been made to the new array. I'm unsure of how to fix this.
3. I've now counted all 8 neighbors; I'll post my code

void neighbors(char board[][20], int size)
{
	char newBoard[70][20];
	unsigned int nCount;
	int z = 0;
	/*
	Rules:
	1.	Any live cell with fewer than two live neighbours dies, as if caused by under-population.
	2.	Any live cell with two or three live neighbours lives on to the next generation.
	3.	Any live cell with more than three live neighbours dies, as if by overcrowding.
	4.	Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
	*/

	for (int x = 0; x < 20; x++)
	{
		for (int y = 0; y < 70; y++)
		{
			nCount = 0;
			newBoard[y][x] = board[y][x];

			//count neighbors
			if (board[y-1][x-1] == 'X') nCount += 1;
            if (board[y-1][x] == 'X') nCount += 1;
            if (board[y-1][x+1] == 'X') nCount += 1;
            if (board[y][x-1] == 'X') nCount += 1;
            if (board[y][x+1] == 'X') nCount += 1;
            if (board[y+1][x-1] == 'X') nCount += 1;
            if (board[y+1][x] == 'X') nCount += 1;
            if (board[y+1][x+1] == 'X') nCount += 1;


			if (board[y][x] == 'X' && nCount < 2 || nCount > 3) //rules 1 and 3
				newBoard[y][x] == ' ';
			else if (board[y][x] == 'X' && nCount == 2 || nCount == 3) //rule 2
				newBoard[y][x] == 'X';
			else if (board[y][x] == ' ' && nCount == 3) //rule 4
				newBoard[y][x] == 'X';
		}
	}
	cout << nCount << endl;
	do
	{
		display(board, newBoard, 70, z);
		z++;
		system("pause");
		system("cls");
	} while(z < 50);
}

void display(char board[][20], char newBoard[][20], int size, int z)
{
	if (z == 0)
	{
		for (int x = 0; x < 20; x++)
		{ 
			for (int y = 0; y < 70; y++)
			{
				cout << board[y][x];
			}
			cout << endl;
		}
	}
	else 
	{
		for (int x = 0; x < 20; x++)
		{ 
			for (int y = 0; y < 70; y++)
			{
				cout << newBoard[y][x];
			}
			cout << endl;
		}
	}
	cout << endl;

}

I'm not quite sure why this isn't working for me. Any help or guidance would be appreciated. Thanks!

I'm trying to finish this assignment for class, and It seems as though I'm not calculating the neighbors correctly. It seems correct to me, but I'm not sure. Also, the rules for the game are not being applied to the new generation. Any help would be appreciated. Thank you for your time. Here's my code:

// Life.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <ctime>

using namespace std;

void generation(char[][20], int);
void neighbors(char[][20], int);
void display(char[][20], char[][20], int, int);

int _tmain(int argc, _TCHAR* argv[])
{
	int x = 0;
	char board[70][20];
	char s[2][2];
	
	srand(time(NULL));
	generation(board, 70);
	

	system("pause");
	return 0;
}

void generation (char board[][20], int size)
{
	
	int x = 0;	
	int number;
	
	
	for (int x = 0; x < 20; x++) //initial configuration
	{
		for (int y = 0; y < 70; y++)
		{
			board[y][x] = ' ';
			board[34][10] = 'X';
			board[35][10] = 'X';
			board[36][10] = 'X';
			board[19][6] = 'X';
			board[20][6] = 'X';
			board[21][6] = 'X';
			board[49][6] = 'X';
			board[50][6] = 'X';
			board[51][6] = 'X';

		}
	}

	neighbors(board, 70);
	
	
}

void neighbors(char board[][20], int size)
{
	char newBoard[70][20];
	int nCount = 0;
	int z = 0;
	/*
	Rules:
	1.	Any live cell with fewer than two live neighbours dies, as if caused by under-population.
	2.	Any live cell with two or three live neighbours lives on to the next generation.
	3.	Any live cell with more than three live neighbours dies, as if by overcrowding.
	4.	Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
	*/

	for (int x = 0; x < 20; x++)
	{
		for (int y = 0; y < 70; y++)
		{
			
			newBoard[y][x] = board[y][x];

			//count neighbors
			if (newBoard[y-1][x-1] == 'X') nCount += 1;
            if (newBoard[y-1][x] == 'X') nCount += 1;
            if (newBoard[y-1][x+1] == 'X') nCount += 1;
            if (newBoard[y][x-1] == 'X') nCount += 1;
            if (newBoard[y][x+1] == 'X') nCount += 1;
            if (newBoard[y+1][x-1] == 'X') nCount += 1;
            if (newBoard[y+1][x] == 'X') nCount += 1;
            if (newBoard[y+1][x+1] == 'X') nCount += 1;


			if (newBoard[y][x] == 'X' && nCount < 2 || nCount > 3) //rules 1 and 3
				newBoard[y][x] == ' ';
			else if (newBoard[y][x] == 'X' && nCount == 2 || nCount == 3) //rule 2
				newBoard[y][x] == 'X';
			else if (newBoard[y][x] == ' ' && nCount == 3) //rule 4
				newBoard[y][x] == 'X';
		}
	}
	cout << nCount << endl;
	do
	{
		display(board, newBoard, 70, z);
		z++;
		system("pause");
		system("cls");
	} while(z < 50);
}

void display(char board[][20], char newBoard[][20], int size, int z)
{
	if (z == 0)
	{
		for (int x = 0; x < 20; x++)
		{ 
			for (int y = 0; y < 70; y++)
			{
				cout << board[y][x];
			}
			cout << endl;
		}
	}
	else 
	{
		for (int x = 0; x < 20; x++)
		{ 
			for (int y = 0; y < 70; y++)
			{
				cout << newBoard[y][x];
			}
			cout << endl;
		}
	}
	cout << endl;

}

There a a few things that are a bit ugly about this code, and likely to be a source of error. [otherwise not a bad attempt]

The first is that you are using char board[70][20] then you are using
stuff like

void display(char board[][20], char newBoard[][20], int size, int z)
{
   if (z == 0)
     {
	for (int x = 0; x < 20; x++)
	  { 
	    for (int y = 0; y < 70; y++)
	      {
		cout << board[y][x];
     	      }
	    cout << endl;
	   }
	}
/....

Look you are passing size BUT not using it. If size was 100 or 20, what difference would it make. So either (a) defined two global constant variables e.g.

const unsigned int XSize(20);
const unsigned int YSize(70);
/// ....
char board[XSize][YSize];
///....
void display(char BB[XSize][YSize]) { //... }

or you can do something like this:
void display(const char** BB,const unsigned int XS,const unsigned YS)
{ /... }

I think that you should just pass a board to display either the newBoard or the Board. The flag is unnecessary .

Next, you then update newBoard and you do this

for (int y = 0; y < 70; y++)
   {	  
     newBoard[y][x] = board[y][x];
     //count neighbors
     if (newBoard[y-1][x-1] == 'X') nCount += 1;
     //.... 
     if (newBoard[y+1][x+1] == 'X') nCount += 1;
//...

three problems:

(i) if y == 0 and y-1 is.... -1 which is actually a very big number, therefore you get undeterminable result.

(ii) you see that you are using newBoard[y+1][x+1] BUT you haven't set that char yet.

(iii) You are not processing the wrap around of the board, e,g. the left edge is normally connected to the right edge.

What you need to do is, replaced newBoard with Board, fixed the wrapping issue.
That is when you are out of your range, you have to do something special. There are many ways to do that you will have to decide on one and try it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.