Thread: Problem with Game of Life program

  1. #1
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37

    Problem with Game of Life program

    Code:
    #include <iostream>
    #include <cstdlib>
    #include <Windows.h>
    
    char grid[25][25];
    
    void turnOn(int x, int y);
    void turnOff(int x, int y);
    bool lhmt3(int x, int y);
    bool lh2o3(int x, int y);
    bool lhlt2(int x, int y);
    bool dhe3(int x, int y);
    int gridCheck(int x, int y);
    void printGrid();
    void initGrid();
    void Game();
    
    int main(){
        initGrid();
        turnOn(10,15);
        turnOn(10,16);
        turnOn(9,15);
        turnOn(11,15);
        turnOn(10,14);
        printGrid();
        Game();
    }
    // Activate cell
    void turnOn(int x, int y){
        grid[x][y] = '0';
    }
    // Kill cell
    void turnOff(int x, int y){
        grid[x][y] = '-';
    }
    // Check whether living cell has more than three neighbours
    bool lhmt3(int x, int y){
        if(gridCheck(x, y) > 3){
            return true;
        } else {
            return false;
        }
    }
    // Check whether living cell has two or three neighbours
    bool lh2o3(int x, int y){
        if(gridCheck(x, y) == 2 or gridCheck(x, y) == 3){
            return true;
        } else {
            return false;
        }
    }
    // Check whether living cell has less than two neighbours
    bool lhlt2(int x, int y){
        if(gridCheck(x, y) < 2){
            return true;
        } else {
            return false;
        }
    }
    // Check whether dead cell has exactly three neighbours
    bool dhe3(int x, int y){
        if(gridCheck(x, y) == 3){
            return true;
        } else {
            return false;
        }
    }
    // Scan adjacent cells for life
    int gridCheck(int x, int y){
        int count = 0;
        if(grid[x-1][y]=='0') ++count;
        if(grid[x-1][y-1]=='0') ++count;
        if(grid[x][y-1]=='0') ++count;
        if(grid[x+1][y-1]=='0') ++count;
        if(grid[x+1][y]=='0') ++count;
        if(grid[x+1][y+1]=='0') ++count;
        if(grid[x][y+1]=='0') ++count;
        if(grid[x-1][y+1]=='0') ++count;
        return count;
    }
    
    void printGrid(){
        for(int x=0;x<25;++x){
            for(int y=0;y<25;++y){
                std::cout << grid[x][y] << " ";
            }
            std::cout << std::endl;
        }
    }
    
    void initGrid(){
        for(int x=0;x<25;++x){
            for(int y=0;y<25;++y){
                grid[x][y] = '-';
            }
        }
    }
    
    void Game(){
        while (true){
            for(int x=0;x<25;++x){
                for(int y=0;y<25;++y){
                    if((grid[x][y] == '0') and (lhmt3(x, y) == true)){
                        std::cout << lhmt3(x,y);
                        turnOff(x, y);
                    }
                    if((grid[x][y] == '0') and (lh2o3(x, y) == true)){
                    }
                    if((grid[x][y] == '0') and (lhlt2(x, y) == true)){
                        turnOff(x, y);
                    }
                    if((grid[x][y] == '-') and (dhe3(x, y) == true)){
                        std::cout << "i am dead";
                        turnOn(x, y);
                    }
                }
            }
            system("PAUSE");
            system("CLS");
            printGrid();
        }
    }
    This doesn't do what it's supposed to. In a functional Life program what should happen is the middle cell dies and the corner cells are activated. Perhaps there's something wrong with my conditionals but they look pretty good to me and I can't figure out what's wrong. If someone could read through it I'd appreciate it.

    P.S. The system("PAUSE") and cout statements in Game() are there only for debugging reasons.

    EDIT: Some sample output:

    Code:
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - 0 - - - - - - - - -
    - - - - - - - - - - - - - - 0 0 0 - - - - - - - -
    - - - - - - - - - - - - - - - 0 - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    i am dead11Press any key to continue . . .
    The 1s are the result of the lhmt3() function in Game(), and the "i am dead" is the result of the dhe3() function. Obviously these numbers are incorrect. There should only be one "true" and it should output "i am dead" four times.

    Code:
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - 0 - - - - - - - - - -
    - - - - - - - - - - - - - - 0 - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    Press any key to continue . . .
    And it doesn't work.
    Last edited by ex-mortis; 08-11-2012 at 11:47 AM.

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I do not what game of life is.And i am sorry that i can not understand what you mean the problem is.I mean i can not see what you want to achieve,so you can explain me a little bit(if you wish and if you see that you get no answers,because other members may understand)

  3. #3
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Sorry. The Game of Life is a non-interactive "game" that is "played" on a grid with any number of cells (in my program it's 25x25). Each cell can either be "dead" or "alive" and the game has four rules to determine what cells live and die. I'm just going to copy paste from Wikipedia because it explains it very well:


    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.


    So I have specific functions to test these conditions and then I either activate or deactivate the cells depending on the result of the conditionals. Check my comments, they should tell you what I'm trying to do with the functions. My program doesn't work however because I am not getting to expected result, which is a square in the 2nd cycle.

  4. #4
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    You need to use another grid (2 dimensional array) to calculate the next generation of cells. With only one grid, the next generation is calculated from a mixture of the current generation and the next generation.

  5. #5
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I think that the problem is not in your code that in something you got wrong by the rules of the game or by examining the output.

    Mind that the cell with coordinates 9,14 is going to regenerate(because it has 3 neighbours ).So i would say that the output is correct.The cells that alive after the first round are the 9,14 and the 10,14.That is correct i would say,isn't it?

  6. #6
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Quote Originally Posted by christop View Post
    You need to use another grid (2 dimensional array) to calculate the next generation of cells. With only one grid, the next generation is calculated from a mixture of the current generation and the next generation.
    The answer i gave ex-Mortis considers that you were aware of what christop said and calculates the output with the mixture he said

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > if(grid[x-1][y]=='0') ++count;
    Beware of array overruns (and underruns).
    You start with x and y at 0.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by std10093 View Post
    I think that the problem is not in your code that in something you got wrong by the rules of the game or by examining the output.

    Mind that the cell with coordinates 9,14 is going to regenerate(because it has 3 neighbours ).So i would say that the output is correct.The cells that alive after the first round are the 9,14 and the 10,14.That is correct i would say,isn't it?
    Nope. See for yourself.

    Quote Originally Posted by christop View Post
    You need to use another grid (2 dimensional array) to calculate the next generation of cells. With only one grid, the next generation is calculated from a mixture of the current generation and the next generation.
    Can you elaborate? I don't really understand.

    Quote Originally Posted by Salem View Post
    > if(grid[x-1][y]=='0') ++count;
    Beware of array overruns (and underruns).
    You start with x and y at 0.
    Hadn't considered it. At the moment I'm only testing the middle of the board so it isn't a problem, but I'll fix it.

  9. #9
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    What I mean is that as you generate the next generation in each cycle, you're partially overwriting the current generation, which affects the results of the next generation.

    For example, if a cell dies, it is no longer counted as a living neighbor for several other cells surrounding it when it should still be counted, and if a new cell is born it is then counted as a living neighbor when it shouldn't be.

    By using two arrays, you read cells from the "current" generation array and write cells to the "next" generation array.
    Last edited by christop; 08-11-2012 at 03:51 PM.

  10. #10
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by ex-mortis View Post
    Can you elaborate? I don't really understand.
    If you make the changes in the same grid then the changed positions will be used in some of the decisions.
    Instead, leave the original grid alone and use another grid to create the new state.
    Then either copy it back to the original grid or use a buffer-switching technique.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  11. #11
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by oogabooga View Post
    If you make the changes in the same grid then the changed positions will be used in some of the decisions.
    Instead, leave the original grid alone and use another grid to create the new state.
    Then either copy it back to the original grid or use a buffer-switching technique.
    Quote Originally Posted by christop View Post
    What I mean is that as you generate the next generation in each cycle, you're partially overwriting the current generation, which affects the results of the next generation.

    For example, if a cell dies, it is no longer counted as a living neighbor for several other cells surrounding it when it should still be counted, and if a new cell is born it is then counted as a living neighbor when it shouldn't be.

    By using two arrays, you read cells from the "current" generation array and write cells to the "next" generation array.
    Makes sense now that I think about it. Thanks for the tips, I'll get to work.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Quote Originally Posted by Salem View Post
    > if(grid[x-1][y]=='0') ++count;
    > Beware of array overruns (and underruns).
    > You start with x and y at 0.
    > Hadn't considered it. At the moment I'm only testing the middle of the board so it isn't a problem, but I'll fix it.

    > for(int x=0;x<25;++x)
    > for(int y=0;y<25;++y)
    You might only have something interesting in the middle of the board, but you are still checking ALL of it.

    Your program is screwed on the very first iteration of your loop.

    Oh, and people who ignore buffer overruns "until later" make me
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by Salem View Post
    Quote Originally Posted by Salem View Post
    > if(grid[x-1][y]=='0') ++count;
    > Beware of array overruns (and underruns).
    > You start with x and y at 0.
    > Hadn't considered it. At the moment I'm only testing the middle of the board so it isn't a problem, but I'll fix it.

    > for(int x=0;x<25;++x)
    > for(int y=0;y<25;++y)
    You might only have something interesting in the middle of the board, but you are still checking ALL of it.

    Your program is screwed on the very first iteration of your loop.

    Oh, and people who ignore buffer overruns "until later" make me
    Sorry, that's not what I was trying to say. I simply commented erroneously that it wasn't a problem but that I was going to fix it. Is this adequate enough?

    Code:
    // Scan adjacent cells for life
    int gridCheck(int x, int y){
        int count = 0;
    
        //To avoid array underrun
        if(x>=1){
            if(grid[x-1][y]=='0') ++count;
        }
        if (x>=1 and y<24)
            if(grid[x-1][y+1]=='0') ++count;
        }
        if (y>=1){
            if(grid[x][y-1]=='0') ++count;
        }
        if (x<24 and y>=1){
            if(grid[x+1][y-1]=='0') ++count;
        }
        if (x>=1 and y>=1){
            if(grid[x-1][y-1]=='0') ++count;
        }
        if (x<24){
            if(grid[x+1][y]=='0') ++count;
        }
        if (x<24 and y<24){
            if(grid[x+1][y+1]=='0') ++count;
        }
        if (y<24){
            if(grid[x][y+1]=='0') ++count;
        }
    
        return count;
    }
    Here's my updated source code:

    Code:
    #include <iostream>
    #include <cstdlib>
    #include <Windows.h>
    
    char grid[25][25];
    char nextGrid[25][25];
    
    void turnOn(int x, int y);
    void turnOff(int x, int y);
    bool lhmt3(int x, int y);
    bool lh2o3(int x, int y);
    bool lhlt2(int x, int y);
    bool dhe3(int x, int y);
    int gridCheck(int x, int y);
    void printGrid();
    void initGrid();
    void initNextGrid();
    void arrayCopy();
    void Game();
    
    int main(){
        initGrid();
        initNextGrid();
        turnOn(10,15);
        turnOn(10,16);
        turnOn(9,15);
        turnOn(11,15);
        turnOn(10,14);
        Game();
    }
    // Activate cell
    void turnOn(int x, int y){
        grid[x][y] = '0';
    }
    // Activate next gen cell
    void turnOnNext(int x, int y){
        nextGrid[x][y] = '0';
    }
    // Kill cell
    void turnOff(int x, int y){
        grid[x][y] = '-';
    }
    // Kill next gen cell
    void turnOffNext(int x, int y){
        nextGrid[x][y] = '-';
    }
    // Check whether living cell has more than three neighbours
    bool lhmt3(int x, int y){
        if(gridCheck(x, y) > 3){
            return true;
        } else {
            return false;
        }
    }
    // Check whether living cell has two or three neighbours
    bool lh2o3(int x, int y){
        if(gridCheck(x, y) == 2 or gridCheck(x, y) == 3){
            return true;
        } else {
            return false;
        }
    }
    // Check whether living cell has less than two neighbours
    bool lhlt2(int x, int y){
        if(gridCheck(x, y) < 2){
            return true;
        } else {
            return false;
        }
    }
    // Check whether dead cell has exactly three neighbours
    bool dhe3(int x, int y){
        if(gridCheck(x, y) == 3){
            return true;
        } else {
            return false;
        }
    }
    // Scan adjacent cells for life
    int gridCheck(int x, int y){
        int count = 0;
    
        //To avoid array underrun
        if(x>=1){
            if(grid[x-1][y]=='0') ++count;
            if(grid[x-1][y+1]=='0') ++count;
        }
        if (y>=1){
            if(grid[x][y-1]=='0') ++count;
            if(grid[x+1][y-1]=='0') ++count;
        }
        if (x>=1 and y>=1){
            if(grid[x-1][y-1]=='0') ++count;
        }
        if(grid[x+1][y]=='0') ++count;
        if(grid[x+1][y+1]=='0') ++count;
        if(grid[x][y+1]=='0') ++count;
    
        return count;
    }
    
    void printGrid(){
        for(int x=0;x<25;++x){
            for(int y=0;y<25;++y){
                std::cout << grid[x][y] << " ";
            }
            std::cout << std::endl;
        }
    }
    
    void initGrid(){
        for(int x=0;x<25;++x){
            for(int y=0;y<25;++y){
                grid[x][y] = '-';
            }
        }
    }
    void initNextGrid(){
        for(int x=0;x<25;++x){
            for(int y=0;y<25;++y){
                nextGrid[x][y] = '-';
            }
        }
    }
    
    void arrayCopy(){
        for(int x=0;x<25;++x){
            for(int y=0;y<25;++y){
                grid[x][y] = nextGrid[x][y];
            }
        }
    }
    
    void Game(){
        printGrid();
        while (true){
            for(int x=0;x<25;++x){
                for(int y=0;y<25;++y){
                    if((grid[x][y] == '0') and (lhmt3(x, y) == true)){
                        std::cout << lhmt3(x,y);
                        turnOffNext(x, y);
                    }
                    if((grid[x][y] == '0') and (lh2o3(x, y) == true)){
                    }
                    if((grid[x][y] == '0') and (lhlt2(x, y) == true)){
                        turnOffNext(x, y);
                    }
                    if((grid[x][y] == '-') and (dhe3(x, y) == true)){
                        std::cout << "i am dead";
                        turnOnNext(x, y);
                    }
                }
            }
            arrayCopy();
            system("PAUSE");
            system("CLS");
            printGrid();
        }
    }
    Right now it "works" in the sense that in the first generation all of the conditionals return the correct values and the 2nd generation of cells is printed correctly. But for some reason the if statements do not run at all (or all return false) and there is no 3rd generation. From what I can tell it should copy the 2nd generation values to the first generation and run another check on all of the cells. I think maybe the sequence is somehow screwed up but I cannot spot the error.
    Last edited by ex-mortis; 08-12-2012 at 04:05 AM.

  14. #14
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    You're still not checking for array overrun.
    You should call initNextGrid() after arrayCopy().
    Kurt

  15. #15
    Registered User ex-mortis's Avatar
    Join Date
    Mar 2012
    Posts
    37
    Quote Originally Posted by ZuK View Post
    You're still not checking for array overrun.
    You should call initNextGrid() after arrayCopy().
    Kurt
    1. I'm not? What is the proper way to check for an overrun then?

    2. I already tried it, it doesn't work. The error is definitely in the conditionals because they return false or don't run at all instead of returning true like they should.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Game of life program
    By paranoidgnu in forum C Programming
    Replies: 31
    Last Post: 05-05-2011, 05:10 AM
  2. A problem with the game of life
    By uber in forum C Programming
    Replies: 4
    Last Post: 03-25-2007, 04:06 PM
  3. C++ Game of Life Program
    By rayrayj52 in forum C++ Programming
    Replies: 16
    Last Post: 09-26-2004, 03:58 PM
  4. The Game of Life problem
    By kippwinger in forum C++ Programming
    Replies: 5
    Last Post: 03-05-2004, 07:59 AM
  5. Game of Life Program Help
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 01-23-2002, 10:32 AM