C语言实现康威生命游戏:第二代状态异常问题求助
康威生命游戏C语言代码异常:随机状态衍生第二代不符合规则
我自主编写的康威生命游戏C语言代码出现异常:选择“生成随机状态”,输入“存活细胞百分比”后,选择“分步动画”或“流畅动画”,发现第二代状态完全不符合第一代的衍生规则。尝试修改矩阵逻辑未解决问题,原代码如下:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <windows.h> #include <string.h> #pragma warning (disable: 4996) #define MAX_ROWS 30 #define MAX_COLS 20 typedef struct { char data[MAX_ROWS][MAX_COLS]; int rows; int cols; } Matrix; char neighbor_count(Matrix *m, int row, int col) { int count = 0; for (int i = row - 1; i <= row + 1; i++) { if (i < 0 || i >= m->rows) { continue; } for (int j = col - 1; j <= col + 1; j++) { if (j < 0 || j >= m->cols) { continue; } if (m->data[i][j] == '*' && (i != row || j != col)) { count++; } } } return count; } void check_cell(Matrix *m, int row, int col) { char neighbors_count = neighbor_count(m, row, col); char current_cell = m->data[row][col]; if (neighbors_count < 2) { //Die Zelle stirbt an Vereinsamung m->data[row][col] = ' '; } else if (neighbors_count > 3 && current_cell == '*') { //Die Zelle stirbt an Übervölkerung m->data[row][col] = ' '; } else if (neighbors_count == 3 && current_cell == ' ') { //Aus der toten Zelle wird eine neue lebende Zelle m->data[row][col] = '*'; } else if (neighbors_count == 2 || neighbors_count == 3) { //Die Zelle lebt weiter m->data[row][col] = '*'; } } void load_from_file(Matrix *m, const char *filename) { FILE *f = fopen(filename, "r"); if (f == NULL) { printf("File not found\n"); exit(-1); } int row_idx = 0; char ch; while ((ch = fgetc(f)) != EOF && row_idx < MAX_ROWS) { if (ch == '\n') { row_idx++; continue; } m->data[row_idx][m->cols] = ch; m->cols++; } m->rows = row_idx; fclose(f); } void randomize(Matrix *m, int percent) { memset(m->data, (int)' ', MAX_COLS * MAX_ROWS); m->rows = MAX_ROWS; m->cols = MAX_COLS; int cells = (m->rows * m->cols) * (percent / 100.0f); srand(time(NULL)); while (cells > 0) { int row = rand() % m->rows; int col = rand() % m->cols; if (m->data[row][col] == ' ') { m->data[row][col] = '*'; cells--; } } } void print_matrix(Matrix *m) { for (int i = 0; i < m->rows; i++) { for (int j = 0; j < m->cols; j++) { printf("%c", m->data[i][j]); } printf("\n"); } printf("\n"); } void step(Matrix *m) { Matrix m_tmp = *m; for (int i = 0; i < m->rows; i++) { for (int j = 0; j < m->cols; j++) { check_cell(&m_tmp, i, j); } } *m = m_tmp; } int main() { Matrix m; // Menü zur Auswahl des Startzustands printf("1. Aus Datei laden\n"); printf("2. Zufallszustand generieren\n"); int selection; scanf("%d", &selection); switch (selection) { case 1: // Aus Datei laden { char filename[20]; printf("Bitte Dateinamen angeben: "); scanf("%s", filename); load_from_file(&m, filename); break; } case 2: // Zufallszustand generieren { int percent; printf("Prozentualer Anteil an lebenden Zellen: "); scanf("%d%%", &percent); randomize(&m, percent); break; } default: printf("Ungültige Eingabe\n"); return 0; } // Menü zur Auswahl der Animation printf("1. Schrittweise Animation\n"); printf("2. Fließende Animation\n"); scanf("%d", &selection); switch (selection) { case 1: // Schrittweise Animation while (1) { print_matrix(&m); step(&m); getchar(); } break; case 2: // Fließende Animation while (1) { print_matrix(&m); step(&m); Sleep(2000); } break; default: printf("Ungültige Eingabe\n"); break; } return 0; }
问题根源
- 状态更新逻辑错误:
step函数中直接修改临时矩阵m_tmp的状态,后续细胞计算时会读取已经被修改的临时矩阵数据,违背了“所有细胞基于上一代完整状态同时更新”的核心规则。 - 存活规则逻辑错误:
check_cell的最后一个分支会强制将任何邻居数为2或3的细胞设为存活,哪怕该细胞原本是死亡状态(死亡细胞仅在邻居数为3时才复活)。 - 初始化细节问题:
randomize中memset的字节数计算写法不严谨,load_from_file未重置列计数,可能导致矩阵结构异常。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <windows.h> #include <string.h> #pragma warning (disable: 4996) #define MAX_ROWS 30 #define MAX_COLS 20 typedef struct { char data[MAX_ROWS][MAX_COLS]; int rows; int cols; } Matrix; char neighbor_count(Matrix *m, int row, int col) { int count = 0; for (int i = row - 1; i <= row + 1; i++) { if (i < 0 || i >= m->rows) { continue; } for (int j = col - 1; j <= col + 1; j++) { if (j < 0 || j >= m->cols) { continue; } if (m->data[i][j] == '*' && (i != row || j != col)) { count++; } } } return count; } void load_from_file(Matrix *m, const char *filename) { FILE *f = fopen(filename, "r"); if (f == NULL) { printf("文件未找到\n"); exit(-1); } int row_idx = 0; char ch; m->cols = 0; while ((ch = fgetc(f)) != EOF && row_idx < MAX_ROWS) { if (ch == '\n') { row_idx++; m->cols = 0; continue; } m->data[row_idx][m->cols] = ch; m->cols++; } m->rows = row_idx; fclose(f); } void randomize(Matrix *m, int percent) { memset(m->data, ' ', sizeof(m->data)); m->rows = MAX_ROWS; m->cols = MAX_COLS; int cells = (int)((m->rows * m->cols) * (percent / 100.0f)); srand(time(NULL)); while (cells > 0) { int row = rand() % m->rows; int col = rand() % m->cols; if (m->data[row][col] == ' ') { m->data[row][col] = '*'; cells--; } } } void print_matrix(Matrix *m) { system("cls"); for (int i = 0; i < m->rows; i++) { for (int j = 0; j < m->cols; j++) { printf("%c", m->data[i][j]); } printf("\n"); } printf("\n"); } void step(Matrix *m) { Matrix new_state = *m; for (int i = 0; i < m->rows; i++) { for (int j = 0; j < m->cols; j++) { int neighbors = neighbor_count(m, i, j); char current = m->data[i][j]; if (current == '*') { if (neighbors < 2 || neighbors > 3) { new_state.data[i][j] = ' '; } } else { if (neighbors == 3) { new_state.data[i][j] = '*'; } } } } *m = new_state; } int main() { Matrix m; memset(&m, 0, sizeof(m)); printf("1. 从文件加载\n"); printf("2. 生成随机状态\n"); int selection; scanf("%d", &selection); switch (selection) { case 1: { char filename[20]; printf("请输入文件名: "); scanf("%s", filename); load_from_file(&m, filename); break; } case 2: { int percent; printf("存活细胞百分比: "); scanf("%d", &percent); while (getchar() != '\n'); randomize(&m, percent); break; } default: printf("无效输入\n"); return 0; } printf("1. 分步动画(按回车下一步)\n"); printf("2. 流畅动画\n"); scanf("%d", &selection); while (getchar() != '\n'); switch (selection) { case 1: while (1) { print_matrix(&m); getchar(); step(&m); } break; case 2: while (1) { print_matrix(&m); step(&m); Sleep(200); } break; default: printf("无效输入\n"); break; } return 0; }
主要修改点
- 重构
step函数:创建独立的新状态矩阵,所有细胞的下一代状态基于原始矩阵计算,确保状态更新的同步性。 - 修正存活规则:明确区分存活/死亡细胞的判断逻辑,删除错误的强制存活分支,严格遵循康威生命游戏规则。
- 完善初始化逻辑:修复
load_from_file中列计数的重置问题,randomize中使用sizeof(m->data)确保内存初始化正确,初始化矩阵结构避免垃圾值。 - 优化用户体验:添加清屏操作让动画更清晰,修复输入缓冲区的换行符问题,兼容带/不带%的百分比输入,调整流畅动画的间隔时间。
内容的提问来源于stack exchange,提问作者HerrYetii
相关产品推荐
相关产品推荐

