You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

问题根源

  1. 状态更新逻辑错误:step函数中直接修改临时矩阵m_tmp的状态,后续细胞计算时会读取已经被修改的临时矩阵数据,违背了“所有细胞基于上一代完整状态同时更新”的核心规则。
  2. 存活规则逻辑错误:check_cell的最后一个分支会强制将任何邻居数为2或3的细胞设为存活,哪怕该细胞原本是死亡状态(死亡细胞仅在邻居数为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;
}

主要修改点

  1. 重构step函数:创建独立的新状态矩阵,所有细胞的下一代状态基于原始矩阵计算,确保状态更新的同步性。
  2. 修正存活规则:明确区分存活/死亡细胞的判断逻辑,删除错误的强制存活分支,严格遵循康威生命游戏规则。
  3. 完善初始化逻辑:修复load_from_file中列计数的重置问题,randomize中使用sizeof(m->data)确保内存初始化正确,初始化矩阵结构避免垃圾值。
  4. 优化用户体验:添加清屏操作让动画更清晰,修复输入缓冲区的换行符问题,兼容带/不带%的百分比输入,调整流畅动画的间隔时间。

内容的提问来源于stack exchange,提问作者HerrYetii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:31:08