2012-07-17 3 views
2

콘솔 버전의 Minesweeper를 만들려고하고 있지만 보드의 특정 셀을 편집하는 데 어려움이 있습니다. 보시다시피, 저는 Cell 객체의 private [6] [6] 배열을 가지고있는 Board를 가지고 있습니다. 순간 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

스택 오버플로 문제에 대한 코드가 너무 많습니다. 문제를 대표하는 훨씬 작은 테스트 케이스를 작성하십시오. –

+0

당신의 생성자는 배열 범위 밖에 있기 때문에 존재하지 않는 객체들에 대해'isMine'을 호출합니다. –

답변

4

당신은 사본을 반환하는 액세스 방법을 정의 : 당신이 반환되는 Cell을 수정할 수 있기를 원하기 때문에, 대신 참조를 반환해야

Cell accessCell(int row, int col) const ; 

을하고, 방법은해야 const이 아닙니다.

Cell & accessCell(int row, int col); 

해당 변경 사항은 해당 방법을 구현할 때도 수행해야합니다.

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

반환하는 대신 사본의 셀 개체에 대한 참조 : 당신은 mutable 버전 (비 const)를해야하는 경우

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

, 그럼 난 당신이 과부하 할 필요가 있음을 암시합니다 기능.

관련 문제