How to check for neighbors in Game of Life C++? - c++

I am working on an assignment for school and of course I receive very vague feedback on our code. The code I am working on is for Conway's Game of Life. I know I am super close. I have code that prints out the new generation but it's definitely not the correct one. It seems it is not counting the neighbors correctly - what should be identified as an alive neighbor doesn't seem to happen.
From our assignment as well (seeing examples of generations being formed) I notice the border cells do change which means I have to access them without going out of bounds. I feel I have been fruitless in my attempts to do this and I think I'm just missing something super obvious.
Please, any feedback would be amazing.
I have several print lines in attempts of debugging.
void gameOfLife(vector<vector<string>> &originalGrid, vector<vector<string>> &grid, int row, int col,
int Rows, int Cols){
//counts # of alive neighbors
int aliveNeighbors = 0;
string alive = "*";
for(int posX = row-1; posX <= row+1; posX++){
for(int posY = col-1; posX <= col+1; posX++){
std::cout << "I am in function - nested loop " << row << " " << col << std::endl;
if(posX == row && posY == col){
continue;
}
else if((posX >= 0 && posX < Rows) && (posY >= 0 && posY < Cols)){
std::cout << "I am in function - nested loop - else if " << row << " " << col << std::endl;
if(grid[posX][posY] == alive){
aliveNeighbors++;
std::cout << "alive neighbors: " << aliveNeighbors << std::endl;
}
}
}
}
/*
//top cell
if(grid[row][col-1] == "*"){
std::cout << "top cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//bottom cell
if(grid[row][col+1] == "*"){
std::cout << "bottom cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//left cell
if(grid[row-1][col] == "*"){
std::cout << "left cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//right cell
if(grid[row+1][col] == "*"){
std::cout << "right cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//top left
if(grid[row-1][col-1] == "*"){
std::cout << "top left cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//top right
if(grid[row+1][col-1] == "*"){
std::cout << "top right cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//bottom left
if(grid[row-1][col+1] == "*"){
std::cout << "bottom left cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
//bottom right
if(grid[row+1][col+1] == "*"){
std::cout << "bottom right cell " << row << " " << col << std::endl;
aliveNeighbors++;
}
*/
//test cases
//test case 1: Any live cell with fewer than two live neighbors dies (as if by underpopulation).
if(grid[row][col] == alive && aliveNeighbors < 2){
originalGrid[row][col] = ".";
}
//test case 2: Any live cell with more than three live neighbors dies (as if by overpopulation/overcrowding).
if(grid[row][col] == alive && aliveNeighbors > 3){
originalGrid[row][col] = ".";
}
//test case 3: Any live cell with two or three live neighbors lives, unchanged, to the next generation.
if(grid[row][col] == alive && (aliveNeighbors == 3 || aliveNeighbors == 2)){
originalGrid[row][col] = grid[row][col];
}
//test case 4: Any dead cell with exactly three live neighbors will come to life (as if by reanimation or birth).
if(grid[row][col] == "." && aliveNeighbors == 3){
originalGrid[row][col] = alive;
}
//prints updated grid
for(int i = 0; i < Rows; i++){
for(int j = 0; j < Cols; j++){
std::cout << originalGrid[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
return;
}
int main() {
int rows, col, numOfGen;
std::cin >> rows >> col >> numOfGen;
string cell;
vector<vector<string>> game;
for(int i = 0; i < rows; i++){
vector<string> temp;
for(int j = 0; j < col; j++){
std::cin >> cell;
temp.push_back(cell);
}
game.push_back(temp);
}
vector<vector<string>> firstGen;
firstGen.insert(firstGen.end(),game.begin(),game.end());
if(numOfGen == 0){
std::cout << "numOfGen == 0" << std::endl;
for(int i = 0; i < rows; i++){
for(int j = 0; j < col; j++){
std::cout << game[i][j] << " ";
}
std::cout << std::endl;
}
}
for(int g = 0; g <= numOfGen; g++){
for(int i = 1; i < rows; i++){
for(int j = 1; j < col; j++){
gameOfLife(game, firstGen, i, j, rows, col);
}
}
if(g == numOfGen){
for(int i = 0; i < rows; i++){
for(int j = 0; j < col; j++){
std::cout << game[i][j] << " ";
}
std::cout << std::endl;
}
}
}
return 0;
}

Looks like firstGen never gets updated, so you're just computing the first generation over and over. So your output is probably correct for a single generation, but it's the same for any number of generations. Also, check the conditions on your main driver loop: with for(int g = 0; g <= numOfGen; g++) the loop executes numOfGen+1 times.

Related

How to use loop to display looped information all at once? Functionality Issue

I am learning C++ and would like some help with functionality for my code below.
Quick summary/usage of my code: Program is to display randomized (x,y) coordinates and then print out the coordinates in a grid.
I got everything to work regarding randomizing (x,y) coordinates and then displaying their grid location.
The problem I am having is my code displays a separate grid for each coordinate instead of showing ALL coordinates on the same grid. [I attached a picture of my current output below].
I know this is a functionality issue.. but I am having trouble thinking of how to manipulate my loops so that the coordinates can be displayed first, followed by ONE grid with all the coordinates on it... I hope this makes sense.
Snippet of my code:
//Note: value of n and k is given by user earlier in the code
vector<vector<int> > vec( n , vector<int> (n));
cout << "\nGrid with city locations:\n";
for(i=0; i<k; i++) {
//random select int coordinates (x,y) for each K(cities)
x = rand() % n + 0;
y = rand() % n + 0;
arrCity[i] = i;
//display coordinates for city 1..city2.. etc
cout << "City " << arrCity[i] <<": (" << x << "," << y << ")" << endl;
//display cities on grid
for (int rows=0; rows < n; rows++) {
for (int columns=0; columns < n; columns++) {
if ((rows == y) && (columns == x)) {
cout << "|" << (i);
} else {
cout << "|_";
}
}
cout << "\n";
}
cout << "\n";
}
Current Output:
As you can see there's a separate grid for each 'city coordinate'
You need to store all city coordinates in order to display them on a single grid print.
In the code below I changed a few things in order to hopefully address your problem.
I have moved all city-related data into a structure
Then all cities are initialized before the grid output
When printing the grid, we have to search all cities if their coordinates match the current position, if so, we print the corresponding index.
Live Demo
#include <vector>
#include <iostream>
struct City
{
int index;
int x, y;
City(int index_, int x_, int y_)
: index(index_), x(x_), y(y_)
{ }
};
int main()
{
int n = 10;
int k = 6;
std::vector<City> arrCity;
arrCity.reserve(k);
for(int i = 0; i < k; i++)
arrCity.emplace_back(i, rand() % n, rand() % n);
std::cout << "\nGrid with city locations:\n";
for (int k = 0; k < arrCity.size(); k++)
std::cout << "City " << arrCity[k].index << ": (" << arrCity[k].x << "," << arrCity[k].y << ")" << std::endl;
//display cities on grid
for (int i=0; i < n; i++) {
for (int j=0; j < n; j++) {
int w = -1;
for (int k = 0; k < arrCity.size(); k++)
if ((i == arrCity[k].y) && (j == arrCity[k].x))
w = k;
if (w >= 0)
std::cout << "|" << arrCity[w].index;
else
std::cout << "|_";
}
std::cout << "\n";
}
return 0;
}
You need to track which cells already has been visited. That's why you need to take another array which stores the cells that are already visited and by which value.
int vis[n][n];
memset(vis, -1, sizeof vis);
for(i=0; i<k; i++) {
//random select int coordinates (x,y) for each K(cities)
x = rand() % n + 0;
y = rand() % n + 0;
arrCity[i] = i;
vis[x][y] = i;
//display coordinates for city 1..city2.. etc
cout << "City " << arrCity[i] <<": (" << x << "," << y << ")" << endl;
//display cities on grid
for (int rows=0; rows < n; rows++) {
for (int columns=0; columns < n; columns++) {
if (vis[rows][columns] != -1) {
cout << "|" << (vis[rows][columns]);
} else {
cout << "|_";
}
}
cout << "\n";
}
cout << "\n";
}
Output:

c++ coordinate grid map marking coordinates

ifstream myfile;
myfile.open("config.txt");
if (myfile.fail())
{
cerr << "Error opening config file" << endl;
myfile.close();
}
int line_no = 0;
while (line_no != 3 && getline(myfile, line3)) {
++line_no;
}
while (line_no != 7 && getline(myfile, line7)) {
++line_no;
}
while (line_no != 10 && getline(myfile, line10)) {
++line_no;
}
while (line_no != 14 && getline(myfile, line14)) {
++line_no;
}
while (line_no != 18 && getline(myfile, line18)) {
++line_no;
}
cout << line3 << endl;
cout << line7 << endl;
cout << line10 << endl;
cout << line14 << endl;
cout << line18 << endl;
gridXIdxA = stoi(ExtractString(line3, "=", "-"));
gridXIdxB = stoi(ExtractString(line3, "-", "\n"));
gridYIdxA = stoi(ExtractString(line7, "=", "-"));
gridYIdxB = stoi(ExtractString(line7, "-", "\n"));
cout << gridXIdxA << endl;
cout << gridXIdxB << endl;
cout << gridYIdxA << endl;
cout << gridYIdxB << endl;
int y = gridYIdxB + 1;
y > -1;
mapBoundaryX = gridXIdxB + 6; // dynamic array to print out boundary of city map
mapBoundaryY = gridYIdxB + 4;
int** dMapBoundaryArray;
dMapBoundaryArray = new int*[mapBoundaryX]();
for (int i = 0; i < mapBoundaryX; i++)
{
dMapBoundaryArray[i] = new int[mapBoundaryY];
}
for (int i = 0; i < mapBoundaryX; i++)
{
cout << endl;
for (int j = 0; j < mapBoundaryY; j++)
{
dMapBoundaryArray[i][j] = i;
if (i == 0 && j > 0 && j < gridXIdxB+4)
{
cout << "# "; // top
}
if (i == 0 && j == 0)
{
cout << " ";
}
if (i == (gridYIdxB+2) && j > 0 && j < gridXIdxB+4)
{
cout << "# "; // bottom
}
if (i == (gridYIdxB + 2) && j == 0)
{
cout << " ";
}
if (i>0 && i<12 && j==1)
{
cout << "#"; // left
}
else if (i == 6 && j == 3)
{
cout << " ";
cout << 3;
}
else if (i == 6 && j == 4)
{
cout << " ";
cout << 3;
}
else if (i == 7 && j == 4)
{
cout << " ";
cout << 3;
}
else if (i > 0 && i < 12 && j == 13) //right
{
cout << setw(24)<<right << "#";
}
if (i == 13 && j > -1 && j < 2) //x axis
{
cout << " ";
}
if (i == 13 && j > 1 && j < 13)
{
x = x++;
cout <<" " << x; //x axis
}
if (j == 0 && i <= gridYIdxB+1 && i >= 1) // y axis
{
y = --y;
cout << y; //y axis
}
}
}
Hi, have some questions that i need help with, beginner to c++ currently so definitely appreciate if stuff can be explained in simple terms. I can manage to create the edges of the coordinate map but I also need to pinpoint certain coordinates within the map and mark them for eg. with a '3'. Is there anyway to pinpoint the coords without moving the column of '#' on the right?
Output
before marking coords
after marking coords
You may already have noticed that C++ alone has no facilities to set a character at a certain position on the screen. curses is a rather wide-spread library that helps with that. However, if you want to stay with your own code you can still get some inspiration from how curses handles output. The contents of the screen are buffered in memory and only when you request it all of it is updated. You can do similar in your own code. Store the contents you want to print on the screen in a std::vector<std::vector<char> or a std::vector<std::string>. Modify the contents as desired and when printing you do not have to bother about alignment and formatting anymore, it is just a simple loop:
for (const auto& line : screen) {
for (const auto& character : line) std::cout << character;
std::cout << "\n";
}

How to update a game board? c++

I'm trying to make a dungeon crawlesque game and I have this code to create a game board. I'm using 'F' as the finish point and 'P' for the player.
void Gameboard::CreateGameboard()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
GameGrid[i][j] = 'x';
}
}
cout << " 0 1 2 3 4 5 6 7 8 9 10" << endl;
cout << " +---------------------+" << endl;
for (int i = 0; i < 10; i++)
{
cout << " " << "|" << GameGrid[i][0];
for (int j = 0; j < 10; j++)
{
if (i == Spawn[0] && j == Spawn[0])
{
GameGrid[0][0] = 'P';
}
cout << " " << GameGrid[i][j];
}
cout << "|" << endl;
}
cout << " +---------------------+" << endl;
}
The problems I'm facing are. 'P' is being placed in the first two slots of the board and unsure why. And how would I update the board with player movement? I have a Player class with x,y position variables and my thought is to increment down/up based on where they're going. Is it required to reprint the whole board after every movement?
With your drawing of the board.
for (int i = 0; i < 10; i++)
{
cout << " " << "|" << ***GameGrid[i][0]***;
for (int j = 0; j < 10; j++)
{
cout << " " << GameGrid[i][j];
}
cout << "|" << endl;
}
You print out the first item of the row, then print the whole row, including the first item again. so each row will have a double up of the first item.
As for your second question, clearing the screen is exactly what you'll have to do. If you're using windows then you can use system("cls"); to 'clear' the console and then redraw. I would recommend putting the board drawing and board creation into different functions.

How do I exit a loop in C++ without using break?

I'm writing a code to swap integers in an array and I want to know how I can exit a loop without using a break statement and keeping my logic consistent. Here is my code below:
int swapped = 0;
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
for (int i = 1; i < arraycount; ++i)
{
for (int j = 1; j < arrays[i][0] + 1; ++j)
{
if (arrays[i][j] % 2 != 0)
{
int temp = arrays[i][j];
cout << "Array #" << 1 << " value " << arrays[0][first] << " swapped with "
<< "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
swapped = 1;
break;
}
}
if (swapped) {
break;
}
Use goto [I'll be bashed because of this].
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
for (int i = 1; i < arraycount; ++i)
{
for (int j = 1; j < arrays[i][0] + 1; ++j)
{
if (arrays[i][j] % 2 != 0)
{
int temp = arrays[i][j];
cout << "Array #" << 1 << " value "
<< arrays[0][first] << " swapped with "
<< "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
goto done;
}
}
done:
something;
for (int i = 1; i < arraycount && !swapped; ++i)
{
for (int j = 1; j < arrays[i][0] + 1 && !swapped; ++j)
{
if(arrays[i][j] % 2 != 0)
int temp = arrays[i][j];
cout << "Array #" << 1 << " value " << arrays[0][first] << " swapped with " << "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
swapped = 1;
}
}
}
this will do the same thing you have in inner loop.
Using a Break statement does not necessarily make your codes logic inconsistent and breaks are often useful to improve the readability of your code. But in answer to your question this can be achieved by utilizing while loops and logical boolean operators. A modified version of your code is below, I have tried to modify it as little as possible so you can still see your code within the example. There are a few logical errors in your code that I have left in the example below that you might want to look into. In particular the line below will print "is odd" when in fact the number would be even. If you where wanting to check if the number arrays[0][first] is odd then the following if statement would be needed if (arrays[0][first] % 2 != 0) instead of if (arrays[0][first] % 2 == 0).
Logical Error
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
This is the code without using breaks.
bool swapped = true;
if (arrays[0][first] % 2 == 0)
{
cout << arrays[0][first] << " is odd " << endl;
int i = 1;
while ( (i < arraycount) && swapped)
{
int j = 1;
bool if_odd = true;
while ((j < arrays[i][0] + 1) && if_odd)
{
if (arrays[i][j] % 2 != 0)
{
int temp = arrays[i][j];
cout << "Array #" << 1 << " value " << arrays[0][first] << " swapped with "
<< "Array #" << i << " value " << temp;
arrays[i][j] = arrays[0][first];
arrays[0][first] = temp;
swapped = false;
if_odd = false;
}
j++;
}
i++;
}
}

How can I let users to input values into the sudoku board?

I'm having trouble generating and inserting numbers inside the Board. Here is what I have so far:
enter code here
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
bool Valid_Set(int line[])
{
bool found = true;
for (int t = 1; (t <= 9 && found); ++t)
{
found = false;
for (int i = 0; i < 9; ++i)
if (line[i] == t) found = true;
}
return found; // returns true if all value 1-9 are in array.
}
bool Valid_Matrix(int sud[9][9])
{
int i, j, check[9];
bool valid = true;
// check each row
for (j = 0; (j < 9) && valid; ++j)
{
for (i = 0; i < 9; ++i)
check[i] = sud[i][j];
valid = Valid_Set(check);
}
// check each column
for (j = 0; (j < 9) && valid; ++j)
{
for (i = 0; i < 9; ++i)
check[i] = sud[j][i];
valid = Valid_Set(check);
}
// check 3x3 area
for (i = 0; (i < 9) && valid; i += 3)
{
for (j = 0; (j < 9) && valid; j += 3)
{
int t = 0;
for (int x = 0; x < 3; ++x)
for (int y = 0; y < 3; ++y)
check[t++] = sud[x + i][y + j];
valid = Valid_Set(check);
}
}
return valid;
}
void numGenerator(int A[]){
for (int i=0; i<9; i++){
A[i]=(1+rand()%9);
}
}
bool check_for_validity(int A[]){
int counter=0;
while (counter!=9){
numGenerator(A);
counter++;
}
for (int i=0; i<9; i++)
for (int j=0; j<9; j++){
if(A[j]==A[i])
numGenerator(A);
}
return true;
}
void main (){
//Descriptions and genral ideas
cout << "WELCOME TO SUDOKU " << endl;
cout << endl;
cout << "RULES: "<< endl;
cout << endl;
cout << "->You'll be given a 9x9 board with some numbers depending on which level of difficulty you choose to play."<< endl;
cout << endl;
cout << "->You have to arrange numbers from 1 to 9 so that a number shows up once in one row, one column and in a 3x3 box." << endl;
cout << endl;
cout << "So, let's get started" << endl;
cout << endl;
cout <<endl;
char dash[9][9];
for (int array=0; array<9; array++) {
for (int array2=0; array2<9; array2++) {
dash[array][array2]='_';
}
}
char row[9];
char column[9];
int num[81];
int num2[9][9];
int length;
length=strlen(row);
//Replaces the _'s in the specified rows/columns and replaces them with the integer the user specified.
for (int i=0; i<length; i++) {
dash[row[i]][column[i]]=num[i]+'0';
}
//Builds the Sudoko board and outputs the full 9x9 array.
cout << " 0 1 2 3 4 5 6 7 8 " << endl;
cout << "-----------------------------------------" << endl;
int i=0;
for (int count=0; count<3; count++) {
for (int count2=0; count2<3; count2++) {
cout << "||_" << dash[count][count2*3] << "_|_" << dash[count][count2*3+1] << "_|_" << dash[count][count2*3+2] << "_";
}
cout << "||" << i << endl;
i++;
}
cout << "-----------------------------------------" << endl;
int j=3;
for (int count=3; count<6; count++) {
for (int count2=0; count2<3; count2++) {
cout << "||_" << dash[count][count2*3] << "_|_" << dash[count][count2*3+1] << "_|_" << dash[count][count2*3+2] << "_";
}
cout << "||" << j << endl;
j++;
}
cout <<"-----------------------------------------" << endl;
int z=6;
for (int count=6; count<9; count++) {
for (int count2=0; count2<3; count2++) {
cout << "||_" << dash[count][count2*3] << "_|_" << dash[count][count2*3+1] << "_|_" << dash[count][count2*3+2] << "_";
}
cout << "||" << z << endl;
z++;
}
cout << "-----------------------------------------" << endl;
for (int row = 0; row < 9; row++) {
cout << "Enter values for row " << row + 1 << " : ";
for (int col = 0; col < 9; col++)
cin >> dash[row][col];
cout << endl << endl;
}
system("pause");
}
This whole section is wrong
char row[9];
char column[9];
int num[81];
int num2[9][9];
int length;
length=strlen(row);
//Replaces the _'s in the specified rows/columns and replaces them with the integer the user specified.
for (int i=0; i<length; i++) {
dash[row[i]][column[i]]=num[i]+'0';
}
You are using row and column even though they haven't got any values. Most likely this will crash your program.
Hard to know what you expected this to do. Perhaps you could explain?
Here's a suggestion for inputing values. Maybe you'll find it useful
// get the user's values
int row, column, value;
cout << "Enter a row number, column number, and value. All numbers should be between 1 and 9\n";
cin >> row >> column >> value;
// put the value in the board, add '0' to convert the integer to a digit
dash[row][column] = value + '0';