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

C语言KenKen游戏代码中全局变量board_size值莫名变更问题

问题排查与解决方案

核心问题分析

导致board_size莫名从5变为3、board数组异常的直接原因是缓冲区溢出:

  • 全局变量group_length仅声明为int group_length[MAXN],但游戏组数group_count最多可达MAXN*MAXN(每个单元格单独成组)。当group_count超过MAXN时,写入group_length[group_count]会覆盖相邻的全局变量(如board_size),破坏其值。

具体修复方案

1. 修正数组大小

将group_length的大小调整为与group_value、group_operator一致,确保能容纳所有组的长度信息:

// 原声明
// int group_length[MAXN] = {0};
// 修改后
int group_length[MAXN*MAXN] = {0};

2. 重构坐标解析逻辑

替换脆弱的手动索引递增方式,使用sscanf和指针迭代实现鲁棒的坐标解析,支持多位数坐标和任意空格:

// 替换原while(current_line[i]!='\0')循环
char *ptr = line;
// 跳过值和运算符部分
while (*ptr != ' ' && *ptr != '\0') ptr++;

int x, y;
while (sscanf(ptr, " (%d,%d)", &x, &y) == 2) {
    group_size++;
    printf("(%d, %d) ", x, y);
    int bx = x - 1;
    int by = y - 1;
    board_group[bx][by] = group_count + 'a';
    board[bx][by] = 0;
    group_points[group_count][group_size-1].x = x;
    group_points[group_count][group_size-1].y = y;

    // 移动指针到下一个坐标
    while (*ptr != ')' && *ptr != '\0') ptr++;
    if (*ptr == ')') ptr++;
}

3. 统一输入读取方式

避免混合使用fscanf和fgets导致的输入缓冲区残留问题,改用fgets读取整行后再解析:

// 读取棋盘尺寸
char line[MAX_IN];
if (!fgets(line, MAX_IN, fp)) {
    perror("Failed to read board size");
    fclose(fp);
    exit(EXIT_FAILURE);
}
sscanf(line, "%d", &board_size);

// 读取每组规则
while (fgets(line, MAX_IN, fp)) {
    // 跳过空行
    if (line[0] == '\n' || line[0] == '\0') continue;
    
    int value;
    char op;
    if (sscanf(line, "%d%c", &value, &op) != 2) {
        fprintf(stderr, "Warning: Invalid line format - %s\n", line);
        continue;
    }
    // 后续解析逻辑...
}

4. 添加错误检查

增加文件打开、读取的错误处理,避免程序崩溃:

FILE *fp = fopen(filename, "r");
if (!fp) {
    perror("Failed to open file");
    exit(EXIT_FAILURE);
}

完整修正后的代码片段

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 10
#define MAX_IN 256

struct point {
    int x;
    int y;
};

struct point group_points[MAXN][MAXN] = {{}};
int board[MAXN][MAXN] = {{}};
char board_group[MAXN][MAXN] = {{}};
int group_value[MAXN*MAXN] = {0};
char group_operator[MAXN*MAXN] = {'\0'};
int group_length[MAXN*MAXN] = {0};
int board_size = 0;
int group_count = 0;

void readPuzzle(char *filename) {
    FILE *fp = fopen(filename, "r");
    if (!fp) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }
    printf("%s\n", filename);

    char line[MAX_IN];
    // 读取棋盘尺寸
    if (!fgets(line, MAX_IN, fp)) {
        perror("Failed to read board size");
        fclose(fp);
        exit(EXIT_FAILURE);
    }
    sscanf(line, "%d", &board_size);
    printf("%d\n", board_size);

    int current_group = 0;
    while (fgets(line, MAX_IN, fp)) {
        if (line[0] == '\n' || line[0] == '\0') continue;

        int value;
        char op;
        if (sscanf(line, "%d%c", &value, &op) != 2) {
            fprintf(stderr, "Warning: Invalid line format - %s\n", line);
            continue;
        }
        printf("%d %c\n", value, op);
        group_value[current_group] = value;
        group_operator[current_group] = op;

        int group_size = 0;
        char *ptr = line;
        while (*ptr != ' ' && *ptr != '\0') ptr++;

        int x, y;
        while (sscanf(ptr, " (%d,%d)", &x, &y) == 2) {
            group_size++;
            printf("(%d, %d) ", x, y);
            int bx = x - 1;
            int by = y - 1;
            board_group[bx][by] = group_count + 'a';
            board[bx][by] = 0;
            group_points[group_count][group_size-1].x = x;
            group_points[group_count][group_size-1].y = y;

            while (*ptr != ')' && *ptr != '\0') ptr++;
            if (*ptr == ')') ptr++;
        }

        group_length[group_count] = group_size;
        group_count++;
        current_group++;
        printf("\n\n%d\n\n", board_size);
    }

    fclose(fp);
}

额外优化建议

  • 避免全局变量:将游戏状态封装到结构体中,通过参数传递,减少意外副作用。
  • 坐标合法性校验:确保解析的x、y值在1~board_size范围内,防止数组越界访问。
  • 测试多尺寸棋盘:验证代码对大于5x5的棋盘的兼容性,确保多位数坐标解析正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:20:29