この間投稿したRPGっぽい物にメニュー機能とアイテム管理機能を付け加えてみました。
メニューは問題なく機能し、アイテムも「インベントリに何もなければ」機能するのですが…………
インベントリに何かを入れた状態でアイテムを表示しようとすると、動作を停止してしまいます。
コンパイルエラーは出ていないので、恐らく「文法的には正常であるが、開発者の意図には沿っていない」類のバグだと思われます。
インベントリに何もない、つまり初期化しただけの状態ならば、ItemFunc.cにも書いてある通り「No. アイテム名:個数」の下に、
「アイテムを所持していません。」と表示されます。
今回は「1. 量産型えくすかりばー:5」と表示するのが目的でした。
下にソース(?)を全て記述します。
何度かコンパイルした結果に問題部分であると思われた箇所を、注釈で示しておきます。
SysFunc.h
/*ゲーム機能のヘッダ。*/
int OptJudge (int *p, int Opt, int OptMIN, int OptMAX); /*参照:OptJudge.c*/
struct Status /*ステータスの構造体*/
{
char Name[50];
int LV;
int HP;
int MP;
};
struct ItemInfo /*アイテム情報の構造体*/
{
char Name[50];
char Explanation[200];
int Kind;
short int CanTrade;
unsigned short int MaxNum;
};
struct Inv /*インベントリ管理の構造体*/
{
int ID;
int Number;
};
OptJudge.c
/*入力された値が選択肢に対して有効かどうかを判断する関数。*/
#include <stdio.h>
void OptJudge (int *p, int Opt, int OptMIN, int OptMAX)
{
if (OptMIN <= Opt && Opt <= OptMAX)
{
*p = 1;
}
else
{
*p = 0;
printf("\n\n選択肢の中の値を入力してください。\n\n入力:");
}
}
game.c
/*ゲーム本体*/
#include <stdio.h>
#include <string.h>
#include "SysFunc.h"
struct Status Player = {"", 1, 15, 10}; /*プレイヤーの初期ステータスを宣言*/
struct ItemInfo Item[1000]; /*アイテム情報表示用の構造体を宣言*/
struct Inv Inventory[100] ; /*プレイヤーのインベントリの構造体とその容量を宣言*/
main()
{
char Input[200], Warn[200]; /*入力用変数(Input)と警告文表示用の変数(Warn)を宣言。*/
int Opt, OptMAX, OptMIN, Judge = 0, flag = 0; /*左から選択肢、選択肢の最大値、選択肢の最小値、成否判断、先に進むフラグ*/
for (flag = 0; flag <= 99; flag++) /*インベントリ全スロットの初期化*/
{
Inventory[flag].ID = 0;
Inventory[flag].Number = 0;
}
/*------------------推測される問題箇所(この部分を取り除いたら動作の停止はなくなった)-------------------------*/
strcpy(Item[1].Name, "量産型えくすかりばー"); /*仮アイテムデータ*/
Inventory[0].ID = 1; /*量産型えくすかりばーを持たせてみる*/
Inventory[0].Number = 5;
/*---------------------------------------推測される問題箇所(以上)-----------------------------------------*/
printf("\n------------------------------\nC言語で作るRPG\n------------------------------\n1.はじめから\n2.つづきから(未実装)\n3.おわる\n\n\n入力:"); /*スタートメニュー表示*/
OptMIN = 1;
OptMAX = 3;
while (flag != 1) /*スタートするか否か*/
{
gets(Input);
Opt = atoi(Input);
OptJudge(&flag, Opt, OptMIN, OptMAX); /*参照:SysFunc.h OptJudge.c*/
}
switch(Opt)
{
case 1: /*ゲーム開始*/
{
Opt = 0;
printf("\n\n\nキャラクターを作成します。キャラクターネームを半角換算50文字以内で入力してください。\n\n入力:");
while (Opt != 1)
{
Judge = 0;
OptMAX = 2;
gets(Player.Name);
printf("\n\nキャラクターネームは「%s」でよろしいですか?\n1.はい\n2.いいえ\n\n入力:",Player.Name);
while (Judge != 1)
{
gets(Input);
Opt = atoi(Input);
OptJudge(&Judge, Opt, OptMIN, OptMAX);
}
if (Opt == 2)
{
printf("\n\n\nキャラクターネームを半角換算50文字以内で入力してください。\n\n入力:");
}
}
printf("\n\n\nキャラクターを作成しました。\n\nようこそ、%s。ゲームを開始します。",Player.Name);
Menu(Player, Item, Inventory);
break;
}
case 2: /*つづきから(未実装)*/
{
printf("\n\n\nこの機能は未実装です。ゲームを終了します。\n");
break;
}
case 3: /*ゲーム終了*/
{
printf("\n\n\nゲームを終了します。\n");
break;
}
}
}
Menu.c
/*メニュー機能*/
#include <stdio.h>
#include "SysFunc.h"
#define MENU_MIN 1
#define MENU_MAX 6
void Menu(struct Status Player, struct ItemInfo Item[], struct Inv Inventory[])
{
int flag = 0, GameEnd = 0, Opt;
char Input[50];
while (GameEnd != 1)
{
printf("\n\n------------------------------");
printf("\nメニュー");
printf("\n------------------------------"); /*プレイヤーステータス表示*/
printf("\n\n%s",Player.Name);
printf("\n\n LV:%d",Player.LV);
printf("\n HP:%d",Player.HP);
printf("\n MP:%d",Player.MP);
printf("\n\n------------------------------"); /*メニュー*/
printf("\n\n1.出撃(未実装)");
printf("\n2.アイテム(実装中)");
printf("\n3.スキル(未実装)");
printf("\n4.装備(未実装)");
printf("\n5.セーブ(未実装)");
printf("\n6.ゲーム終了");
printf("\n\n入力:");
while (flag != 1)
{
gets(Input);
Opt = atoi(Input);
OptJudge(&flag, Opt, MENU_MIN, MENU_MAX);
}
flag = 0;
switch (Opt)
{
case 1: /*出撃*/
{
break;
}
case 2: /*アイテム*/
{
ItemFunc(Item, Inventory);
break;
}
case 3: /*スキル*/
{
break;
}
case 4: /*装備*/
{
break;
}
case 5: /*セーブ*/
{
break;
}
case 6: /*ゲーム終了*/
{
printf("\n\nゲームを終了してもよろしいですか?\n1.はい\n2.いいえ\n\n入力:");
while (flag != 1)
{
gets(Input);
Opt = atoi(Input);
OptJudge(&flag, Opt, 1, 2);
}
flag = 0;
switch (Opt)
{
case 1:
printf("\n\n\nゲームを終了します。\n");
GameEnd = 1;
break;
case 2:
GameEnd = 0;
break;
}
break;
}
}
}
}
ItemFunc.c
/*アイテムの管理*/
#include <stdio.h>
#include "SysFunc.h"
void ItemFunc(struct ItemInfo Item[], struct Inv Inventory[])
{
short int ItemEnd = 0;
int Opt = 0, flag = 0, OptMIN = 0, OptMAX = 0;
char Input[50];
while (ItemEnd != 1) /*0を入力するとメニューに戻る*/
{
printf("\n\n\n------------------------------");
printf("\nアイテム");
printf("\n------------------------------");
printf("\n\n%4s %-40s:%s\n","No.","アイテム名","個数");
for (flag = 0; Inventory[flag].ID != 0 && flag <= 99; flag++) /*持っているものをすべて表示する*/
{
printf("\n%3s. %-40s:%d", flag + 1, Item[Inventory[flag].ID].Name, Inventory[flag].Number); /*恐らくここで動作が止まっている*/
}
if (Inventory[0].ID == 0) /*インベントリの1スロット目のアイテムIDが0、すなわち空だったら*/
{
printf("\n\nアイテムを所持していません。");
}
else
{
OptMAX = flag + 1; /*flag + 1個で表示したアイテムの個数、すなわち選択肢の数*/
}
flag = 0;
printf("\n\n 0.戻る\n\n\n入力:");
while (flag != 1) /*アイテム選択 or 戻る*/
{
gets(Input);
Opt = atoi(Input);
OptJudge(&flag, Opt, OptMIN, OptMAX); /*参照:SysFunc.h OptJudge.c*/
}
switch (Opt)
{
case 0:
{
ItemEnd = 1;
break;
}
}
}
}
こういう場合、ソースを全て書いておいた方が多分良いですよね?
この分だと回を追うごとに冗長になりそうですが……(汗)
救助求む!
-----------------------修正-----------------------------
ItemFunc.c
for (flag = 0; Inventory[flag].ID != 0 && flag <= 99; flag++) /*持っているものをすべて表示する*/
{
printf("\n%3d. %-40s:%d", flag + 1, Item[Inventory[flag].ID].Name, Inventory[flag].Number);
}
if (Inventory[0].ID == 0) /*インベントリの1スロット目のアイテムIDが0、すなわち空だったら*/
\n%3s → \n%3d に直したところ、正常に動作しました。flag + 1は整数ですからね。
Ki4mTaria様、有難うございました。