【问题标题】:Passing an object reference into an overloader将对象引用传递给重载器
【发布时间】:2015-09-17 06:04:17
【问题描述】:

当我运行 ComputerVsComputer 时,井字棋盘都是空的。我已经研究过,试图找出原因。我怀疑它与范围有关。但是,我迷失在 C++ 中,无法理解它。帮忙?

井字游戏.h

#include <iostream>

using namespace std;

class TicTacToeBoard{
    public:
        TicTacToeBoard(){
            for(int x=0; x<9; x++){
                board[x]='\0';
            }
        }

        void printBoard(){
            cout << endl << board[0] << " |" << board[1] << " |" << board[2] << endl;
            cout << "--"<< "|--|" << "--" << endl;
            cout << board[3] << " |" << board[4] << " |" << board[5] << endl;
            cout << "--" << "|--|" << "--" << endl;
            cout << board[6] << " |" << board[7] << " |" << board[8] << endl << endl;
        }

        char board[9];

        string name;
};

class TicTacToePlayer
{
    public:


        TicTacToePlayer(int isFirstPlayer, TicTacToeBoard& newboard)
        : board(newboard)
        {

            if(isFirstPlayer)
                symbol = 'X';
            else
                symbol = 'O';                 
        }

        /* user made move */
        void makeMove(int m, int n){     

            board.board[getIndexRef(m,n)] = symbol;

            board.printBoard();
        };

        /* computer made move */
        void automateMove(){
            for(int x=0; x<9; x++){
                if(board.board[x]=='\0'){
                    board.board[x]=OpponentSymbol();
                    break;
                }
            }
        };

        /* checks if position in the board is ocupied, 
           returns 1 for occupied
           0 for not occupied */
        int checkPoss(int m, int n){
            int indexRef;

            //if((m>=0 && m<4) && (n>=0 && n<4)){
                indexRef = getIndexRef(m,n);

                if( board.board[indexRef]=='X' || board.board[indexRef]=='O' ){
                    return 1;
                } else {
                    return 0;
                }
            //}
        };

        /* checks and prints the status of game,
        with the help of checkWin()
        retuns  0 for inprogress
            1 for end of game */

        int checkGameStatus(){
            int privateStatus = checkWin();

            if(privateStatus==0){
                if(symbol=='X'){
                    cout << endl << "You win!" << endl;
                } else {
                    cout << endl << "You lose :(" << endl;
                }
                return 1;
            } else if(privateStatus==1){
                if(symbol=='O'){
                    cout << endl << "You win!" << endl;
                } else {
                    cout << endl << "You lose :(" << endl;
                }
                return 1;
            } else if(privateStatus==2){
                cout << endl << "Draw!" << endl;
                return 1;
            } else {
                cout << endl << "The game is in progress!  Continue." << endl;
                return 0;
            }
        };

    private:
        /* Use an appropriate data structure
        for storing the board */

        TicTacToeBoard board;

        char symbol;

        /* Checks who won
        returns 0 for X win
            1 for O win
            2 for draw */
        int checkWin(){
            // check the verticals

            if((checkSlots(1,1,'X') && checkSlots(2,1,'X') && checkSlots(3,1,'X')) || (checkSlots(1,2,'X') && checkSlots(2,2,'X') && checkSlots(3,2,'X')) || (checkSlots(1,3,'X') && checkSlots(2,3,'X') && checkSlots(3,3,'X'))){
                return 0;
            }

            // check horizontals
                if((checkSlots(1,1,'X') && checkSlots(1,2,'X') && checkSlots(1,3,'X')) || (checkSlots(2,1,'X') && checkSlots(2,2,'X') && checkSlots(2,3,'X')) || (checkSlots(3,1,'X') && checkSlots(3,2,'X') && checkSlots(3,3,'X'))){
                return 0;
            }           

            // check diagonals
            if((checkSlots(1,1,'X') && checkSlots(2,2,'X') && checkSlots(3,3,'X')) || (checkSlots(3,1,'X') && checkSlots(2,2,'X') && checkSlots(3,1,'X'))){
                return 0;
            }


            // check verticals
            if((checkSlots(1,1,'O') && checkSlots(2,1,'O') && checkSlots(3,1,'O')) || (checkSlots(1,2,'O') && checkSlots(2,2,'O') && checkSlots(3,2,'O')) || (checkSlots(1,3,'O') && checkSlots(2,3,'O') && checkSlots(3,3,'O'))){
                return 1;
            }

            // check horizontals
            if((checkSlots(1,1,'O') && checkSlots(1,2,'O') && checkSlots(1,3,'O')) || (checkSlots(2,1,'O') && checkSlots(2,2,'O') && checkSlots(2,3,'O')) || (checkSlots(3,1,'O') && checkSlots(3,2,'O') && checkSlots(3,3,'O'))){
                return 1;
            }           

            // check diagonals
            if((checkSlots(1,1,'O') && checkSlots(2,2,'O') && checkSlots(3,3,'O')) || (checkSlots(3,1,'O') && checkSlots(2,2,'O') && checkSlots(3,1,'O'))){
                return 1;
            }

            // to check if it is a draw, confirm that all slots are filled
            for(int x=0; x<9; x++){
                if(board.board[x]=='\0'){
                    return 3; // 3 is neither a win nor a draw
                }
            }

            // if the function hasn't returned by this point, it's a draw
            return 2;
        }

        bool checkSlots(int m, int n, char testSymbol){
            return board.board[getIndexRef(m,n)]==testSymbol;
        }

        int getIndexRef(int row, int col){
            int indexRef;

            if((row>=0 && row<4) && (col>=0 && col<4)){
                if(row==1) {
                    indexRef = col-1; // col is always 1, 2, or 3, so get board[0], board[1], or board[2]
                } else if(row==2) {
                    indexRef = row+col; // always 2+1, 2+2, or 2+3, or boards 3,4,5
                } else if(row==3) {
                    indexRef = row+col+2;     // always 3+1+2, 3+2+2, or 3+3+2, or 6,7,8
                }

                return indexRef;
            } else {
                return 99; // error
            }
        }

        char OpponentSymbol(){
            if(symbol=='X'){
                return 'O';
            } else {
                return 'X';
            }
        }
};

现在是 ComputerVsComputer

#include <iostream>
#include "TicTacToe.h"

using namespace std;

int main()
{
    TicTacToeBoard gameboard;
gameboard.name = "Boo"; 
    TicTacToePlayer player1(true, gameboard);
    TicTacToePlayer player2(false, gameboard);
    gameboard.printBoard();

    while (1)
    {
        player1.automateMove();
        if (player1.checkGameStatus())
        {
            gameboard.printBoard();
            break;
        }
        gameboard.printBoard();
        player2.automateMove();
        if (player2.checkGameStatus())
        {
            gameboard.printBoard();
            break;
        }
        gameboard.printBoard();
    }

    return 0;
}

【问题讨论】:

    标签: c++ reference scope


    【解决方案1】:

    TicTacToePlayer 采用TicTacToeBoard 按值,这意味着它在每个TicTacToePlayer 对象中复制。当你修改副本时,只有副本被修改,而不是原始的。

    您需要通过 reference 来传递它:

    TicTacToePlayer(int isFirstPlayer, TicTacToeBoard& newboard);
    

    还有成员board 作为参考:

    TicTacToeBoard& board;
    

    但是,您不能分配引用,您需要初始化它,您可以使用构造函数初始化列表:

    TicTacToePlayer(int isFirstPlayer, TicTacToeBoard& newboard)
        : board(newboard)
    {
        ...
    }
    

    现在player1player2 都将引用gameboard 变量,并且一个玩家对象的更改将更改gameboard 对象。

    【讨论】:

    • 根据您的反馈,我在我的 TicTacToe.h 文件中更改了这些行。不过,我没有看到任何 X 或 O。 [code]class TicTacToePlayer{ public: TicTacToePlayer(int isFirstPlayer, TicTacToeBoard& newboard) : board(newboard) { if(isFirstPlayer) symbol = 'X';否则符号='O'; }[/code]
    • 对不起,约阿希姆。我之前的评论很糟糕。这是在线编译器的链接:goo.gl/6mo2Rv
    猜你喜欢
    • 2014-05-01
    • 1970-01-01
    • 2012-09-05
    • 2013-09-15
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多