I tried to code a simple version of tic-tac-toe in C++ using the minimax algorithm but ran into a problem while trying to determine the position where the score is the best. The minEval (Returns score for min), maxEval(returns score for max) and playMove (determines which position to play and then plays the move) functions are shown below.
int maxEval(int board[9]) {
if (checkDraw(board)) {
return 0;
}
else if (checkWin(board)) {
return -1000;
}
int finalScore = -1000;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = 1;
int score = minEval(board);
if (score > finalScore) {
finalScore = score;
}
board[i] = 0;
}
}
return finalScore;
}
int minEval(int board[9]) {
if (checkDraw(board)) {
return 0;
}
else if (checkWin(board)) {
return 1000;
}
int finalScore = 1000;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = -1;
int score = maxEval(board);
if (score < finalScore) {
finalScore = score;
}
board[i] = 0;
}
}
return finalScore;
}
void playMove(int board[9], int player) {
int finalScore = player * -1000;
int position;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = player;
int score;
if (player == 1) {
score = maxEval(board);
}
else {
score = minEval(board);
}
if (player == 1 && score >= finalScore) {
finalScore = score;
position = i;
}
else if (player == -1 && score <= finalScore) {
finalScore = score;
position = i;
}
board[i] = 0;
}
}
board[position] = player;
}
When I tested different positions to see whether minEval and maxEval correctly evaluate the position, the functions return the correct score (1000 for max win, -1000 for min win and 0 for a draw). However, when I make the AI play by using the playMove function, it plays very dubious moves and almost always makes "incorrect" moves.
Here is an example of a game I made the program play (with itself):
I suspect that there is something wrong with the way I set position to i, but I tried to make changes to no avail. Any suggestions as to what is wrong with the evaluate function? Thanks.
Here is the link to the entire code: http://ideone.com/6791d4
I would check up on the variations found not just the scores. Are you finding just any winning variation, or the one where the opponent plays best?
e.g. Modify your min/max Eval code to also add the move chosen to an array.
BTW it may be easier to see what is happening if you combine the min/max Eval routines into one.
WARNING UNTESTED CODE
int minmaxEval(int board[9], int player, int moves[9], int move) {
if (checkDraw(board)) {
return 0;
}
int finalScore = player * -1000;
if (checkWin(board)) {
return finalScore;
}
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = player;
int score = minmaxEval(board, -player, moves, move+1);
if ( (player > 0 && score > finalScore) ||
(player < 0 && score < finalScore) ) {
finalScore = score;
moves[move] = i;
}
board[i] = 0;
}
}
return finalScore;
}
If you print out moves[] in your toplevel routine you should see the variation which gave that score. A mismatch there will inform your understanding of the algorithm e.g. is it stopping when it finds a win.
In general it is important to have a way to double check your code is doing what you expect. Look into unit testing and test-driven development.
Thanks for your insights, I solved the problem. There was a bug in the playMove function, where I mismatched maxEval and minEval, this causing the AI to not play for a win or draw. So, the corrected code is:
void playMove(int board[9], int player) {
int finalScore = player * -1000;
int position;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = player;
int score;
if (player == 1) {
score = minEval(board); //Previously Mismatched
}
else {
score = maxEval(board); //Previously Mismatched
}
if (player == 1 && score >= finalScore) {
finalScore = score;
position = i;
}
else if (player == -1 && score <= finalScore) {
finalScore = score;
position = i;
}
board[i] = 0;
}
}
board[position] = player;
}
Related
I have been trying to create a top-down game, similar to that of 'realm of the mad gods'. I am having some issues with getting my player movement to behave properly with my player movement.
Some things to keep in mind. There are 4 buffers located on each side of my player which is 1 pixel thick. When the player collides with a wall at a speed of 1 pixel, the player will stop and behaves as expected.
Here is the issue. I want my player to move faster than 1 pixel, but when I increase the player speed to 4 pixels, the player will move into the wall. this makes sense, but I have taken measures to avoid this, but have been unsuccessful so far.
Code sample 1 shows the movement code.
Code sample 2 shows the movement trigger code.
I have put the rest of the code on GitHub, which can be found through the following link: https://github.com/Quinn-R/top-down-tech-demo
Thanks for any help I receive.
EDIT: My player does not completely surpass the wall. Both the player and the wall are 32 pixel boxes.
EDIT2: Code sample 3 is the code that shows the game loop.
Code sample 1
void player::move(std::string direction, std::vector<wall> walls)
{
if(direction == "left")
{
for(int i = 0; i < walls.size(); i++)
{
if(leftBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || leftBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
{
//collideTop = 0;
//collideBottom = 0;
collideLeft = 1;
//collideRight = 0;
}
}
if(collideLeft != 1)
{
character.move(-1, 0);
collideTop = 0;
collideBottom = 0;
collideLeft = 0;
collideRight = 0;
}
}
if(direction == "right")
{
for(int i = 0; i < walls.size(); i++)
{
if(rightBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || rightBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
{
//collideTop = 0;
//collideBottom = 0;
//collideLeft = 0;
collideRight = 1;
}
}
if(collideRight != 1)
{
character.move(1, 0);
collideTop = 0;
collideBottom = 0;
collideLeft = 0;
collideRight = 0;
}
}
if(direction == "up")
{
for(int i = 0; i < walls.size(); i++)
{
if(topBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || topBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds())*/)
{
collideTop = 1;
//collideBottom = 0;
//collideLeft = 0;
//collideRight = 0;
}
}
if(collideTop != 1)
{
character.move(0, -1);
collideTop = 0;
collideBottom = 0;
collideLeft = 0;
collideRight = 0;
}
}
if(direction == "down")
{
for(int i = 0; i < walls.size(); i++)
{
if(bottomBuf.getGlobalBounds().intersects(walls[i].wall1.getGlobalBounds())/* || bottomBuf.getGlobalBounds().intersects(walls2[i].wall1.getGlobalBounds()*/)
{
//collideTop = 0;
collideBottom = 1;
//collideLeft = 0;
//collideRight = 0;
}
}
if(collideBottom != 1)
{
character.move(0, 1);
collideTop = 0;
collideBottom = 0;
collideLeft = 0;
collideRight = 0;
}
}
}
Code sample 2
void sfml1::buttonPressed()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
for(int i = 0; i < speed; i++)
{
players[0].move("left", walls);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
for(int i = 0; i < speed; i++)
{
players[0].move("right", walls);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
for(int i = 0; i < speed; i++)
{
players[0].move("up", walls);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
for(int i = 0; i < speed; i++)
{
players[0].move("down", walls);
}
}
}
Code sample 3
void sfml1::sfmlLoop()
{
setWalls();
while(window.isOpen())
{
update();
buttonPressed();
update();
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
/*if (event.type == sf::Event::Resized)
{
// update the view to the new size of the window
//event.size.width, event.size.height);
//view1.setWidth();
//view1.setViewport(sf::FloatRect(0, 0, 1, 1.5f));
view1.scale(1, 1);
window.setView(view1);
}*/
}
draw();
}
}
While inside the buttonPressed() function, your character's state is defined by its collision buffers. When you make this call:
for(int i = 0; i < speed; i++)
{
players[0].move("right", walls);
}
The move() function has the potential of changing the player's state, but this is not reflected in the player's collision buffer. You move speed times to the right while making the collision check from your initial position speed times.
All you need to do is call bufUpdate() at the end of your move() function. This will ensure that after the movement has been resolved, your collision buffer is updated.
So I am working on Huffman coding for a project. However, my code just doesn't work. When i ran it on visual studio, it didn't give me an error. What I was trying to do is to read a file and put all of them into a string. And get the frequency for each character in that string. But I think when the file got a little bit large, it seems like my code is running in a infinite loop. Can anyone explain anything to me? By the way, I had a sorted function that I used to sort a vector of node* by their frequency.
ifstream infile;
infile.open(filename);
string q;
string line;
while (getline(infile, line))
{
q += line;
}
char y;
int count = 0;
int check = 0;
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
}
}
if (check == 0)
{
for (int i = 0; i < q.size(); i++)
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}
sort(list1.begin(), list1.end(), sorter); //sort them from small to big
while (list1.size() > 1)
{
node*left = list1[0];
node*right = list1[1];
list1.erase(list1.begin(), list1.begin() + 2);
double sum = left->freq + right->freq;
node* x = new node;
x->freq = sum;
x->left = left;
x->right = right;
list1.push_back(x);
sort(list1.begin(), list1.end(), sorter);
}
list1.clear();
return true;
The following is my sort function
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() != '\0') {
return (int)a->getCharacter() < (int)b->getCharacter();
}
return false;
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
I see two major problems.
You have a for loop inside a for loop both initializing and using int i
Change the variable name of the inner loop.
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
.
.
if (check == 0)
{
for (int i = 0; i < q.size(); i++) //Change this to int j for example
{
.
.
And the Sorter struct. I would rewrite it as this.
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() == '\0') return true;
return (int)a->getCharacter() < (int)b->getCharacter();
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
A few suggestions for your for loop:
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
//You can avoid this entire loop by using a structure like map
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
//break; //if you use a loop, break it once you find the character.
}
}
if (check == 0)
{
for (int j = 0; j < q.size(); j++)//Renamed variable + you can start this loop from j = i as you know there is no occurrence of y before that.
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}
Im making this console game and the way im doing it is printing chars to the console from a 3 dimentional array called map. Which is assigned using the chars of the monsters, characters and background. The problem is i have been able to assign to the map array and print of successfully the char taken a monster class. But for some reason the derived character class objects aren't having their chars printed.
I am confident this is not an access issue cause there are no compiling errors and when the program runs there are empty gaps on the row(not the exact index but the right row index) that the characters are assigned to.
Here is the code that assigns it:
void game::assignScreen() {
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 40; col++) {
if (col == 0 || col == 39) {
map[row][col] = (char) 124;
} else if (row == 0 || row == 19) {
map[row][col] = (char) 95;
} else {
map[row][col] = (char) 46;
}
}
}
switch (difficulty) {
case 1:
for (int i=0; i <2; i++){
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
case 2:
if (difficulty == 2) {
for (int i = 0; i <4; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
}
map[elfPlayer.getPos(true)][elfPlayer.getPos(false)] = elfPlayer.getSymbol();
map[guardPlayer.getPos(true)][guardPlayer.getPos(false)] = guardPlayer.getSymbol();
map[knightPlayer.getPos(true)][knightPlayer.getPos(false)] = knightPlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
break;
case 3:
for (int i = 0; i <6; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
case 4:
if (difficulty == 4) {
for (int i = 0; i <9; i++) {
map[enemy[i]->getPos(true)][enemy[i]->getPos(false)] = enemy[i]->getSymbol();
}
}
map[elfPlayer.getPos(true)][elfPlayer.getPos(false)] = elfPlayer.getSymbol();
map[guardPlayer.getPos(true)][guardPlayer.getPos(false)] = guardPlayer.getSymbol();
map[knightPlayer.getPos(true)][knightPlayer.getPos(false)] = knightPlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
map[roguePlayer.getPos(true)][roguePlayer.getPos(false)] = roguePlayer.getSymbol();
break;
}
}
And this prints it
void game::printScreen(string msg) {
clearScreen();
cout << msg;
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 40; col++) {
if (map[row][col] == 'E' || map[row][col] == 'G' || map[row][col] == 'K' ||
map[row][col] == 'R' || map[row][col] == 'W') {
if (getPlayer(map[row][col]).getStatus() == 1) {
changeColor(14, false);
cout << map[row][col];
changeColor(15, false);
} else if (getPlayer(map[row][col]).getStatus() == 2 || getPlayer(map[row][col]).getStatus() == 3) {
changeColor(4, false);
cout << map[row][col];
changeColor(15, false);
}
} else {
cout << map[row][col];
}
}
cout << endl;
}
}
getPlayer is a function that takes the currently saved/selected char and returns the object it belongs to
position
int character::getPos(bool getX) {
if (getX) {
return xPos;
} else {
return yPos;
}
}
returns char
char character::getSymbol() {
return symbol;
}
header file
class character
{
public:
character();
~character();
string getName();
char getSymbol();
int getStatus();
int getPos(bool);
void setPos(int, int);
void setStatus(bool, bool);
protected:
string className;
char symbol;
private:
int xPos;
int yPos;
};
from game header file
monster *enemy[21];
elf elfPlayer;
guard guardPlayer;
knight knightPlayer;
rogue roguePlayer;
wizard wizardPlayer;
printScreen(elfPlayer.getName());
cout << elfPlayer.getSymbol();
I tested whether the postions for the objects can be printed, it's working for *enemy[], the derived classes look fine. I really have no idea why it's not printing right. Maybe im making a stupid mistake id just like some insight.
What happens when the map is printed, the bottom right empty area is meant to be full of chars
I turns out it was just a very silly mistake on my part. Thanks to Simon Kraemer for finding the problem.
I just added another else to print out stuff to the character if statement inside of the printScreen method.
Btw, what does it matter if i have a get positon function like that, it uses less space and is quicker to use. Also this is not a group project so confusion is not an issue (if i was in a group perhaps id change it).
I did my cellular automaton in c but now I want to convert it to c++ with using class and object. I am new in c++ that is why I need your help. My program crashes after typing decimal number. I think data is not transfered properly between the functions, but I send few hours on it and I cannot get it. I would be pleased if I could get any advice with finding when my error is. I've got 3 files. One is my main, one is file with functions, and the last one is a header.
Main:
#include <iostream>
#include "cellular.h"
using namespace std;
int main()
{
CA myCA;
myCA.run();
return 0;
}
File with functions:
#include "cellular.h"
#include <cstdio>
CA::CA()
{
int WIDTH = 59;
int numOfRules = 8;
currentState = new int [WIDTH];
nextState = new int[WIDTH];
storeTheRules = new int[numOfRules];
}
CA::~CA()
{
delete [] currentState;
delete [] nextState;
delete [] storeTheRules;
}
void CA::run()
{
int x;
int t;
//enter which cellular you want to print out
printf("Enter the number of cellular you want to print out 0-255 (-1 to end):\n");
scanf("%d", &number);
while(number != -1) {
if(number >= 0 && number <= 255) {
for(x = 0; x < WIDTH; x++) {
currentState[x] = 0;
}
for(x = 0; x < WIDTH; x++) {
t = (int)WIDTH/2;
currentState[t] = 1;
}
// convert decimal number to binary
decimalToBinary(number);
// print binary number
printf("In binary:");
for(x = 0; x < numOfRules; x++)
{
printf("%d", storeTheRules[x]);
}
printf("\n");
//print current state
printCellular();
printf("\n");
// calculate for next generation
calcNextGeneration();
// update array
updateArray();
}
else {
printf("\nWrong number entered! Try again\n");
}
//enter which cellular you want to print out
printf("\nEnter the number of cellular you want to print out 0-255 (-1 to end):\n");
scanf("%d", &number);
}
}
void CA::calcNextGeneration()
{
int i;
int j;
int LENGHT = 27;
for(j = 0; j < LENGHT; j++) {
for (i = 0; i < WIDTH; i++) {
left = currentState[i-1];
middle = currentState[i];
right = currentState[i+1];
nextState[i] = rules(left, middle, right);
}
updateArray();
printCellular();
printf("\n");
}
}
int CA::rules(int left,int middle, int right)
{
if(left == 1 && middle == 1 && right == 1)
return storeTheRules[0];
else if(left == 1 && middle == 1 && right == 0)
return storeTheRules[1];
else if(left == 1 && middle == 0 && right == 1)
return storeTheRules[2];
else if(left == 1 && middle == 0 && right == 0)
return storeTheRules[3];
else if(left == 0 && middle == 1 && right == 1)
return storeTheRules[4];
else if(left == 0 && middle == 1 && right == 0)
return storeTheRules[5];
else if(left == 0 && middle == 0 && right == 1)
return storeTheRules[6];
else if(left == 0 && middle == 0 && right == 0)
return storeTheRules[7];
return 0;
}
void CA::printCellular()
{
int i;
for(i = 0; i < WIDTH; i++) {
if(nextState[i] == 1 || currentState[i] == 1)
printf("#");
else
printf(" ");
}
}
void CA::updateArray()
{
int i;
for(i = 0; i < WIDTH; i++) {
currentState[i] = nextState[i];
}
}
// function to convert decimal number to binary
void CA::decimalToBinary(int n)
{
int k;
int i = 0;
for (numOfRules = 7; numOfRules >= 0; numOfRules--) {
k = n >> numOfRules;
if (k & 1)
storeTheRules[i] = 1;
else
storeTheRules[i] = 0;
i++;
}
printf("\n");
}
Header:
#ifndef CELLULAR_H_INCLUDED
#define CELLULAR_H_INCLUDED
// A cellular automaton class
class CA {
private:
int WIDTH;
int numOfRules;
int *currentState;
int *nextState;
int *storeTheRules;
int number;
int left, middle, right;
public:
// Constructor
CA();
// Destructor
~CA();
// Functions
void run();
int rules(int left, int middle, int right);
void calcNextGeneration();
void printCellular();
void updateArray();
void decimalToBinary(int n);
};
#endif // CELLULAR_H_INCLUDED
I am making my code in CodeBlocks. And.. include cstdio is because I didn't changed my printf's from C code yet.
Thank you for any help.
Regards,
Nel
I didn't read through everything, but a few issues upon first glance:
In your constructor you are creating local variables instead of accessing the class variables you intend to modify.
int WIDTH = 59;
int numOfRules = 8;
Also, just as a personal preference, I wouldn't organize this in such a way that a data entry loop getting input from the user is a part of a class. That could just be personal preference though.
I saw Conway's Game of Life and decided to make my own.
I have a bool array to represent the world, but the edges (Top and bottom) are acting weird, random cells becomes live.
In this code, it does not print the bottom and top of the world, but this is a bad solution.
The world "wraps" at the right and the left, causing even more problems, but that is for another time.
#include <iostream>
const int height = 20;
const int width = 20;
bool now_world[height][width];
bool then_world[height][width];
void clear_world();
void place_random_live_cells();
void then_world_initialization();
void print_world();
void generation_pass();
void update_worlds();
int main(int argc, const char * argv[])
{
using namespace std;
srand((unsigned)time(NULL));
int timer = 0;
int generation = 0;
clear_world();
place_random_live_cells();
then_world_initialization();
bool running = true;
while (running) {
if (timer == 50000000) {
cout << "Generation #" << generation << endl;
print_world();
generation_pass();
update_worlds();
++generation;
timer = 0;
}
++timer;
}//While (running) ends here
return 0;
}
void place_random_live_cells()
{
int percent = 30;
int max_live_cells = ((height * width) / 100) * percent;
int current_live_cells = 0;
while (current_live_cells < max_live_cells) {
int ycoords = 0 + (rand() % (height + 1));
int xcoords = 0 + (rand() % (width + 1));
if (now_world[ycoords][xcoords] == false) {
now_world[ycoords][xcoords] = true;
} else {
current_live_cells--;
}
++current_live_cells;
}
}
//A generation pass and cells die and some cells come to life
void generation_pass()
{
using namespace std;
int neighbours = 0;
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii+1][jjj ] == true) {
++neighbours;
}
if (now_world[iii+1][jjj-1] == true) {
++neighbours;
}
if (now_world[iii ][jjj+1] == true) {
++neighbours;
}
if (now_world[iii ][jjj-1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
if (now_world[iii-1][jjj ] == true) {
++neighbours;
}
if (now_world[iii-1][jjj-1] == true) {
++neighbours;
}
//Apply rules to the cells
//Dead cells with three live neighbours becomes alive
if (then_world[iii][jjj] == false && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with fewer than two, they die
if (then_world[iii][jjj] == true && neighbours < 2) {
then_world[iii][jjj] = false;
}
//Alive with 2 or three live neighbours live on unchanged
if (then_world[iii][jjj] == true && neighbours == 2) {
then_world[iii][jjj] = true;
}
if (then_world[iii][jjj] == true && neighbours == 3) {
then_world[iii][jjj] = true;
}
//Alive with more than three, they die
if (then_world[iii][jjj] == true && neighbours > 3) {
then_world[iii][jjj] = false;
}
//Dead cells without exactly three live neighbours remain dead
//Reset neighbour value to zero
neighbours = false;
}
}
}
//Make next generation identical to current
//This is only called once
void then_world_initialization()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
then_world[iii][jjj] = now_world[iii][jjj];
}
}
}
//Make the next generation be today
//This is called every generation
void update_worlds()
{
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = then_world[iii][jjj];
}
}
}
//Set all cells to dead
void clear_world()
{
for (long iii = 0; iii < height; iii++) {
for (long jjj = 0; jjj < width; jjj++) {
now_world[iii][jjj] = false;
then_world[iii][jjj] = false;
}
}
}
//Print world
void print_world()
{
using namespace std;
char live = 'X';
char dead = '.';
for (long iii = height; iii > 0; iii--) {
for (long jjj = width; jjj > 0; jjj--) {
if (iii != 0 && iii != height) {
if (now_world[iii][jjj]) {
cout << live;
} else {
cout << dead;
}
cout << " ";
}
}
cout << endl;
}
cout << endl;
}
Having done this for a course I taught in the past, the most common issue I always see people having is going outside the bounds of the array they're using.
If you look at the if statements in your nested for loop, I think you'll find some issues. For instance, in this case, what happens when iii equals (height-1) or jjj equals (width-1)?
for (int iii = 0; iii < height; iii++) {
for (int jjj = 0; jjj < width; jjj++) {
//Count neighbouring cells that are alive
if (now_world[iii+1][jjj+1] == true) {
++neighbours;
You're going outside the bounds of your array and so your results will be undefined. You may get segfaults, but you may just also get spurious data. C++ doesn't enforce you staying within the bounds of the array you define.
Make sure you also handle cases like this:
if (now_world[iii-1][jjj+1] == true) {
++neighbours;
}
What if iii equals zero?
Hope that helps.
You're trying to access out-of-boundary indexes in your array.
I'm not sure what behaviour you expect, but an easy way is to not calculate updates for cells on the edges.
So in generation_pass the loops should go from 1 till height-1.