在 C 中对指向对象的指针使用方法
Posted
技术标签:
【中文标题】在 C 中对指向对象的指针使用方法【英文标题】:Using methods on pointers to objects in C 【发布时间】:2012-07-15 21:29:26 【问题描述】:我正在尝试制作 Minesweeper 的控制台版本,但在编辑板上的特定单元格时遇到了一些困难。如您所见,我有一个 Board,它有一个私有的 [6][6] Cell 对象数组。
目前,我正在尝试使用类似的方式调用 Cell 方法
Board gameBoard;
gameBoard.accessCell(row,col).flag();
但这似乎实际上并不是在编辑访问的 Cell 的状态,因为正在复制对象而不是指针。如何修复 Board::accessCell(int row, int col)
以返回指向对象的指针,以便我可以调用函数并实际编辑其状态?
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <iomanip>
#include <string>
using namespace std;
#define debugging true //set this to true to activiate debugging
const int ROWS(6), COLS(6), MINE(-1);
const char FLAG('F'), REVEALED('R'), HIDDEN('*');
class Cell
friend class Board;
private:
char displaySetting;
int minesTouching;
public:
Cell();
int getMinesTouching() const;
void increaseMinesTouching();
char getDisplaySetting() const;
bool isMine() const;
void flag();
void reveal();
void setMine();
;
int Cell::getMinesTouching() const return this->minesTouching;
void Cell::increaseMinesTouching() this->minesTouching++;
char Cell::getDisplaySetting() const return this->displaySetting;
bool Cell::isMine() const return this->minesTouching == MINE;
void Cell::flag() this->displaySetting = FLAG;
void Cell::reveal() this->displaySetting = REVEALED;
void Cell::setMine() this->minesTouching = MINE;
Cell::Cell():
displaySetting(HIDDEN),
minesTouching(0)
class Board
private:
Cell boardCells[ROWS][COLS];
public:
Board();
bool isInBounds(int row, int col) const;
void reveal(int row, int col);
void displayBoard() const;
Cell accessCell(int row, int col) const;
;
Board::Board()
//place mines randomly
srand(time(0));
for(int i=0; i<6;)
int row = rand()%6, col = rand()%6;
if(!this->boardCells[row][col].isMine())
this->boardCells[row][col].setMine();
i++;
//determine number of mines touching each space and store them
for(int i=0; i<ROWS; i++)
for(int j=0; j<COLS; j++)
if(!boardCells[i][j].isMine())
if(boardCells[i+1][j+1].isMine()) boardCells[i][j].increaseMinesTouching(); //bottom right
if(boardCells[i-1][j-1].isMine()) boardCells[i][j].increaseMinesTouching(); //top left
if(boardCells[i+1][j+0].isMine()) boardCells[i][j].increaseMinesTouching(); //down
if(boardCells[i+0][j+1].isMine()) boardCells[i][j].increaseMinesTouching(); //right
if(boardCells[i-1][j-0].isMine()) boardCells[i][j].increaseMinesTouching(); //up
if(boardCells[i-0][j-1].isMine()) boardCells[i][j].increaseMinesTouching(); //left
if(boardCells[i+1][j-1].isMine()) boardCells[i][j].increaseMinesTouching(); //bottom left
if(boardCells[i-1][j+1].isMine()) boardCells[i][j].increaseMinesTouching(); //top right
bool Board::isInBounds(int row, int col) const
if(row < 0) return false;
if(row >= ROWS) return false;
if(col >= COLS) return false;
if(col < 0) return false;
return true;
void Board::reveal(int row, int col)
if(!this->boardCells[row][col].getMinesTouching())
this->boardCells[row][col].reveal();
if(isInBounds(row+1, col+1)) this->reveal(row+1, col+1); //bottom right
if(isInBounds(row-1, col-1)) this->reveal(row-1, col-1); //top left
if(isInBounds(row+1, col+0)) this->reveal(row+1, col+0); //down
if(isInBounds(row+0, col+1)) this->reveal(row+0, col+1); //right
if(isInBounds(row-1, col-0)) this->reveal(row-1, col-0); //up
if(isInBounds(row-0, col-1)) this->reveal(row-0, col-1); //left
if(isInBounds(row+1, col-1)) this->reveal(row+1, col-1); //bottom left
if(isInBounds(row-1, col+1)) this->reveal(row-1, col+1); //top right
void Board::displayBoard() const
system("clear");
if(debugging) //display system board if debugging is enabled
for(int i=0; i<ROWS; i++)
for(int j=0; j<COLS; j++)
cout << "[ " << setw(3) << this->boardCells[i][j].getMinesTouching() << setw(3) << " ]";
cout << "\n";
cout << "\n\n\n";
//
for(int i=0; i<ROWS; i++)
for(int j=0; j<COLS; j++)
if(this->boardCells[i][j].getDisplaySetting() == HIDDEN)
cout << "[ " << setw(3) << this->boardCells[i][j].getDisplaySetting() << setw(3) << " ]";
else if(this->boardCells[i][j].getDisplaySetting() == REVEALED)
cout << "[ " << setw(3) << this->boardCells[i][j].getMinesTouching() << setw(3) << " ]";
else
cout <<"[ " << setw(3) << FLAG << setw(3) << " ]";
cout << "\n";
cout << "\n";
Cell Board::accessCell(int row, int col) const return this->boardCells[row][col];
//function prototypes
void provideMenu();
string playTurn(Board gameBoard, int& guesses);
void playGame();
int main()
Board gameBoard;
provideMenu();
return 0;
void provideMenu()
int choice(0);
while(choice < 1 || choice > 3)
cout << "1:\t Play a game of Minesweeper" << endl;
cout << "2:\t Help" << endl;
cout << "3:\t Exit" << endl;
cin>>choice;
switch(choice)
case 1:
playGame();
break;
case 2:
cout << "The objective of Minesweeper is to clear all the tiles on the board without mines without uncovering any hidden mines" << endl;
cout << "*\t Hidden tile, has yet to be revealed" << endl;
cout << "F\t Flagged tile, marked by user as possible mine" << endl;
cout << "#\t Any number represents the number of mines touching the tile" << endl;
break;
void playGame()
Board gameBoard;
int guesses(0);
string gameState = "onGoing";
while(gameState == "onGoing")
gameState = playTurn(gameBoard, guesses);
if(gameState == "userWon")
cout << "Congratulations, you've one!" << endl;
if(gameState == "userLost")
cout << "Game over! Try again!" << endl;
gameBoard.displayBoard();
string playTurn(Board gameBoard, int& guesses)
gameBoard.displayBoard();
int row;
do
cout << "Row:";
cin>>row;
while(row <0 || row >= ROWS);
int col;
do
cout << "Column:";
cin>>col;
while(col < 0 || col>= COLS);
if(gameBoard.accessCell(row, col).isMine())
return "userLost";
if(++guesses == ROWS*COLS-6)
return "userWon";
gameBoard.reveal(row,col);
return "onGoing";
【问题讨论】:
对于 Stack Overflow 问题来说,这远代码太多了。请创建一个小得多的测试用例来代表您的问题。 您的构造函数对不存在的对象调用isMine
,因为它们超出了数组的范围。
【参考方案1】:
您已经定义了返回副本的访问方法:
Cell accessCell(int row, int col) const ;
由于您希望能够修改返回的Cell
,因此您应该返回一个引用,并且方法不应该是const
。
Cell & accessCell(int row, int col);
也需要对方法的实现进行相应的更改。
Cell & Board::accessCell(int row, int col) return this->boardCells[row][col];
【讨论】:
【参考方案2】:返回对 Cell 对象的引用而不是副本:
const Cell& Board::accessCell(int row, int col) const
return this->boardCells[row][col];
如果你需要mutable
版本(非const
),那么我会提示你需要重载这个函数。
【讨论】:
以上是关于在 C 中对指向对象的指针使用方法的主要内容,如果未能解决你的问题,请参考以下文章