I have to build the "Game of Life" by J.H. Conway. The game follows strict rules I wanted to implement in my code. Now I am getting an Errorcode anytime I want to debug. For those who doesn't know the game. Please look it up. It would take some time to explain :)
I was trying to implement the rules for "Game of Life". I started working with dynamic 2D-Arrays. I think I messed something up with my memory allocation, but I can't help myself.
// Game of Life
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#pragma warning (disable: 4996)
int dau_eingabe(int min, int max);
char** zufallsstart(char zeilen, char spalten, float prozent);
void execution(char zeilen, char spalten, char** body);
void print_body(char zeilen, char spalten, char ** body);
void free_speicherplatz(char zeilen, char ** body);
int main(){
int choice = 0;
char zeilen = 0;
char spalten = 0;
float prozent;
char ** body;
srand( time( NULL ) );
printf("\n");
printf("\t\t*** Game of Life ***\n\n");
printf("Zufallsgenerator: 1\n");
printf("Datei: 2\n");
printf("\n");
printf("Startzustand auswählen:\n");
choice = dau_eingabe(1,2);
printf("\n");
// 1. Menü für Startzustand über eine Datei
if(choice == 2){
printf("Datei");
}
// 2. Menü für Startzustand: Zufall und Datei
switch(choice){
case 1:
// Start durch Zufallsgenerator
printf("\nGeben Sie die Anzahl an Zeilen an (1 - 255):");
zeilen = dau_eingabe(1,255);
printf("\nGeben Sie die Anzahl an Spalten an (1 - 255:");
spalten = dau_eingabe(1,255);
printf("\nGeben Sie an, mit wie viel Prozent das Spielfeld mit lebenden Zellen zu füllen ist (0 - 100):");
prozent = dau_eingabe(0,100);
zufallsstart(zeilen,spalten,prozent);
break;
}
printf("\nWählen Sie aus die Form der Abarbeitung aus:");
printf("\n\n1. schrittweise Abarbeitung\n2. animierte Abarbeitung");
printf("\nEingabe >> ");
choice = dau_eingabe(1,2);
switch(choice){
case 1:
printf("\n\t\t***Schrittweise Abarbeitung***");
case 2:
printf("\n\t\t***Animierte Abarbeitung***\n");
execution(zeilen,spalten,body);
}
free_speicherplatz(zeilen,body);
return 0;
}
int dau_eingabe(int min, int max){
int choice;
if(scanf(" %d",&choice) == 0){
printf("Die Eingabe ist falsch. Beachten Sie den Eingabebereich!\n");
choice = dau_eingabe(min,max);
}
if(choice < min || choice > max){
printf("Die Eingabe ist falsch. Beachten Sie den Eingabebereich!\n");
choice = dau_eingabe(min,max);
}
if(choice >= min && choice <= max){
return choice;
}
}
// Funktion gibt body (Matrix der Zellen) zurück an main-Funktion und realisiert den Zufallsstart
// d.h. die Funktion erstellt den Startzustand des Spiels
char** zufallsstart(char zeilen, char spalten, float prozent){
char ** body;
int maxcells_alive = (zeilen * spalten) * (prozent / 100);
int maxcells_dead = ((zeilen) * (spalten)) - maxcells_alive;
int cells_alive = 0;
int cells_dead = 0;
char currentstate = ' ';
// Speicherplatz reservieren für die char-Zeiger
body = malloc(zeilen * sizeof(char *));
if(body == NULL){
printf("\nFehler bei der Speichervergabe!\n");
}
// Speicherplatz reservieren für die einzelnen Spalten der jeweiligen Zeile i
for(int i = 0; i < zeilen;i++){
body[i] = malloc(spalten * sizeof(char *));
if(body[i] == NULL){
printf("\nFehler bei der Speichervergabe in Zeile %d!\n",i);
}
}
// Zufallsstart
for(int i = 0; i < zeilen; i++){
for(int j = 0; j < spalten; j++){
body[i][j]= ' ';
}
}
for(int i = 0; i < zeilen; i++){
for(int j = 0; j < spalten; j++){
if( maxcells_alive > cells_alive ){
if( rand() % 2 == 1){
currentstate = '*';
body[i][j] = currentstate;
cells_alive++;
} else if( maxcells_dead > cells_dead) {
currentstate = ' ';
body[i][j] = currentstate;
cells_dead++;
} else{
currentstate = '*';
body[i][j] = currentstate;
cells_alive++;
}
}
}if(body== NULL){printf("Zellen sind null");}
}
printf("\n\nStartzustand:\n");
print_body(zeilen,spalten,body);
return body;
}
// zeigt die Matrix der Zellen
void print_body(char zeilen, char spalten, char ** body){
for(int i = 0; i < zeilen; i++){
for(int j = 0; j < spalten; j++){
printf(" %c",body[i][j]);
}
printf("\n");
}
}
// gibt den Speicherplatz wieder frei, nachdem das Programm durchgelaufen ist
void free_speicherplatz(char zeilen, char ** body){
for(int i = 0; i < zeilen; i++){
free(body[i]);
}
free(body);
}
void execution(char zeilen, char spalten, char** body){
int repetition = 0;
int dead_neighbor_cell = 0;
int alive_neighbor_cell = 0;
char single_cell = ' ';
// Speicherplatz reservieren für die char-Zeiger
body = malloc(zeilen * sizeof(char *));
if(body == NULL){
printf("\nFehler bei der Speichervergabe!\n");
}
// Speicherplatz reservieren für die einzelnen Spalten der jeweiligen Zeile i
for(int i = 0; i < zeilen;i++){
body[i] = malloc(spalten * sizeof(char *));
if(body[i] == NULL){
printf("\nFehler bei der Speichervergabe in Zeile %d!\n",i);
}
}
while(repetition <= 10){
for(int i = 0; i < zeilen; i++){
for(int j = 0; j < spalten; j++){
// Spieldynamik
dead_neighbor_cell = 0;
alive_neighbor_cell = 0;
single_cell = body[i][j];
if( single_cell == '*'){
if( i == 0 && j == 0){
if( single_cell == body[i][j+1]){alive_neighbor_cell++;}
if( single_cell == body[i+1][j]){alive_neighbor_cell++;}
if( single_cell == body[i+1][j+1]){alive_neighbor_cell++;}
}
if( i == 0 && j == (spalten)-1){
if( single_cell == body[i][j-1]){alive_neighbor_cell++;}
if( single_cell == body[i+1][j]){alive_neighbor_cell++;}
if( single_cell == body[i+1][j-1]){alive_neighbor_cell++;}
}
if( i == (zeilen)-1 && j == 0){
if( single_cell == body[i-1][j]){alive_neighbor_cell++;}
if( single_cell == body[i][j+1]){alive_neighbor_cell++;}
if( single_cell == body[i-1][j+1]){alive_neighbor_cell++;}
}
if( i == (zeilen)-1 && j == (spalten)-1){
if( single_cell == body[i-1][j]){alive_neighbor_cell++;}
if( single_cell == body[i][j-1]){alive_neighbor_cell++;}
if( single_cell == body[i-1][j-1]){alive_neighbor_cell++;}
}
if( 0 < i < zeilen && 0 < j < spalten){
if(single_cell == body[i-1][j-1]){alive_neighbor_cell++;}
if(single_cell == body[i-1][j]){alive_neighbor_cell++;}
if(single_cell == body[i-1][j+1]){alive_neighbor_cell++;}
if(single_cell == body[i][j-1]){alive_neighbor_cell++;}
if(single_cell == body[i][j+1]){alive_neighbor_cell++;}
if(single_cell == body[i+1][j-1]){alive_neighbor_cell++;}
if(single_cell == body[i+1][j]){alive_neighbor_cell++;}
if(single_cell == body[i+1][j+1]){alive_neighbor_cell++;}
}
}
if( single_cell == ' '){
if( i == 0 && j == 0){
if( single_cell != body[i][j+1]){dead_neighbor_cell++;}
if( single_cell != body[i+1][j]){dead_neighbor_cell++;}
if( single_cell != body[i+1][j+1]){dead_neighbor_cell++;}
}
if( i == 0 && j == (spalten)-1){
if( single_cell != body[i][j-1]){dead_neighbor_cell++;}
if( single_cell != body[i+1][j]){dead_neighbor_cell++;}
if( single_cell != body[i+1][j-1]){dead_neighbor_cell++;}
}
if( i == (zeilen)-1 && j == 0){
if( single_cell != body[i-1][j]){dead_neighbor_cell++;}
if( single_cell != body[i][j+1]){dead_neighbor_cell++;}
if( single_cell != body[i-1][j+1]){dead_neighbor_cell++;}
}
if( i == (zeilen)-1 && j == (spalten)-1){
if( single_cell != body[i-1][j]){dead_neighbor_cell++;}
if( single_cell != body[i][j-1]){dead_neighbor_cell++;}
if( single_cell != body[i-1][j-1]){dead_neighbor_cell++;}
}
if( 0 < i < zeilen && 0 < j < spalten){
if(single_cell != body[i-1][j-1]){dead_neighbor_cell++;}
if(single_cell != body[i-1][j]){dead_neighbor_cell++;}
if(single_cell != body[i-1][j+1]){dead_neighbor_cell++;}
if(single_cell != body[i][j-1]){dead_neighbor_cell++;}
if(single_cell != body[i][j+1]){dead_neighbor_cell++;}
if(single_cell != body[i+1][j-1]){dead_neighbor_cell++;}
if(single_cell != body[i+1][j]){dead_neighbor_cell++;}
if(single_cell != body[i+1][j+1]){dead_neighbor_cell++;}
}
}
if(body[i][j] == '*'){
if(alive_neighbor_cell != 2 || alive_neighbor_cell != 3){body[i][j] = ' ';}
else if (alive_neighbor_cell == 2 || alive_neighbor_cell == 3){body[i][j] = '*';}
}else if (body[i][j] == ' ' && dead_neighbor_cell == 3){body[i][j] = '*';}
else{body[i][j]= ' ';}
}
}repetition++;
}
}
This line here
if( 0 < i < zeilen && 0 < j < spalten){
does not do what you think it does. You probably meant to write
if (0 < i && i < zeilen - 1 && 0 < j && j < spalten - 1) {
Let's see why this is, step by step:
C evaluates the highest precedent operators first. In this case, <
evaluates before &&
.
if ((0 < i < zeilen) && (0 < j < spalten)) {
But if there are multiple operators at the same level of precedence, they evaluate left-to-right.
if (((0 < i) < zeilen) && ((0 < j) < spalten)) {
If i
or j
are not 0
, the expression does not work.
Let's go step by step (say i
is 3
and j is 10
for example):
if (((0 < 3) < zeilen) && ((0 < 10) < spalten)) {
then
if (((1) < zeilen) && ((1) < spalten)) {
then
if ((1) && (1)) {
In mathematics, it's common practice to write expressions like a < x < b
, but the C language cannot evaluate the expression in this way.