Old 01-25-2014, 12:23 PM   #1
Psittacosis
AKA Cold Kitten
 
Psittacosis's Avatar
 
Join Date: Oct 2012
Posts: 91
Send a message via Skype™ to Psittacosis
Default C++ Conway's Game of Life

So, my lab for this week is to code a conway's game of life file and have it generate new generation and things. It's... sort of doing that, but it's not quite doing it right. It doesn't seem to be following any of the general rules for Conway's Game of Life and it's acting awfully odd.

(For those not familiar with Conway's Game of Life see here)

Anyway. I wish I could explain my problem better, but if anyone has had any experience with this, that would be great. Code is below

Code:
  6 #include <iostream>
  7 #include <iomanip>
  8 #include <fstream>
  9 #include <stdlib.h>
 10 #include <unistd.h>
 11 #include <time.h>
 12 #include "ansi.h"
 13
 14 using namespace std;
 15
 16 #define GRID_WIDTH 80
 17 #define GRID_HEIGHT 24
 18 #define DELAY 500000
 19
 20 void initGrid(bool grid[][GRID_WIDTH]);
 21 void initGrid(const char* fileName, bool [][GRID_WIDTH]);
 22 void renderGrid(bool [][GRID_WIDTH]);
 23 void nextGeneration(bool cur[][GRID_WIDTH], bool next[][GRID_WIDTH]);
 24
 25 int main(int argc, char **argv)
 26 {
 27   bool grid1[GRID_HEIGHT][GRID_WIDTH];
 28   bool grid2[GRID_HEIGHT][GRID_WIDTH];
 29   int generation = 1;
 30
 31   //initialize the grid
 32   if(argc==2)
 33   {
 34      initGrid(argv[1], grid1);
 35   }
 36   else
 37   {
 38      initGrid(grid1);
 39   }
 40  
 41   //run the generations, until the user presses ctrl+c
 42   while(true)
 43   {
 44     //show the appropriate grid, and generate the next population
 45     if(generation++ % 2)
 46     {
 47       //odd numbered generation
 48       renderGrid(grid1);
 49       nextGeneration(grid1, grid2);
 50     }
 51     else
 52     {
 53       //even numbered generation
 54       renderGrid(grid2);
 55       nextGeneration(grid2, grid1);
 56     }
 57
 58     //wait awhile before doing it again
 59     usleep(DELAY);
 60   }
 61
 62   return 0;
 63 }
 64
 65 //initialize the grid with random cells
 66 void initGrid(bool grid[][GRID_WIDTH])
 67 {
 68   //get the random number seeded with our present time
 69   srand(time(0));
 70
 71   //loop through each row
 72   for(int y=0; y < GRID_HEIGHT; y++)
 73   {
 74     //loop through each column
 75     for(int x=0; x < GRID_WIDTH; x++)
 76     {
 77       //1/3 of the cells are alive
 78       grid[y][x] = (rand() % 3) == 1;
 79     }
 80   }
 81 }
 82
 83 //initialize the grid from a file
 84 void initGrid(const char* fileName, bool grid[][GRID_WIDTH])
 85 {
 86   ifstream file;
 87   char c;
 88
 89   file.open(fileName);
 90
 91   //we are just going to assume that the file is valid
 92   //this is bad but in the interest of time, its okay
 93   for(int y=0; y < GRID_HEIGHT; y++)
 94   {
 95     for(int x=0; x < GRID_WIDTH; x++)
 96     {
 97       c=file.get();
 98
 99       if(c=='\n')
100       {
101         c=file.get();
102       }
103
104       grid[y][x]= c =='*';
105     }
106   }
107
108   file.close();
109 }
110
111 //render the grid
112 void renderGrid(bool grid[][GRID_WIDTH])
113 {
114   //loop through the grid, rendering as we go
115   for(int y=0; y < GRID_HEIGHT; y++)
116   {
117     for(int x=0; x < GRID_WIDTH; x++)
118     {
119       //go to the position
120       cout << cursorPosition(x+1, y+1);
121
122       //print the ' ' or '*'
123       cout << (grid[y][x] ? '*' : ' ');
124     }
125   }
126 }
127
128 //create the next generation. The cur grid generates the next grid
129 void nextGeneration(bool cur[][GRID_WIDTH], bool next[][GRID_WIDTH])
130 {
131
132   int count;
133
134
135   for(int y=0; y < GRID_HEIGHT; y++)
136   {
137     for(int x=0; x < GRID_WIDTH; x++)
138     {
139       count = 0;
140
141       //checks grid for asteriks
142       if((cur[y - 1][x]) == '*')
143       {
144         count = count + 1;
145       }
146       else if((cur[y + 1][x]) == '*')
147       {
148         count = count + 1;
149       }
150       else if((cur[y - 1][x - 1]) == '*')
151       {
152         count = count + 1;
153       }
154       else if((cur[y + 1][x + 1]) == '*')
155       {
156         count = count + 1;
157       }
158       else if((cur[y][x - 1]) == '*')
159       {
160         count = count + 1;
161       }
162       else if((cur[y][x + 1]) == '*')
163       {
164         count = count + 1;
165       }
166       else if((cur[y - 1][x + 1]) == '*')
167       {
168         count = count + 1;
169       }
170       else if((cur[y + 1][x - 1]) == '*')
171       {
172         count = count + 1;
173       }
174
175       //less than 2 living neighbors - cell dies: starvation
176       if((cur[y][x]) == '*' && (count < 2))
177       {
178         next[y][x] = ' ';
179         cout << "h" << "\n";
180       }
181       //more than 3 living neighbors - cell dies: overcrowding
182       else if((cur[y][x]) == '*' && (count > 3))
183       {
184         next[y][x] = ' ';
185         cout << "i" << "\n";
186       }
187       //2 or 3 living neighbors - cell stays alive: stability
188       else if((cur[y][x]) == '*' && count == 2 || count == 3)
189       {
190         next[y][x] = '*';
191         cout << "j" << "\n";
192       }
193       //dead cell with exactly 3 neighbors - cell is reborn: reproduction
194       else if((cur[y][x]) == ' ' && count == 3)
195       {
196         next[y][x] = '*';
197         cout << "j" << "\n";
198       }
199
200     }
201   }
202 }
And for anyone wondering just exactly what my code is doing when I run it, it's doing this

Last edited by Psittacosis; 01-25-2014 at 01:12 PM..
Psittacosis is offline   Reply With Quote
Old 01-25-2014, 01:12 PM   #2
Kekeb
davai
FFR Veteran
 
Kekeb's Avatar
 
Join Date: Dec 2006
Age: 28
Posts: 2,765
Default Re: C++ Conway's Game of Life

You're treating your grid like it's an array of characters when it's boolean (true or false, not '*', ' ', or any other character).

I suspect your confusion might stem from this line of code,
Code:
cout << (grid[y][x] ? '*' : ' ');
which isn't checking to see if the character within the grid is '*' or ' '. The ? operator equates the previous condition and evaluates one of the following expressions depending on the result of the condition (in this case, returning '*' if the grid is true (1) at (y,x) or returning ' ' if the grid is false (0) at (y,x)) The character that's returned by the statement is then passed into cout.

Be careful about extending beyond the bounds of your arrays.

Last edited by Kekeb; 01-25-2014 at 01:29 PM.. Reason: dont know c++
Kekeb is offline   Reply With Quote
Old 01-25-2014, 04:15 PM   #3
reuben_tate
Kawaii Desu Ne?
Sectional ModeratorFFR Veteran
 
reuben_tate's Avatar
 
Join Date: Dec 2007
Location: The Kawaiian Island~
Age: 26
Posts: 4,118
Default Re: C++ Conway's Game of Life

Quote:
Originally Posted by Kekeb View Post

Be careful about extending beyond the bounds of your arrays.
This is the first thing I noticed myself. One possible easy fix if you don't want to deal with having a lot of "if" constructs to check if you're within your boundaries, is to implement circular boundary conditions and do your operations in mod n (i.e. having "whatever % n" in your code) where n*n is your grid size. In this way, the game will play as if it's a pacman universe (or you can imagine folding up your grid into a torus if you can visualize that :P).
__________________
AMA: http://ask.fm/benguino

Happening now! Click to join!



Quote:
Originally Posted by Spenner View Post
(^)> peck peck says the heels
Quote:
Originally Posted by Xx{Midnight}xX
And god made ben, and realized he was doomed to miss. And said it was good.
Quote:
Originally Posted by Zakvvv666
awww :< crushing my dreams; was looking foward to you attempting to shoot yourself point blank and missing
reuben_tate is offline   Reply With Quote
Old 01-25-2014, 04:51 PM   #4
Charu
Snivy! Dohoho!
FFR Simfile AuthorFFR Veteran
 
Charu's Avatar
 
Join Date: Mar 2006
Age: 28
Posts: 6,970
Default Re: C++ Conway's Game of Life

Fission wanted to help out in this thread, since he can't, I'm going to do it in his place.

Quote:
Originally Posted by Fission
prefer "const int" declaration to #define macros. also prefer cstdlib and ctime to stdlib.h and time.h. what is the purpose of ansi.h? you don't appear to use any of it's functionality.

you use statements such as "generation++ % 2" but also use "count = count + 1"; you should be consistent.

"//we are just going to assume that the file is valid
//this is bad but in the interest of time, its okay"
i disagree with this being ok in the interest of time. all you have to do is wrap up your open call in an if statement and exit if it's false with some message. it doesn't take much time to do and it's really bad form not to like you said.

you mentioned c++. that means calls such as file.close() are unnecessary because destructors will take care of closing file handles. i don't know if this is something your instructor wants you to do, but it's worth noting.

finally, you should use a debugger when something like this happens and step through one statement at a time and find out where your program isn't doing exactly what you expected. that's the general procedure to dealing with issues like this in small programs. in bigger programs you would use breakpoints and do the same thing.
__________________


Quote:
Originally Posted by JohnRedWolf87 View Post
Charu the red-nosed Snivy
Had a very shiny nose
And if you ever saw it
You could even say it glows

All of the other Snivies
Used to laugh and call him names
They never let poor Charu
Join in any Snivy games

(Click the arrow to see the rest)


Quote:
Originally Posted by Vendetta21 View Post
All in all I would say that Charu not only won this game, his play made me reconsider how I play it.
Charu is offline   Reply With Quote
Old 01-25-2014, 06:31 PM   #5
Psittacosis
AKA Cold Kitten
 
Psittacosis's Avatar
 
Join Date: Oct 2012
Posts: 91
Send a message via Skype™ to Psittacosis
Default Re: C++ Conway's Game of Life

Let me explain that a lot of this base file is from my instructor. The #define is from him, assuming that the file is correct is from him (I know it's not difficult to check or anything), etc. He basically gave us the base code and then told us to make it work. I guess I should have clarified that. Same with the libraries.

Also ansi.h is for cursorPosition, and at some point in time, it will be to modify some of the text. Again, that's something my instructor wants. Wouldn't bother if he wouldn't have told me to.

EDIT: I also fixed some of the consistency issues after I went back and looked at it.

Last edited by Psittacosis; 01-25-2014 at 06:37 PM..
Psittacosis is offline   Reply With Quote
Old 01-25-2014, 06:50 PM   #6
TC_Halogen
Rhythm game specialist.
Simfile JudgeFFR Simfile AuthorFFR Music ProducerD7 Elite KeysmasherFFR Veteran
 
TC_Halogen's Avatar
 
Join Date: Feb 2008
Location: Bel Air, Maryland
Age: 28
Posts: 18,589
Send a message via AIM to TC_Halogen Send a message via Skype™ to TC_Halogen
Default Re: C++ Conway's Game of Life

Fission has asked me to post this on his behalf:

Quote:
Originally Posted by Fission
using #define works, it's just not best practice since it's not type checked and simply does text substitution. there is nothing wrong with the headers but you should prefer the ones prefixed with "c" rather than the ones postfixed with ".h". you don't have to do these things, i just recommend it so you are writing more idiomatic c++ rather than a mix of c and c++.

my bad about sursorPosition. i didn't look at the code you included carefully enough. it makes sense now though.
TC_Halogen is offline   Reply With Quote
Old 01-25-2014, 07:10 PM   #7
Psittacosis
AKA Cold Kitten
 
Psittacosis's Avatar
 
Join Date: Oct 2012
Posts: 91
Send a message via Skype™ to Psittacosis
Default Re: C++ Conway's Game of Life

If I'm coding the entire file myself, I do tend to use actual c++ libraries over c. Again, instructor's base file. Same with using const int over #define.

Thanks for the suggestions though.
Psittacosis is offline   Reply With Quote
Old 04-24-2014, 03:30 PM   #8
igotrhythm
Fractals!
FFR Veteran
 
igotrhythm's Avatar
 
Join Date: Sep 2004
Location: Meesheegan
Age: 34
Posts: 6,533
Send a message via Skype™ to igotrhythm
Default Re: C++ Conway's Game of Life

Quote:
Originally Posted by reuben_tate View Post
This is the first thing I noticed myself. One possible easy fix if you don't want to deal with having a lot of "if" constructs to check if you're within your boundaries, is to implement circular boundary conditions and do your operations in mod n (i.e. having "whatever % n" in your code) where n*n is your grid size. In this way, the game will play as if it's a pacman universe (or you can imagine folding up your grid into a torus if you can visualize that :P).
Just say that the grid will wrap around like in Asteroids. No reason to break people's brains with the idea of a torus.

Edit: Ooh, CK, check this out. http://en.wikipedia.org/wiki/Conway&...ife#Algorithms
__________________
Quote:
Originally Posted by thesunfan View Post
I literally spent 10 minutes in the library looking for the TWG forum on Smogon and couldn't find it what the fuck is this witchcraft IGR

Last edited by igotrhythm; 04-24-2014 at 03:39 PM..
igotrhythm is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump



All times are GMT -5. The time now is 03:33 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
Copyright FlashFlashRevolution