如何在C++类中初始化一个可变大小的二维数组?

4

我正在开发一个井字游戏程序,需要在一个类中创建一个可变尺寸的二维数组。目前我是这样写的:

class ticTacToe
{
     public:
         ticTacToe();
         void display();
         bool moveIsValid();
     private:
         int rows;
         int cols;
         int board[rows][col];
}

我在构造函数中从文件中读取棋盘,但是我不知道如何使它具有可变大小,以便我可以读取任意大小的棋盘,然后在类外部访问它。


谢谢你的帮助!只是有一个小问题,当我在类外使用数组时,我只需要写 'ticTacToe newGame;' 和 'newGame->board[i][j];' 吗? - gcccpp
是的,你只需要写 ticTacToe newGame;,不需要使用 new - πάντα ῥεῖ
由于'board'是私有变量,你无法在ticTacToe类之外访问它。 - Quest
@Quest 你可以给它一个访问器函数,有什么问题吗? - πάντα ῥεῖ
1
@πάνταῥεῖ 我刚刚回答了他的问题,他不能直接使用它,因为它是私有变量,但是他可以使用访问器。 - Quest
@Quest 我没有看到他们的评论编辑。 - πάντα ῥεῖ
4个回答

5

"我在构造函数中从文件中读取棋盘,但我不知道如何使它具有可变大小,以便我可以读取任意大小的棋盘"

在C++中,您可以使用std::vector而不是原始数组,如下所示:

class ticTacToe {
     public:
         ticTacToe();
         void display();
         bool moveIsValid();
     private:
         int rows;
         int cols;
         std::vector<std::vector<int>> board; // <<<<
};

在构造函数中可以如下应用动态分配
ticTacToe(int rows_, int cols_) : rows(rows_), cols(cols_) {
    board.resize(rows,std::vector<int>(cols));
}

然后在类外部访问它

好的,我不确定这是否是一个好主意,但你可以简单地添加一个访问器函数来访问该成员变量。

 std::vector<std::vector<int>>& accBoard() { return board; }

更好的设计方法可能是提供类似于从std::istream读取的单独函数。
 void ticTacToe::readFromStream(std::istream& is) {
     // supposed the first two numbers in the file contain rows and cols
     is >> rows >> cols;
     board.resize(rows,std::vector<int>(cols));
     for(int r = 0; r < rows; ++r) {
         for(int c = 0; c < cols; ++c) {
             cin >> board[r][c];
         }
     }
 }

对于真实的代码,当然需要检查输入错误,例如:

 if(!(is >> rows >> cols)) {
    // handle errors from input
 }

4

如果这是一份作业并且您无法使用标准库:

// Declaration
int rows;
int columns;
int **board;

// Construction

board = new int*[rows];
for (int i = 0; i < rows; i++) {
    board[i] = new int[columns];
}

// Destruction


for (int i = 0; i < rows; i++) {
    delete[] board[i];
}
delete[] board;

更新:您可以执行单个分配,但按照这种方式处理会更容易。


1

你需要使用动态数组。

int* board;

那么你的构造函数将是:
ticTacToe::ticTacToe(int _rows, int _cols)
: rows{_rows}, cols{_cols}
{
    board = new int[rows * cols];
}

而你的析构函数

ticTacToe::~ticTacToe()
{
    delete[] board;
}

或者更好的方法是使用一个 std::vector
std::vector<int> board;

然后你的构造函数将是:
ticTacToe::ticTacToe(int _rows, int _cols)
: rows{_rows}, cols{_cols}
{
    board.resize(_rows * _cols);
}

2
你的意思是 vector<vector<int>> 对吧? - Christophe
@Christophe 不一定。他们可以使用单个向量并使用行/列算术。由他们决定。 - Cory Kramer
没错,我认为对于原帖的作者来说,使用一维向量会更容易/更好。找到它的“平方”,并使用行乘以高度来获取值。 - Evan Carslake
1
索引 =(当前行 * 行长度)+ 当前列例如:在一个5x5的棋盘上,[2][5]的索引为25。 - Evan Carslake
@Cyber 当然可以!他们也可以直接用汇编语言编写程序 :-D 但是如果他们使用2D板和2D算法,为什么不使用专门用于此目的的语言特性呢? - Christophe
如果你声明int board[rows][col],它看起来像一个二维数组,但实际上它已经是一个一维数组,这就是我所说的。 - Cory Kramer

0

我建议您使用指向指针的指针。

#include <iostream>
#include <cstdlib>

using namespace std;

class ticTacToe{
private:
    int rows;
    int cols;
    int **board; // POINTER TO POINTER
public:
    ticTacToe(int a,int b){
        rows=a;
        cols=b;
        board=new int*[rows];

        for (int k = 0; k < rows; ++k) {
            board[k]=new int[cols];
        }

        /*LET'S INITIALIZE CELL VALUES TO= 0*/
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                board[i][j]=0;
            }
        }
    }
    void display();
    bool moveIsValid();
};

这个问题的主要问题是必须动态初始化2D数组。因此,我们使用指针进行动态初始化,但是当我们必须初始化2D数组时,使用指针有点不同。然后,我们使用指向指针的指针(int **board)。它用双星号标记定义,可以保存指针。之后,我们可以将指针数组分配给它(board = new int * [rows];)。然后它可以填充一个维度。为了填充其他维度,我们可以使用循环并将列数组分配给它。 - Iresh Rajitha Kalhara
不要将它作为注释提及,编辑答案并添加说明。 - 0xInfection

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接