2012-07-17 114 views
2

我試圖製作一個控制檯版本的掃雷,但是我在編輯電路板上的特定單元時遇到了一些困難。正如你所看到的,我有一個Board擁有一個私人的[6] [6] Cell對象數組。使用指針指向對象的方法C

此刻,我想叫的東西的細胞的方法,如 Board gameBoard; gameBoard.accessCell(row,col).flag(); 但這似乎不實際編輯訪問單元的狀態,因爲對象正在被複制,而不是一個指針。我如何修復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"; 
} 
+0

這是**遠**太多代碼堆棧溢出問題。請創建一個代表您的問題的小得多的測試用例。 – 2012-07-17 00:13:21

+0

您的構造函數在不存在的對象上調用'isMine',因爲它們超出了數組範圍。 – 2012-07-17 00:18:29

回答

4

您已經定義了訪問方法返回一個副本:

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]; } 
0

返回Cell對象而不是複製一個參考:

const Cell& Board::accessCell(int row, int col) const 
{ 
    return this->boardCells[row][col]; 
} 

如果你需要一個mutable版本(非const),那麼我會提示你,你需要重載這個功能。