如何在C语言中不使用数组生成指定模式数独网格并修复偶数行重复问题
数独网格生成代码的错误分析与修复
需求说明
需要用C语言生成特定模式的数独网格,要求如下:
- 左上角起始值为可配置变量
- 方块大小为变量(示例中方块大小为2,网格边长为4)
- 禁止使用数组、指针,仅可使用循环等控制结构
示例效果:
- 起始值为1时的网格:
1 2 3 4 3 4 1 2 2 3 4 1 4 1 2 3
- 起始值为3时的网格:
3 4 1 2 1 2 3 4 4 1 2 3 2 3 4 1
总结规律:奇数行的下一行起始值为当前行倒数第二个数,偶数行的下一行起始值为当前行最后一个数。但编写的代码出现偶数行重复问题,尝试的代码如下:
#include <stdio.h> const int intSquareSize = 2; const int intFieldLength = intSquareSize * intSquareSize; int intStartValue = 3; int main() { int a = 0; int b = 0; int m = 0; for (int intRowCounter = 1; intRowCounter <= intFieldLength; intRowCounter++) { m = intFieldLength - 1; for (int intColumnCounter = 1; intColumnCounter <= intFieldLength; intColumnCounter++) { a = intStartValue + (intColumnCounter - 1); b = a; if (a > intFieldLength) { a = intFieldLength - m; m--; } if (intRowCounter % 2 == 0 && intColumnCounter == intFieldLength) { intStartValue = a; } else if (intRowCounter % 2 == 1 && intColumnCounter == (intFieldLength - 1)) { intStartValue = b; } printf("%d\t", a); } printf("\n"); } return 0; }
错误分析
代码存在以下核心问题:
- 起始值更新时机错误:在列循环内部修改
intStartValue,会导致当前行后续列的计算提前使用更新后的值,破坏当前行的生成逻辑。 - 奇数行起始值更新逻辑错误:列循环中记录的
b是当前列的a值,而非当前行倒数第二个元素的值,导致下一行起始值计算错误。 - 元素计算逻辑冗余易出错:用
m变量处理超出网格边长的数值,逻辑复杂且容易出现计数偏差,不如模运算简洁可靠。
修复方案
重新设计逻辑,核心思路:
- 每一行生成完成后,再根据当前行奇偶性计算下一行起始值,避免在列循环中修改起始值干扰当前行。
- 用模运算简化元素值的循环生成逻辑。
- 记录当前行的倒数第二个和最后一个元素,用于计算下一行起始值。
修复后的代码:
#include <stdio.h> const int intSquareSize = 2; const int intFieldLength = intSquareSize * intSquareSize; int intStartValue = 3; int main() { for (int intRowCounter = 1; intRowCounter <= intFieldLength; intRowCounter++) { int lastVal = 0; int secondLastVal = 0; for (int intColumnCounter = 1; intColumnCounter <= intFieldLength; intColumnCounter++) { // 用模运算实现1~intFieldLength的循环数值生成 int val = intStartValue + intColumnCounter - 1; if (val > intFieldLength) { val -= intFieldLength; } // 记录倒数第二个和最后一个元素值 if (intColumnCounter == intFieldLength - 1) { secondLastVal = val; } if (intColumnCounter == intFieldLength) { lastVal = val; } printf("%d\t", val); } printf("\n"); // 行结束后更新下一行起始值 if (intRowCounter % 2 == 1) { intStartValue = secondLastVal; } else { intStartValue = lastVal; } } return 0; }
运行修复后的代码,起始值为3时会输出符合要求的网格:
3 4 1 2 1 2 3 4 4 1 2 3 2 3 4 1
起始值为1时也能生成正确结果。
内容的提问来源于stack exchange,提问作者Chipmaster5
相关产品推荐
相关产品推荐

