• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C++のプログラミングについての質問)

C++プログラミングについての質問

このQ&Aのポイント
  • C++初心者がクラスを組み合わせたプログラムを製作していますが、MPが不足している場合に再度攻撃の選択をさせる方法について教えてください。
  • 英雄と魔王が戦うC++プログラムを作成中ですが、MPが不足している場合に攻撃の選択を再度させる方法について質問です。
  • C++初心者です。英雄と魔王が戦うプログラムを組み合わせる際、MPが不足している場合に再度攻撃の選択をさせる方法について教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • goosyu
  • ベストアンサー率58% (36/62)
回答No.4

 修正したソースを貼ります。修正点は”【”で検索できます。  ☆プログラム方法は色々とありますので,参考としてください。 #include <iostream> #include <cstdlib> #include <ctime> using namespace std; class Hero { int Power; int ATP; int DFP; int MP; public: Hero() : Power(200),ATP(50),DFP(30),MP(50){} int GetPower() { return Power; } int GetATP() { return ATP; } int GetDFP() { return DFP; } int GetMP() { return MP; } void Report() const { cout << "☆☆☆勇者のステータス☆☆☆" <<endl; cout << "パワー" << Power << "pt" <<endl; cout << "攻撃力" << ATP << "pt" <<endl; cout << "防御力" << DFP << "pt" <<endl; cout << "魔力 " << MP << "pt" <<endl; } int command(); //【置換】void tokushu(int p); bool tokushu(int p); //【置換】void mahou(int p); bool mahou(int p); }; int Hero::command() { int n; std::cout << std::endl; cout << "コマンドを選択してください" <<endl; cout << "1:通常攻撃"<<endl; cout << "2:特殊攻撃 (MP10消費)"<<endl; cout << "3:魔法攻撃 (MP20消費)"<<endl; cin >> n; switch(n) { case 1: cout << "勇者の通常攻撃" <<endl; break; case 2: cout << "勇者の特殊攻撃" <<endl; // 【置換】tokushu(10); if ( false == tokushu(10) ) n = 0; // command再入力が必要 break; default: cout << "勇者の魔法攻撃" <<endl; // 【置換】mahou(20); if ( false == mahou(20) ) n = 0; // command再入力が必要 break; } return n; } // 【置換】void Hero::tokushu(int p) bool Hero::tokushu(int p) { if(p > MP) { cout << "MPが不足しています" <<endl; // 【置換】command(); return false; } else { std::cout << "特殊攻撃をします。"<< std::endl; MP -= p; } // 【追加】 return true; } // 【置換】void Hero::mahou(int p) bool Hero::mahou(int p) { if(p > MP) { cout << "MPが不足しています" <<endl; // 【置換】command(); return false; } else { std::cout << "魔法攻撃をします。"<< std::endl; MP -= p; } // 【追加】 return true; } class Daimao { int Power; int ATP; int DFP; public: Daimao() : Power(400),ATP(70),DFP(20){} int GetPower() { return Power; } int GertATP() { return ATP; } int GetDFP() { return DFP; } void Attacked(int n, int p); }; void Daimao::Attacked(int n, int p) { if(n==1) { Power -= p; std::cout <<"敵に"<< p <<"のダメージ!!"<< std::endl; } else if(n==2) { Power -= p; std::cout <<"敵に"<< p <<"のダメージ!!"<< std::endl; } else { Power -= p; std::cout << "敵に" << p << "のダメージ!!" << std::endl; } } class Battle { Hero h; Daimao d; public: Battle(); void taiketsu(); }; Battle::Battle() { cout << "勇者であるあなたは大魔王を倒さなければいけません。" << endl; } void Battle::taiketsu() { std::cout << "勇者の攻撃です。" << std::endl; std::cout << std::endl; h.Report(); // 【置換】int n =h.command(); int n; while (1) { n = h.command(); if ( 0 != n ) break; // 0以外はループから抜ける } cout << endl; if(n==1) { d.Attacked(n,h.GetATP() - d.GetDFP()); } else if(n==2) { d.Attacked(n,h.GetATP() - d.GetDFP() + rand() % 9 + 1); } else { d.Attacked(n,h.GetATP() - d.GetDFP() + rand() % 9 + 5); } } int main() { Battle dokoka; dokoka.taiketsu(); }

jiuko77
質問者

お礼

回答を参考に自分なりに修正してみたところ、問題点を解決することが出来ました。 図々しい質問にもかかわらず、懇切丁寧な回答をしていただき 本当にありがとうございました。 深く感謝致します。

その他の回答 (3)

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.3

少し補足します。参考になれば幸いです。 問題動作のトレース結果,” + ”はコールの深さです。 dokoka.taiketsu();  + h.Report();  + n1=h.command();     + n2=3     + mahou(20);        + command();           + n3=1           + return n; (n3=1) ←ここの結果がどこにも反映されない。        + return;     + return n2; (n2=3)  + d.Attacked(3, h.GetATP() - d.GetDFP() + rand() % 9 + 5); (n1=3)     + return;  + return; ※nはローカル変数の為,同じ名前の変数だがコール元とコール先の変数は全く別です。わかりやすくする為にnをn1,n2,n3を置き換えています。 上記のトレースでわかるように,再入力が連続するとコールが深くなり,再入力の回数に限界があります。 この為,commandの入力は再入力も含め1箇所で行うようにロジックを修正する必要があります。 サンプルとしてcommand再入力の問題を解決する方法を載せておきます。 ・command()に1つルール追加。戻り値が0の場合は再入力させる。戻り値が1~3は今まで通り。   int Hero::command()   {     int n;       :略     cin >> n;     switch(n)     {     case 1:       cout << "勇者の通常攻撃" <<endl;       break;     case 2:       cout << "勇者の特殊攻撃" <<endl;       if (0 == tokushu(10)) {         n = 0; // 再入力       }       break;     default:       cout << "勇者の魔法攻撃" <<endl;       if (0 == mahou(20)) {         n = 0; // 再入力       }       break;     }     return n;   } ・command()をコールする場合はループ処理内から行い,command()の戻り値が0以外の時にループから抜ける。   ☆具体的には次のようなループ   while (1) {     n = h.command();    if ( 0 != n ) break;   } ・tokushu(),mahou()からのcommand()コールを止めて,戻り値の返す関数にします。再入力が必要な場合は0を返し,再入力の必要がない場合は1を返す。   ☆tokushu()サンプル   int Hero::tokushu(int p)   {     if(p > MP)     {       cout << "MPが不足しています" <<endl;       //command(); コールが深くなるのでここでは止める。       return 0;     }     else     {       std::cout << "特殊攻撃をします。"<< std::endl;       MP -= p;     }     return 1;   }

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.2

ソース提示ありがとうございます。ソースを確認しました。  原因は mahou()関数から呼ばれるcommand()関数の戻り値が捨てられている為です。 簡単に処理を追うと次のようになります。 事前条件:  MP=10でcommand()コールされ,”3:魔法攻撃 (MP20消費)"を選択。 動作トレース:  Hero::mahou()関数をコール,MP不足と判断して再入力の為,command()をコールします。  しかしこのcommand()関数のコールでは戻り値の処理が無い為,command()の選択を1としてもその結果がコール元に反映されない。つまりnの値が反映される機会がない為,もとの値n=3になります。

jiuko77
質問者

お礼

迅速かつ真摯な回答をしていただきありがとうございます。 command()関数で戻り値の処理が無いということは理解できたのですが、その後修正してみたものの思うようにいきません。 具体的にどうソースを修正すればよいのでしょうか? 初心者の至らない質問で申し訳ありません。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.1

 何をしたいかと,うまく動かないという説明だけでは,解決方法の提示は出来ません。どのように作ったという情報が欠けています。まずはソース添付してください。  あと,開発環境はわかりませんが,トレース(ステップ実行などのデバッグ)を使えるようにしておくと今回のようなロジック(処理)の問題点がわかります。

jiuko77
質問者

補足

#include <iostream> #include <cstdlib> #include <ctime> using namespace std; class Hero { int Power; int ATP; int DFP; int MP; public: Hero() : Power(200),ATP(50),DFP(30),MP(50){} int GetPower() { return Power; } int GetATP() { return ATP; } int GetDFP() { return DFP; } int GetMP() { return MP; } void Report() const { cout << "☆☆☆勇者のステータス☆☆☆" <<endl; cout << "パワー" << Power << "pt" <<endl; cout << "攻撃力" << ATP << "pt" <<endl; cout << "防御力" << DFP << "pt" <<endl; cout << "魔力 " << MP << "pt" <<endl; } int command(); void tokushu(int p); void mahou(int p); }; int Hero::command() { int n; std::cout << std::endl; cout << "コマンドを選択してください" <<endl; cout << "1:通常攻撃"<<endl; cout << "2:特殊攻撃 (MP10消費)"<<endl; cout << "3:魔法攻撃 (MP20消費)"<<endl; cin >> n; switch(n) { case 1: cout << "勇者の通常攻撃" <<endl; break; case 2: cout << "勇者の特殊攻撃" <<endl; tokushu(10); break; default: cout << "勇者の魔法攻撃" <<endl; mahou(20); break; } return n; } void Hero::tokushu(int p) { if(p > MP) { cout << "MPが不足しています" <<endl; command(); } else { std::cout << "特殊攻撃をします。"<< std::endl; MP -= p; } } void Hero::mahou(int p) { if(p > MP) { cout << "MPが不足しています" <<endl; command(); } else { std::cout << "魔法攻撃をします。"<< std::endl; MP -= p; } } class Daimao { int Power; int ATP; int DFP; public: Daimao() : Power(400),ATP(70),DFP(20){} int GetPower() { return Power; } int GertATP() { return ATP; } int GetDFP() { return DFP; } void Attacked(int n, int p); }; void Daimao::Attacked(int n, int p) { if(n==1) { Power -= p; std::cout <<"敵に"<< p <<"のダメージ!!"<< std::endl; } else if(n==2) { Power -= p; std::cout <<"敵に"<< p <<"のダメージ!!"<< std::endl; } else { Power -= p; std::cout << "敵に" << p << "のダメージ!!" << std::endl; } } class Battle { Hero h; Daimao d; public: Battle(); void taiketsu(); }; Battle::Battle() { cout << "勇者であるあなたは大魔王を倒さなければいけません。" << endl; } void Battle::taiketsu() { std::cout << "勇者の攻撃です。" << std::endl; std::cout << std::endl; h.Report(); int n =h.command(); cout << endl; if(n==1) { d.Attacked(n,h.GetATP() - d.GetDFP()); } else if(n==2) { d.Attacked(n,h.GetATP() - d.GetDFP() + rand() % 9 + 1); } else { d.Attacked(n,h.GetATP() - d.GetDFP() + rand() % 9 + 5); } } int main() { Battle dokoka; dokoka.taiketsu(); } 全部載せると長くなってしまうので、パワー(体力)が0になるまで繰り返すといったところは省略しています。

関連するQ&A