C++で3目並べのプログラムを作っているのですが、自分の手番に指し手を入力しても、相手の手番になりません。これは、どこが違ってしまっているのでしょうか。自分ではどうしても見つけられませんでしたので、ご教授頂ければ幸いです。
mac os high sierra 10.13.6を使っており、コンパイラはclangで
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
となっています。どうぞよろしくお願いいたします。
コード #include <iostream> #include <cstdlib> #include <ctime> using namespace std; //プレイヤーを表すクラスの定義(基本クラス) class Player { protected: char mark; //枠に書き込む記号 int number; //選んだ手(1~9) public: virtual void select() = 0; //手を選ぶ(純粋仮想関数) char getMark(); //記号を返す int getNumber(); //手を返す Player(char mark); //コンストラクタ }; //ユーザーを表すクラスの定義(派生クラス) class User : public Player { public: void select(); //手を選ぶ User(char mark); //コンストラクタ Markにしてバグってた }; //コンピュータを表すクラスの定義(派生クラス) class Computer : public Player { public: void select(); //手を選ぶ Computer(char mark); //コンストラクタ }; //盤面を表すクラスの定義 class Board { private: char cell[3][3]; public: void show(); //盤面を表示する bool setCell(Player *player); //枠に記号を書き込む bool judge(Player *player); //勝敗を判定する Board(); //コンストラクタ }; //プレイヤーを表すクラスの実装(記号を返す) char Player::getMark() { return mark; } //プレイヤーを表すクラスの実装(手を返す) int Player::getNumber() { return number; } //プレイヤーを表すクラスの実装(コンストラクタ) Player::Player(char mark) { this->mark = mark; } //ユーザーを表すクラスの実装(手を選ぶ) void User::select() { int n; do { cout << mark << "の手を選んでください = "; cin >> n; } while (n > 1 || n > 9); number = n; } //ユーザーを表すクラスの実装(コンストラクタ) User::User(char mark) : Player(mark) { } //コンピュータを表すクラスの実装(手を選ぶ) void Computer::select() { number = rand() % 9 + 1; cout << mark << "の手を選んでください = " << number << "\n"; } //コンピュータを表すクラスの実装(コンストラクタ) Computer::Computer(char mark) : Player(mark) { } //盤面を表すクラスの実装(盤面を表示する) void Board::show() { cout << "\n"; for (int v = 0; v < 3; v++) { cout << "+-+-+-+\n"; for (int h = 0; h < 3; h++) { cout << "|" << cell[v][h]; } cout << "|\n"; } cout << "+-+-+-+\n"; } //盤面を表すクラスの実装(枠に記号を書き込む) bool Board::setCell(Player *player) { int number = player->getNumber(); int v = (number - 1) / 3; int h = (number - 1) % 3; // %を/にしていてエラーになっておった if (cell[v][h] >= '1' && cell[v][h] <= '9') { //書き込めたらtrueを返す cell[v][h] = player->getMark(); return true; } else { //書き込めないならfalseを返す cout << "そこには書き込めません!\n"; return false; } } //盤面を表すクラスの実装(勝敗を決定する) bool Board::judge(Player *player) { //プレイヤーが勝ちならtureを返す char mark = player->getMark(); if (cell[0][0] == mark && cell[0][1] == mark && cell[0][2] == mark || cell[1][0] == mark && cell[1][1] == mark && cell[1][2] == mark || cell[2][0] == mark && cell[2][1] == mark && cell[2][2] == mark || cell[0][0] == mark && cell[1][0] == mark && cell[2][0] == mark || cell[0][1] == mark && cell[1][1] == mark && cell[2][1] == mark || cell[0][2] == mark && cell[1][2] == mark && cell[2][2] == mark || cell[0][0] == mark && cell[1][1] == mark && cell[2][2] == mark || cell[2][0] == mark && cell[1][1] == mark && cell[0][2] == mark) { cout << "\nゲーム終了:" << mark << "の勝ちです!\n"; return true; } //引き分けならtrueを返す bool draw = true; for (int v = 0; v < 3 && draw; v++){ for (int h = 0; h < 3 && draw; h++ ){ if (cell[v][h] >= '1' && cell[v][h] <= '9'){ draw = false; } } } if (draw){ cout << "\nゲーム終了:" << "引き分けです!\n"; return true; } //勝敗が確定していなければ、falseを返す return false; } //盤面を表すクラスの実装(コンストラクタ) Board::Board(){ for(int v = 0; v < 3; v++){ for(int h = 0; h < 3; h++){ cell[v][h] = (v * 3 + h + 1) + '0'; } } } //メイン関数 int main(){ Player *player[2]; //2人のプレイヤー User user('o'); //ユーザー(記号はo) Computer computer('x'); //コンピューター(記号はx) player[0] = &computer; //先手のプレイヤー(コンピュータ) player[1] = &user; //後手プレイヤー(ユーザー) Board board; //盤面 int turn = 0; //順番(0と1で交互に切り替える) //乱数を初期化する srand(time(NULL)); //勝敗が決まるまで繰り返す while(true){ //盤面を表示する board.show(); //プレイヤーが手を選ぶ do { player[turn]-> select(); } while(board.setCell(player[turn]) == false); //勝敗を判定する if (board.judge(player[turn])) { //勝敗が確定したら、ゲームを終了する break; } //プレイヤーを交互に切り返る if (turn == 0) { turn = 1; } else { turn = 0; } } //盤面を表示する board.show(); return 0; }
そして、以下が参考書にありました模範回答です(こちらは手元の環境で正常に動きました)
上下のコードを見比べていたのですが、違いが見つけられません。
コード #include <iostream> #include <cstdlib> #include <ctime> using namespace std; // プレイヤーを表すクラスの定義(基本クラス) class Player { protected: char mark; // 枠に書き込む記号 int number; // 選んだ手(1〜9) public: virtual void select() = 0; // 手を選ぶ(純粋仮想関数) char getMark(); // 記号を返す int getNumber(); // 手を返す Player(char mark); // コンストラクタ }; // ユーザーを表すクラスの定義(派生クラス) class User : public Player { public: void select(); // 手を選ぶ User(char mark); // コンストラクタ }; // コンピュータを表すクラスの定義(派生クラス) class Computer : public Player { public: void select(); // 手を選ぶ Computer(char mark); // コンストラクタ }; // 盤面を表すクラスの定義 class Board { private: char cell[3][3]; // 3×3の枠 public: void show(); // 盤面を表示する bool setCell(Player *player); // 枠に記号を書き込む bool judge(Player *player); // 勝敗を判定する Board(); // コンストラクタ }; // プレイヤーを表すクラスの実装(記号を返す) char Player::getMark() { return mark; } // プレイヤーを表すクラスの実装(手を返す) int Player::getNumber() { return number; } // プレイヤーを表すクラスの実装(コンストラクタ) Player::Player(char mark) { this->mark = mark; } // ユーザーを表すクラスの実装(手を選ぶ) void User::select() { int n; do { cout << mark << "の手を選んでください = "; cin >> n; } while (n < 1 || n > 9); number = n; } // ユーザーを表すクラスの実装(コンストラクタ) User::User(char mark) : Player(mark) { } // コンピュータを表すクラスの実装(手を選ぶ) void Computer::select() { number = rand() % 9 + 1; cout << mark << "の手を選んでください = " << number << "\n"; } // コンピュータを表すクラスの実装(コンストラクタ) Computer::Computer(char mark) : Player(mark) { } // 盤面を表すクラスの実装(盤面を表示する) void Board::show() { cout << "\n"; for (int v = 0; v < 3; v++) { cout << "+-+-+-+\n"; for (int h = 0; h < 3; h++) { cout << "|" << cell[v][h]; } cout << "|\n"; } cout << "+-+-+-+\n"; } // 盤面を表すクラスの実装(枠に記号を書き込む) bool Board::setCell(Player *player) { int number = player->getNumber(); int v = (number - 1) / 3; int h = (number - 1) % 3; if (cell[v][h] >= '1' && cell[v][h] <= '9') { // 書き込めたらtrueを返す cell[v][h] = player->getMark(); return true; } else { // 書き込めないならfalseを返す cout << "そこには書き込めません!\n"; return false; } } // 盤面を表すクラスの実装(勝敗を判定する) bool Board::judge(Player *player) { // プレイヤーが勝ちならtrueを返す char mark = player->getMark(); if (cell[0][0] == mark && cell[0][1] == mark && cell[0][2] == mark || cell[1][0] == mark && cell[1][1] == mark && cell[1][2] == mark || cell[2][0] == mark && cell[2][1] == mark && cell[2][2] == mark || cell[0][0] == mark && cell[1][0] == mark && cell[2][0] == mark || cell[0][1] == mark && cell[1][1] == mark && cell[2][1] == mark || cell[0][2] == mark && cell[1][2] == mark && cell[2][2] == mark || cell[0][0] == mark && cell[1][1] == mark && cell[2][2] == mark || cell[2][0] == mark && cell[1][1] == mark && cell[0][2] == mark) { cout << "\nゲーム終了:" << mark << "の勝ちです!\n"; return true; } // 引き分けならtrueを返す bool draw = true; for (int v = 0; v < 3 && draw; v++) { for (int h = 0; h < 3 && draw; h++) { if (cell[v][h] >= '1' && cell[v][h] <= '9') { draw = false; } } } if (draw) { cout << "\nゲーム終了:" << "引き分けです!\n"; return true; } // 勝敗が確定していなければfalseを返す return false; } // 盤面を表すクラスの実装(コンストラクタ) Board::Board() { for (int v = 0; v < 3; v++) { for (int h = 0; h < 3; h++) { cell[v][h] = (v * 3 + h + 1) + '0'; } } } // メイン関数 int main() { Player *player[2]; // 2人のプレイヤー(基本クラスの配列) User user('o'); // ユーザー(記号はo) Computer computer('x'); // コンピュータ(記号はx) player[0] = &computer; // 先手のプレイヤー(コンピュータ) player[1] = &user; // 後手のプレイヤー(ユーザー) Board board; // 盤面 int turn = 0; // 順番(0と1で交互に切り替える) // 乱数を初期化する srand(time(NULL)); // 勝敗が決まるまで繰り返す while (true) { // 盤面を表示する board.show(); // プレイヤーが手を選ぶ do { player[turn]->select(); } while (board.setCell(player[turn]) == false); // 勝敗を判定する if (board.judge(player[turn])) { // 勝敗が確定したらゲームを終了する break; } // プレイヤーを交互に切り替える if (turn == 0) { turn = 1; } else { turn = 0; } } // 盤面を表示する board.show(); return 0; }
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/01/16 09:59
2019/01/16 13:39