Thread: Game of life

  1. #16
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Neither look right to me. Using the 2:3 rules, you should end up with a lot of familiar shapes:

    Code:
    **
    **
    
     **
    *  *
     **
    
    ***
    
        *
        *
        *
    
    ***   *** 
     
        *
        *
        *
    ...and some others I can't be arsed to draw in ASCII.

  2. #17
    *this
    Join Date
    Mar 2005
    Posts
    498
    well it doesnt necessarily come up with those patterns, depending on the rules, and given coordinates they differ.

    here is what i came up with to make sure its not out of boundaries, but it still does not work properly...any suggestions?

    Code:
    /***************************
    Made by: Joshua R
    Date Created:
    Date Finished:
    Lesson 18, LAB EXERCISE LIFE
    ***************************/
    #include <iostream>
    #include <fstream>
    #include <iomanip>
    using namespace std;
    
    //array max needs to be one more
    //row and column 0 won't be used
    const int MAX = 20 + 1;
              
    void fill (char [ MAX ][ MAX ]);
    void getBacteria (char [ MAX ][ MAX ], int &);
    void oneGeneration (char [ MAX ][ MAX ], int &);
    bool alive (const char [ MAX ][ MAX ], int &, int &);
    void neighbor (const char [ MAX ][ MAX ], int &, int &, int &);
    void copy (char [ MAX ][ MAX ], char [ MAX ][ MAX ]);
    void print (const char [ MAX ][ MAX ]);
    
    main()
    {
       char table[ MAX ][ MAX ];
       int total;
       
       fill (table);
       getBacteria (table, total);
       
       print (table);
       
       for (int generation = 4; generation < 5; generation++)
          oneGeneration (table, total);
       
       print (table);
       
       cout<< endl << "Total Bacteria = " << total;
       return 0;
    }
    
    /**** ARRAY MANIPULATION ****/
    void fill (char table[ MAX ][ MAX ])
    //fill the table with blank spaces
    {
       for (int row = 0; row < MAX; row++)
          for (int col = 0; col < MAX; col++)
             table[ row ][ col ] = ' ';
    }
    
    /**** ARRAY MANIPULATION ****/
    void getBacteria (char table[ MAX ][ MAX ], int &total)
    //get coordinates for bacteria from an external file
    {
       int num, x, y;
       ifstream infile("Life100.txt");
       
       //get total number of bacteria, the first integer
       infile >> num;
       total = num;
       //get coordinates and fill location with "*"
       while (!infile.eof())
       {
          infile >> x;
          infile >> y;
          table[ x ][ y ] = '*';
       }
    }
    
    /**** ARRAY MANIPULATION ****/
    void oneGeneration (char table[ MAX ][ MAX ], int &total)
    //calculate each generation and assign new locations
    {
       char temp[ MAX ][ MAX ];
       bool life;
       
       fill (temp);
       for (int row = 0; row < MAX; row++)
          for (int col = 0; col < MAX; col++)
          {   
             life = alive(table, row, col);
             if (life)
                temp[ row ][ col ] = '*';
          }
       copy (table, temp);
    }
    
    /**** BOOLEAN EVALUATION ****/
    bool alive (const char table[ MAX ][ MAX ], int &x, int &y)
    //calculate if the cell will live
    {
       int living = 0;
       //get number of neighbors
       neighbor (table, x, y, living);
       //determine if current cell will live
       if (table[ x ][ y ] == '*') 
       {   
          if ((living == 2) || (living == 3))
             return true;
          else
             return false;
       }
       else
       {   
          if (living == 3)
             return true;
          else 
             return false;
       }
    }
    
    /****** INTEGER COUNT ******/
    void neighbor (const char table[ MAX ][ MAX ], int &x, int &y, int &a)
    //count number of surrounding neighbors
    {
       if ((x - 1) >= 0))
          for (int row = y - 1; row <= y + 1; row++)
             if ((row >= 0) && (row < MAX))
    	if (table[ row ][ x - 1 ] == '*')
    	   a += 1;
    
       if ((x + 1) < MAX)
          for (int row = y - 1; row <= y + 1; row++)
             if ((row >= 0) && (row < MAX))
    	if (table[ MAX ][ x + 1 ] == '*')
    	   a += 1;
    
       if ((y - 1) >= 0)
          if (table[ y - 1 ][ x ] == '*')
             a += 1;
    
       if ((y + 1) < MAX)
          if (table[ y + 1 ][ x ] == '*')
             a += 1;
    }
    
    /******* COPY ARRAY ********/
    void copy (char table[ MAX ][ MAX ], char temp[ MAX ][ MAX ])
    //copy new "temp" table to old "table"
    {
       for (int row = 0; row < MAX; row++)
          for (int col = 0; col < MAX; col++)
             table[ row ][ col ] = temp[ row ][ col ];
    }
    
    /******* PRINT ARRAY *******/  
    void print (const char table[ MAX ][ MAX ])
    //print full table with reference numbers
    {
       int horizontal = 1;
       
       cout<< setw(10);
       //prints horizontal reference numbers, x-axis
       for (int ref = 1; ref < MAX; ref++)
       {   
          cout<< horizontal;
          horizontal++;
          if (horizontal == 10) horizontal = 0;
       }
          cout<< endl << endl;
       //prints verticle reference numbers, y-axis
       for (int row = 1; row < MAX; row++)
       {   
          cout<< setw(5) << row << setw(5);
          for (int col = 1; col < MAX; col++)
             cout<< table[ row ][ col ];
          cout<< endl;
       }
    }

  3. #18
    Registered User
    Join Date
    May 2003
    Posts
    82
    i'm piecing through this. One random style suggestion, is that you should really use 0-indexed lists. If you don't stick with the idiom, it gets confusing, as you always have to keep track of if code is using 1 or 0 based indexes.

  4. #19
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Why not have the getBacteria function return the amount of cells, instead of using the reference?

  5. #20
    *this
    Join Date
    Mar 2005
    Posts
    498
    because the assignment says to initialize a max array of 20 by 20, i used 21 so that i didnt have to use row and column 0.

  6. #21
    *this
    Join Date
    Mar 2005
    Posts
    498
    Quote Originally Posted by AH_Tze
    i'm piecing through this. One random style suggestion, is that you should really use 0-indexed lists. If you don't stick with the idiom, it gets confusing, as you always have to keep track of if code is using 1 or 0 based indexes.
    but the file contains coordinates, none are 0.

  7. #22
    *this
    Join Date
    Mar 2005
    Posts
    498
    does anyone have any suggestions??? i know there is something wrong with my code i just cant pinpoint it.

  8. #23
    Registered User
    Join Date
    May 2003
    Posts
    82
    Not seeing it immediately. The alive() and neighbor() functions look error-prone.
    If you want to find the error, I'd probably write a seperate driver program so you can test those two individually. You could write a test driver which has each function on a small array, with none of the other program logic obscuring things, and make it easy to watch as it steps through so you can spot the trouble spot.

  9. #24
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Easiest way to spot the error is to render one frame and wait for a key. Then render another and so on. This way you can tell exactly what is going in inside of your code. I would say it is your alive and neighbor functions as well.

    You must remember that just because you might 'get away' with overstepping your array bounds, does not mean it won't adversely affect your data, code, etc. You will frag the heap and/or stack depending on how you are allocating the array. This will result in perfectly good code executing incorrectly due to messed up memory.

    So if you are getting weird stuff then that is probably what is happening.

    To stop the overrun, just clamp on x and y.

    Code:
    int x1=x-1
    int y1=y-1
    int x2=x+1
    int y2=y+1
    
    if (x1<0) x1=maxX;
    if (y1<0) y1=maxY;
    if (x2>maxX) x2=0;
    if (y2>maxY) y2=0;
    
    char n0,n1,n2,n3,n4,n5,n6,n7;
    n0=n1=n2=n3=n4=n5=n6=n7=0;
    
    n0=array[y1][x1];
    n1=array[y1][x];
    n2=array[y1][x2];
    
    n3=array[y][x1];
    n4=array[y][x2];
    
    n5=array[y2][x1];
    n6=array[y2][x];
    n7=array[y2][x2];
    
    ...
    This picks up all 8 neighbors and will wrap the effect at the boundaries of the array.

    But you would want something like that to count the number of alive and dead instead of retrieving the value. What I showed is more useful for filtering images. But it should get you on the right track.

    Given any one location this is what that code will give:

    Code:
    n0,n1,n2
    n3,**,n4
    n5,n6,n7
    Where ** is the current location you are checking.

  10. #25
    *this
    Join Date
    Mar 2005
    Posts
    498
    Code:
    if (x1<0) x1=maxX;
    if (y1<0) y1=maxY;
    if (x2>maxX) x2=0;
    if (y2>maxY) y2=0;
    if x1 or y1 is less than 0 it should yield 0 not max.
    this is the code i used, it works inside but not on the edges so for that im having dificulties.

    Code:
    /**** BOOLEAN EVALUATION ****/
    bool life (const char table[ MAX ][ MAX ], int &x, int &y)
    //count number of surrounding neighbors
    {
       int x1=x-1; int y1=y-1;
       int x2=x+1; int y2=y+1;
       int a = 0;
    
       if (x1<0) x1=0;
       if (y1<0) y1=0;
       if (x2>MAX) x2=MAX;
       if (y2>MAX) y2=MAX;
    
       char n0,n1,n2,n3,n4,n5,n6,n7;
       n0=n1=n2=n3=n4=n5=n6=n7=0;
    
       n0=table[y1][x1]; n1=table[y1][x]; n2=table[y1][x2];
       n3=table[y][x1]; n4=table[y][x2]; n5=table[y2][x1];
       n6=table[y2][x]; n7=table[y2][x2];
    
       if (n0 == '*') a++; if (n1 == '*') a++; if (n2 == '*') a++;
       if (n3 == '*') a++; if (n4 == '*') a++; if (n5 == '*') a++;
       if (n6 == '*') a++; if (n7 == '*') a++;
    
       if (table[ x ][ y ] == ' ')
       {
          if (a == 3)
             return true;
          else 
             return false;
       }
       if (table[ x ][ y ] == '*')
       {
          if ((a == 3) || (a == 2))
             return true;
          else
             return false;
       }
    }

  11. #26
    *this
    Join Date
    Mar 2005
    Posts
    498
    does anyone have any other ideas for setting boundaries? i dont need the code, just an idea

  12. #27
    Registered User
    Join Date
    Dec 2002
    Posts
    56
    You can use modulus arithmetic and set it up to have no boundaries, that is, the sides would be connected. I have an example from my game of life implementation if you need to see it.

  13. #28
    *this
    Join Date
    Mar 2005
    Posts
    498
    i am curious, could you just give me an example of how the modulus operator could be used?

  14. #29
    Registered User samGwilliam's Avatar
    Join Date
    Feb 2002
    Location
    Newport
    Posts
    382
    Quote Originally Posted by JoshR
    i am curious, could you just give me an example of how the modulus operator could be used?
    Highly general example:

    Code:
    #define MAX 20
    
    int main (void)
    {
       int i = 0;
    
       while (1)
          i++ %= MAX;
    }
    ...will wrap i so that it is constantly within 20.

    But you don't want to do that in the game of life (unless you want to implement a conceptual torus) - you should just ignore out of bounds values.

  15. #30
    *this
    Join Date
    Mar 2005
    Posts
    498
    well i clamped down as hard as i could on the x and y values and made sure that they were only used if in parameters as follows below, but it still wont work, im lost...
    Code:
    /**** BOOLEAN EVALUATION ****/
    bool life (const char table[ MAX ][ MAX ], int &x, int &y)
    //count number of surrounding neighbors
    {
       int x1=x-1; int y1=y-1;
       int x2=x+1; int y2=y+1;
       int a = 0;
    
       char n0,n1,n2,n3,n4,n5,n6,n7;
       n0=n1=n2=n3=n4=n5=n6=n7=0;
    
       if ((y1 > 0) && (x1 > 0))
          n0=table[y1][x1]; 
       if (y1 > 0)
          n1=table[y1][x]; 
       if ((y1 > 0) && (x2 < MAX))
          n2=table[y1][x2];
       if (x1 > 0)
          n3=table[y][x1]; 
       if (x2 < MAX)
          n4=table[y][x2]; 
       if ((x1 > 0) && (y2 < MAX))
          n5=table[y2][x1];
       if (y2 < MAX)
          n6=table[y2][x]; 
       if ((y2 < MAX) && (x2 < MAX))
          n7=table[y2][x2];
    
       if (n0 == '*') a++; if (n1 == '*') a++; if (n2 == '*') a++;
       if (n3 == '*') a++; if (n4 == '*') a++; if (n5 == '*') a++;
       if (n6 == '*') a++; if (n7 == '*') a++;
    
       if (table[ x ][ y ] == ' ')
       {
          if (a == 3)
             return true;
          else 
             return false;
       }
       if (table[ x ][ y ] == '*')
       {
          if ((a == 3) || (a == 2))
             return true;
          else
             return false;
       }
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Open-source Game Project
    By Glorfindel in forum Projects and Job Recruitment
    Replies: 0
    Last Post: 03-24-2009, 01:12 AM
  2. 2D RPG Online Game Project. 30% Complete. To be released and marketed.
    By drallstars in forum Projects and Job Recruitment
    Replies: 2
    Last Post: 10-28-2006, 12:48 AM
  3. C Programming 2d Array Question
    By jeev2005 in forum C Programming
    Replies: 3
    Last Post: 04-26-2006, 03:18 PM
  4. Game Of Life
    By din1983 in forum C Programming
    Replies: 20
    Last Post: 10-11-2005, 10:36 PM
  5. Please help with some coding..
    By stehigs321 in forum C Programming
    Replies: 2
    Last Post: 10-27-2003, 06:44 PM