★関数(引数と戻り値2)★


前回は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つ渡すことになれば同じ問題が発生します。

この問題を解決するため、次回から「ポインタ変数」「アドレス渡し」という考え方を説明します。


次へ

戻る

目次へ