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

C++控制台数独开发:如何设置二维数组部分元素不可修改

问题背景

我正在开发一款控制台端数独游戏。根据数独游戏规则,用户在棋盘上移动光标时可修改自行填入的单元格数值。我目前采用二维数组存储棋盘所有数值,但遇到如下问题:数独棋盘存在部分预设初始值不可被用户修改,用户必须基于这些固定值推导完成解题,而我当前无法实现这部分单元格的常量锁定特性。

  • 核心疑问:如何才能实现二维数组中指定元素的不可修改特性?

以下是现有完整项目代码:

#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77

class Sudoku
{
    int wholeArray[9][9];
    int number;

public:
    void setArray(void);
    void displayArray(int& x, int& y);
    void readNumber(void);
    void setPositions(int& x, int& y);
    void changeEntry(int &x, int &y);
};

void setConsoleColor(int textColor, int bgColor) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (textColor + (bgColor * 16)));
}

void Sudoku::setArray(void)
{
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            wholeArray[i][j] = 0;
        }
    }
}

void Sudoku::displayArray(int& x, int& y)
{
    setConsoleColor(11, 0);
    cout << "\t\b\b\b1 2 3   4 5 6   7 8 9\n";
    cout << "   -------------------------\n";
    for (int i = 0; i < 9; i++)
    {
        cout << i + 1 << "  | ";
        for (int j = 0; j < 9; j++)
        {
            if (x == i && y == j)
                setConsoleColor(0, 11);
            cout << wholeArray[i][j];
            setConsoleColor(11, 0);
            cout << " ";

            if ((j + 1) % 3 == 0)
                cout << "| ";
        }
        cout << endl;
        if ((i + 1) % 3 == 0)
            cout << "   -------------------------\n";
    }
}

void Sudoku::readNumber(void)
{
    cout << "Enter number you want to enter (from 1-9): ";
    cin >> number;
}

void Sudoku::setPositions(int& x, int& y)
{
        char key = _getch();
        if (key == KEY_UP)
            x--;
        if (key == KEY_DOWN)
            x++;
        if (key == KEY_LEFT)
            y--;
        if (key == KEY_RIGHT)
            y++;

        if (x < 0)
            x = 8;
        else if (x > 8)
            x = 0;

        if (y < 0)
            y = 8;
        else if (y > 8)
            y = 0;

        if (key == 'x')
            exit(0);
        if (key == 'v')
            changeEntry(x, y);
        system("cls");
}

void Sudoku:: changeEntry(int& x, int& y)
{
    int entry;
    do
    {
        cout << "Enter value:\t";
        cin >> entry;
    } while (entry < 1 || entry > 9);

    wholeArray[x][y] = entry;
}

int main()
{
    int x = 0, y = 0, entry;

    Sudoku s1;
    s1.setArray();

    s1.displayArray(x, y);
    while (1)
    {
        s1.setPositions(x, y);
        s1.displayArray(x, y);
    }
    return 0;
}
实现方案

C++原生数组不支持给单个元素单独加const修饰实现锁效果,做数独场景下的格子锁定,用标记数组是最简单、可维护性最高的方案,全程不需要改动现有核心逻辑,只需要加3处小改动:

  1. 给Sudoku类新增一个和棋盘同尺寸的布尔二维数组isFixed[9][9],专门记录对应坐标的格子是不是初始预设、禁止修改的固定值。
  2. 初始化阶段同步设置标记:初始化棋盘时先把isFixed所有值设为false,后续加载数独题面、填入预设初始数字时,同步把对应坐标的isFixed设为true。
  3. 修改写入逻辑加拦截:在changeEntry方法最开头加判断,如果当前光标所在格子的isFixed标记为true,直接终止修改流程,可按需给用户弹出提示,只有标记为false的格子允许用户写入数值。

核心改动代码参考

类成员新增标记数组:

class Sudoku
{
    int wholeArray[9][9];
    bool isFixed[9][9]; // 固定格子标记
    int number;

public:
    void setArray(void);
    void displayArray(int& x, int& y);
    void readNumber(void);
    void setPositions(int& x, int& y);
    void changeEntry(int &x, int &y);
};

初始化方法补充标记初始化:

void Sudoku::setArray(void)
{
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            wholeArray[i][j] = 0;
            isFixed[i][j] = false; // 初始默认所有格子可修改
        }
    }
    // 后续加载题面填预设值时,同步写 isFixed[i][j] = true 即可
}

修改方法加锁定拦截:

void Sudoku:: changeEntry(int& x, int& y)
{
    // 拦截固定格子的修改请求
    if (isFixed[x][y]) {
        cout << "错误:当前格子为初始预设值,无法修改" << endl;
        system("pause");
        return;
    }
    int entry;
    do
    {
        cout << "Enter value:\t";
        cin >> entry;
    } while (entry < 1 || entry > 9);

    wholeArray[x][y] = entry;
}

可选体验优化

渲染棋盘时可以给isFixed为true的格子设置不同的文字颜色,比如用亮白色显示固定值,用青色显示用户填入的值,用户不需要试就能直接区分哪些格子可修改,交互体验会好很多。后续如果要加棋盘重置功能,也只需要遍历所有格子,把isFixed为false的格子值清0即可,不需要重复加载题面。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 05:48:34