Grid does not work for values greater than 30x30

72 Views Asked by At

I am trying to make Conway's Game of Life using C and raylib. In this program, I am facing issues to generate a grid greater than 30 such as 40x40 or 100x100. The program works fine for 30x30, but as soon as I change the value the program breaks. Only half the grid is generated and half the screen is blank.

#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "raylib.h"
#include "raymath.h"

int main()
{   
    int up, down, left, right;
    int life;
    int k, i, j;
    int COLS = 30;
    int ROWS = 30;
    int spaceC = 0;
    int mouseC = 0;
    int screenWidth = 600;
    int screenHeight = 600;
    int cellWidth = screenWidth / ROWS;
    int cellHeight = screenHeight / COLS;
    int mat[ROWS][COLS];
    int buffer[ROWS][COLS];

    SetTargetFPS(60);
    InitWindow(screenWidth, screenHeight, "try render");
//default
    for (i = 0; i < ROWS; i++)
    {
        for (j = 0; j < COLS; j++)
        {
            mat[i][j] = 0;
        }
    }

    while (!WindowShouldClose())
    {
        for (i = 0; i < ROWS; i++)
        {
            for (j = 0; j < COLS; j++)
            {
                if (mat[i][j] == 0)
                {
                    DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, WHITE);
                }
                else
                {
                    DrawRectangle(i * cellWidth, j * cellHeight, cellWidth, cellHeight, BLACK);
                }
                DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, GRAY);
            }
        }

        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
        {
            Vector2 mPos = GetMousePosition();
            int x = mPos.x / cellWidth;
            int y = mPos.y / cellHeight;
            if (x >= 0 && x < ROWS && y >= 0 && y < COLS)
            {
                if (mat[x][y] != 1)
                {
                    mouseC = 1;
                    mat[x][y] = 1;
                }
                else if (mouseC == 1 && mat[x][y] == 1) {
                    mouseC=0;
                    mat[x][y] = 0;
                }           
            }
        }

        if (IsKeyPressed(KEY_SPACE))
        {
            spaceC++;
        }
        if (spaceC % 2 != 0)
        {
            SetTargetFPS(4);
            for (k = 0; k < 1; k++)
            {
                for (i = 0; i < ROWS; i++)
                {
                    for (j = 0; j < COLS; j++)
                    {
                        right = (j + 1) % COLS;
                        left = ((j - 1) + COLS) % COLS;
                        up = ((i - 1) + ROWS) % ROWS;
                        down = (i + 1) % ROWS;

                        life = mat[down][j] + mat[i][left] + mat[up][left] + mat[up][j] + mat[up][right] + mat[i][right] + mat[down][right] + mat[down][left];

                        if (mat[i][j] == 1 && (life < 2 || life > 3))
                        {
                            buffer[i][j] = 0;
                        }
                        else if (mat[i][j] == 1 && (life == 2 || life == 3))
                        {
                            buffer[i][j] = 1;
                        }
                        else if (mat[i][j] == 0 && life == 3)
                        {
                            buffer[i][j] = 1;
                        }
                        else
                        {
                            buffer[i][j] = mat[i][j];
                        }
                    }
                }

                for (i = 0; i < ROWS; i++)
                {
                    for (j = 0; j < COLS; j++)
                    {
                        mat[i][j] = buffer[i][j];
                    }
                }
            }
        }

        BeginDrawing();
        ClearBackground(RAYWHITE);
        EndDrawing();
    }

    CloseWindow();
    return 0;
}
1

There are 1 best solutions below

3
On

The reason the display is broken is you do not redisplay between the calls BeginDrawing(); ClearBackground(RAYWHITE); and EndDrawing();.

Note also these remarks:

  • there is still a confusion between rows and columns: you set mat[x][y] in the cell update code instead of mat[y][x], and you use the wrong variables in the display code: it should be j * cellWidth, i * cellHeight instead of i * cellWidth, j * cellHeight

  • using row and col as index variables would make the code more readable and less error prone.

  • there is no need for DrawRectangleLines(i * cellWidth, j * cellHeight, cellWidth, cellHeight, WHITE); in the display code if the matrix cell is not set because the background has been cleared.

  • you can use the xor operator to simplify the mouse toggle code:

      mat[row][col] ^= 1;
    
  • the game logic can also be simplified:

      if (mat[i][j] == 1) {
          buffer[i][j] = (life == 2 || life == 3);
      } else {
          buffer[i][j] = (life == 3);
      }
    

Here is a modified version:

#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "raylib.h"
#include "raymath.h"

int main(void)
{
    int COLS = 40;
    int ROWS = 40;
    int spaceC = 0;
    int mouseC = 0;
    int screenWidth = 600;
    int screenHeight = 600;
    int cellWidth = screenWidth / COLS;
    int cellHeight = screenHeight / ROWS;
    int fps = 60;
    int mat[ROWS][COLS];
    int buffer[ROWS][COLS];

    SetTargetFPS(fps);
    InitWindow(screenWidth, screenHeight, "try render");

    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            mat[i][j] = 0;
        }
    }

    while (!WindowShouldClose()) {
        if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
            Vector2 mPos = GetMousePosition();
            int col = (int)mPos.x / cellWidth;
            int row = (int)mPos.y / cellHeight;
            if (row >= 0 && row < ROWS && col >= 0 && col < COLS) {
                mat[row][col] ^= 1;
            }
        }

        if (IsKeyPressed(KEY_SPACE)) {
            spaceC++;
        }
        if (spaceC % 2 != 0) {
            if (fps != 8) {
                SetTargetFPS(fps = 8);
            }
            for (int k = 0; k < 1; k++) {
                for (int i = 0; i < ROWS; i++) {
                    for (int j = 0; j < COLS; j++) {
                        int up = (i - 1 + ROWS) % ROWS;
                        int down = (i + 1) % ROWS;
                        int right = (j + 1) % COLS;
                        int left = (j - 1 + COLS) % COLS;
                        int life = mat[up][left] + mat[up][j] + mat[up][right] +
                            mat[i][left] + mat[i][right] +
                            mat[down][j] + mat[down][left] + mat[down][right];

                        if (mat[i][j] == 1) {
                            buffer[i][j] = (life == 2 || life == 3);
                        } else {
                            buffer[i][j] = (life == 3);
                        }
                    }
                }
                for (int i = 0; i < ROWS; i++) {
                    for (int j = 0; j < COLS; j++) {
                        mat[i][j] = buffer[i][j];
                    }
                }
            }
        }

        BeginDrawing();
        ClearBackground(RAYWHITE);
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                if (mat[row][col] != 0) {
                    DrawRectangle(col * cellWidth, row * cellHeight, cellWidth, cellHeight, BLACK);
                }
                DrawRectangleLines(col * cellWidth, row * cellHeight, cellWidth, cellHeight, GRAY);
            }
        }
        EndDrawing();
    }
    CloseWindow();
    return 0;
}