2013-12-14 2 views
0

В игре Tic Tac Toe, которую я создаю для школы, у меня есть пять классов: игра (действует как контроллер для игры), Player (базовый класс), HumanPlayer и AIPlayer (оба производные от игрока) и Board.Объект C++ или двумерный массив в качестве параметра?

Совет содержит 2D-массив и некоторые функции для отображения и работы с массивом. У всех трех игроков есть функция makeAMove(Board &board), которая выберет позицию на доске и поместит X или O.

Как видите, makeAMove принимает параметр Board в качестве параметра. Затем функция примет решение о перемещении и изменит массив досок платы Board. Если я правильно понимаю, фактический объект, который будет передан, будет изменен, и нет необходимости возвращать что-либо обратно.

Я правильно понимаю это? Было бы лучше использовать 2d-массив в качестве параметра вместо этого?

Это сокращенная версия моего кода.

#include <iostream> 
#include <memory> // auto_ptr 

class Board 
{ 
    public: 
     Board() 
     { 
      for (int row = 0; row < 3; row++) 
      { 
       for (int column = 0; column < 3; column++) 
        board[row][column] = ' '; 
      } 
     } 

     void displayBoard() 
     { 
      std::cout << "\n-------------" << std::endl; 

      for (int row = 0; row < 3; row++) 
      { 
       std::cout << "| " ; 
       for (int column = 0; column < 3; column++) 
        std::cout << board[row][column] << " | "; 
       std::cout << "\n-------------" << std::endl; 
      } 
     } 

/*  My thought was to use getBoard to return the array rather than using the 
     object as a parameter  
     char getBoard() 
     { 
      return board[][3]; 
     }  
*/ 

    char getCell(int row, int column) 
    { 
     return board[row][column]; 
    } 

    void setCell(int row, int column, char player) 
    { 
     board[row][column] = player; 
    } 

    private: 
     char board[3][3]; 

}; 

class Player 
{ 
    public: 
     virtual void makeAMove(Board &board) = 0; 
}; 

class AIPlayer : public Player 
{ 
    virtual void makeAMove(Board &board) 
    { 
     // do some work ont the board array 
    } 
}; 

class HumanPlayer : public Player 
{ 
    virtual void makeAMove(Board &board) 
    { 
     // do some work on the board array 
    } 
}; 

class Game 
{ 
    public: 
     Game(unsigned int players) 
     { 
      if (players == 1) 
      { 
       player1.reset (new HumanPlayer()); 
       player2.reset (new AIPlayer()); 
      } 
      else 
      { 
       player1.reset (new HumanPlayer()); 
       player2.reset (new HumanPlayer()); 
      } 
     } 

     void playGame() 
     { 
      player1->makeAMove(myBoard); 
     } 

    private: 
     std::auto_ptr<Player> player1; // pointer to a Player object (C++11 has more secure unique_ptr) 
     std::auto_ptr<Player> player2; // pointer to a Player object 
     Board myBoard; 
}; 

int main() 
{ 
    Game myGame(1); 
    myGame.playGame(); 

    return 0; 
} 

ответ

1

makeAMove принадлежит board. Объекты игрока должны решить, что делать, а затем позвонить board::makeAMove, чтобы сделать ход. Таким образом, объекту игрока не важно, что такое внутреннее представление платы.

2

Да, потому что вы передаете объект Board по ссылке, любое изменение к нему в функции изменит фактический объект Board. Я думаю, что передача объекта Board является лучшей идеей, так как лучше не подвергать пользователя реальную реализацию (2D-массив в этом случае) игры. Таким образом, переход к объекту Board дает больше абстракции, что хорошо.

0

Передайте объект по ссылке, как и вы, вместо массива. Любые изменения, сделанные игроком на борту, будут сохраняться.

board является частным членом Board. Его следует возвращать только по значению, а не по ссылке. Если вы передадите игроку 2d массив по значению, любые изменения, внесенные им на доске, не будут сохраняться.

Вашему классу Player необходимо будет получить доступ к Board.setCell(int, int), в функции makeAMove(Board &board), и для этого им понадобится объект платы.

Однако ваши классы Players должны будут прочитать доску. Чтобы сделать ход. Функция getCell(int,int) может быть достаточной, но также может быть утомительным для вложенного цикла через все ячейки. A getBoard может быть полезен для возможной функции decideMove.

+0

Да, возможно, вы правы. Но я не уверен, как вернуть 2d-массив в getter. – navig8tr

+0

Вы действительно не должны, если только массив не был 'std :: vector ' или 'std :: array ' from C++ 11. В противном случае ваши игроки не будут знать длину массивов. Может быть, просто есть символ 'char [9]' вместо 2D-массива? Нужно ли быть 2D-массивом? – cheezsteak

+0

Нет, нет. Это просто облегчает ввод пользователя. Сначала пользователь вводит строку, а затем столбец. Эти числа затем непосредственно применяются к массиву 2d (после некоторой проверки). Если бы я использовал 1d-массив, мне нужно было бы преобразовать каждую строку и столбец в один индекс. Конечно, не невозможно, но я стараюсь держать его как можно проще. – navig8tr

Смежные вопросы