質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

3916閲覧

C++で3目並べのプログラムが相手の手番になりません。

hon.ki

総合スコア157

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/01/16 09:43

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

//ユーザーを表すクラスの実装(手を選ぶ) void User::select() { int n; do { cout << mark << "の手を選んでください = "; cin >> n; } while (n > 1 || n > 9); number = n; }

ここの不等号の向きが逆になっていますが、これですかね?

投稿2019/01/16 09:52

ko.tu

総合スコア178

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko.tu

2019/01/16 09:59

ちなみにVScodeの差分表示機能を使って探しました プログラムとクリップボードの内容を簡単に比較できます それ以外でもVSCodeは便利なので使っていないのであれば是非使ってみてください
hon.ki

2019/01/16 13:39

当該箇所を修正したところ、無事動きました。また、VSCodeをちょうど使っていたのですが、差分表示機能は知らなかったので、とても参考になりました。本当に、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問