前回はBattle関数を作り、戦闘後のhpがmain関数のhpに反映されないことが問題でした。
今回は対応策を考えてみます。
関数には「戻り値」というものがあります。
関数から1つデータを戻せるという機能です。
これを使えば、戦闘後のhpをmain関数に戻せるのでは無いでしょうか?
早速やってみますので、前回のプログラム↓を出してください。
<sample program 131-05>
#include <stdio.h>
void Status(int hp);
void Battle(int hp); /* @ */
int main(void)
{
int hp;
hp = 100;
Status(hp);
Battle(hp); /* A */
Status(hp);
return 0;
}
void Status(int hp)
{
printf("Player's Status\n");
printf("HP = %d\n", hp);
}
void Battle(int hp) /* @ */
{
hp -= 50; /* B */
}
|
@戻り値としてhpを戻すためvoidからintに変更します。
ABattle関数は戻り値を返すため、main関数のhpで受け取ります。
Bhpを減らした後、return文を使ってhpを戻さなければなりません。
以前やったことを思い出して変更してみてください。
解答例です。
<sample program 132-01>
#include <stdio.h>
void Status(int hp);
int Battle(int hp); /* @ */
int main(void)
{
int hp;
hp = 100;
Status(hp);
hp = Battle(hp); /* A */
Status(hp);
return 0;
}
void Status(int hp)
{
printf("Player's Status\n");
printf("HP = %d\n", hp);
}
int Battle(int hp) /* @ */
{
hp -= 50;
return hp; /* B */
}
|
<実行結果>
Player's Status HP = 100 Player's Status HP = 50 続行するには何かキーを押してください・・・
実行結果を見るとhpの変化が反映されていることが分かります。
前回と同じように図で流れを書いてみます。
<sample program 132-01>
#include <stdio.h>
void Status(int hp);
int Battle(int hp);
int main(void)
{
int hp;
hp = 100; /* @ */
Status(hp); /* A */
hp = Battle(hp); /* B */
Status(hp); /* E */
return 0;
}
void Status(int hp)
{
printf("Player's Status\n");
printf("HP = %d\n", hp);
}
int Battle(int hp)
{
hp -= 50; /* C */
return hp; /* D */
}
|
初期状態からです。
main関数 Battle関数
+------+ +------+
int hp | ???? | int hp | ???? |
+------+ +------+
@の部分でmain関数のhpに初期値がセットされます。
main関数 Battle関数
+------+ +------+
int hp | 100 | int hp | ???? |
+------+ +------+
Aの部分でmain関数のhpが表示されます。
main関数 Battle関数
+------+ +------+
int hp | 100 | int hp | ???? |
+------+ +------+
↓
画面に出力
Bの部分でバトル関数が呼び出されmain関数のhpの中身がコピーされます。
main関数 Battle関数
+------+ +------+
int hp | 100 | → コピー int hp | 100 |
+------+ +------+
Cの部分でBattle関数のhpが50減ります。
main関数 Battle関数
+------+ +------+
int hp | 100 | int hp | 50 |
+------+ +------+
Dの部分でBattle関数のhpがmain関数に戻されます。
main関数 Battle関数
+------+ +------+
int hp | 50 | 戻り値 ← int hp | 50 |
+------+ +------+
※関数の実行が完了すると引数の変数は解放されます。
Eの部分でmain関数のhpが表示されます。
main関数 Battle関数
+------+ +------+
int hp | 50 | int hp | ???? |
+------+ +------+
↓
画面に出力
これで上手くいったように感じますが、パラメーターを増やしたらどうなるでしょう?
パラメーターとしてmp(マジックポイント、マナポイント、マジックパワーなどの略)を追加してみましょう。
まずは、Status関数を改良してmpも表示できるようにしましょう。
main関数に変数mpを追加し初期値50を入れ、Status関数の引数にもmpを追加します。
hpの次の行にmpを表示するプログラムを追加します。
それでは作ってみてください。
※プロトタイプ宣言を変更した場合、本体も同じように変更するのを忘れないようにしましょう。
<実行結果>
Player's Status HP = 100 MP = 50 Player's Status HP = 50 MP = 50 続行するには何かキーを押してください・・・
解答例です。
<sample program 132-02>
#include <stdio.h>
void Status(int hp, int mp);
int Battle(int hp);
int main(void)
{
int hp;
int mp;
hp = 100;
mp = 50;
Status(hp, mp);
hp = Battle(hp);
Status(hp, mp);
return 0;
}
void Status(int hp, int mp)
{
printf("Player's Status\n");
printf("HP = %d\n", hp);
printf("MP = %d\n", mp);
}
int Battle(int hp)
{
hp -= 50;
return hp;
}
|
<実行結果>
Player's Status HP = 100 MP = 50 Player's Status HP = 50 MP = 50 続行するには何かキーを押してください・・・
Status関数はこれで完成です。
続いてBattle関数にも引数mpを追加し、mpを渡せるようにしましょう。
途中まで書いてみます。
<sample program 132-03>
#include <stdio.h>
void Status(int hp, int mp);
int Battle(int hp, int mp);
int main(void)
{
int hp;
int mp;
hp = 100;
mp = 50;
Status(hp, mp);
hp = Battle(hp, mp);
Status(hp, mp);
return 0;
}
void Status(int hp, int mp)
{
printf("Player's Status\n");
printf("HP = %d\n", hp);
printf("MP = %d\n", mp);
}
int Battle(int hp, int mp)
{
hp -= 50;
return hp;
}
|
Battle関数の中身以外は変更しました。
さて、この中身が問題です。
とりあえず、mpを20ほど減らしてみましょう。
int Battle(int hp, int mp)
{
hp -= 50;
mp -= 20;
return hp;
}
|
さて、どうやってmpを戻すのでしょうか?
return文は1つのデータしか戻せません。
return hp, mp; |
とは書けませんし、
hp = Battle(hp, mp); |
こちらもhpしか受け取れない状態です。
return hp; return mp; |
このように2行に分けて書いたとしても、最初のreturn文が実行されたら関数は実行を終わります。
return hp; return mp; ← こっちは実行されない。(コンパイル時に警告が出ます) |
困りました・・・ゲームのパラメーターはhp、mpだけではありません。
構造体を使うことで一時的には解決出来ますが、構造体を2つ渡すことになれば同じ問題が発生します。
この問題を解決するため、次回から「ポインタ変数」「アドレス渡し」という考え方を説明します。