#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h> //擬似乱数rand()のため
#define max_player 10
int menu();
void state();
void state_end();
void game();
void show_state(int flg);
void save();
void load();
typedef struct PLAYER /*キャラクターステータスの構造体*/
{
char name[10];
int hp , atk , spd;
int hpCurrent;
/* hp=体力 atk=攻撃力 spd=素早さ hpCurrent=現在の体力*/
}PLAYER;
int nin; //キャラクター数
int flgState=0; //ステータス入力orロードをしたときに1となる
struct PLAYER player[max_player];
int main()
{
int flg;
srand((unsigned int)time(NULL)); //擬似乱数rand()を使うためのもの(実行するたびに異なる値を得るためのもの)
while(1){
flg=menu(); //1が返ってきたら終了する
if(flg==1)break;
}
return 0;
}
int menu()
{
int flg;
printf("[メニュー画面]\n");
printf("0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了\n");
scanf("%d",&flg);
printf("\n");
switch(flg){
case 0:state();flgState=1;break;
case 1:game();break;
case 2:save();break;
case 3:load();flgState=1;break;
case 4:return 1;
default:menu();
}
return 0;
}
void state()
{
int i; /*ninはプレイヤー人数の指定変数*/
printf("[ステータス入力画面]\n");
printf("作成するプレイヤーの数を決めてください(1-10)\n");
scanf("%d",&nin);
if(nin<1)return;
for(i=0;i<nin;i++) /*入力ループ*/
{
printf("\nプレイヤー%dのステータスを設定してください\n",i+1);
printf(" NAME:");
scanf("%s",player[i].name);
printf(" HP:");
scanf("%d",&player[i].hp);
if(player[i].hp<1)return;
printf("ATTACK:");
scanf("%d",&player[i].atk);
if(player[i].atk<1)return;
printf(" SPEED:");
scanf("%d",&player[i].spd);
if(player[i].spd<1)return;
}
printf("\n作成したプレイヤーの確認を行います\n");
show_state(2);
state_end();
return;
}
void state_end()
{
char yn;
fflush(stdin); //これがないと次のscanfで'\n'が入力されてしまう。stdinは普通キーボード入力を意味する
printf("この設定でよろしいですか?(Y/N)\n");
scanf("%c",&yn);
printf("\n");
if((yn=='y')||(yn=='Y'))return;
else if((yn=='n')||(yn=='N')){
state();
}
else{
state_end();
}
}
void game()
{
int i,j;
int t; //ターン数
int spdTotal; //各プレイヤーのspd(素早さ)の総和
int spdIndex[max_player]; //まだHPが0でないキャラクタの番号リスト
int spdNum; //まだHPが0でないキャラクタの数
printf("[戦闘実行画面]\n");
if(flgState!=1){
printf("戦闘できませんでした(ステータスが入力されてません)\n\n");
return;
}
for(i=0;i<nin;i++)player[i].hpCurrent=player[i].hp;
show_state(0);
t=0;
while(1){
printf("%d回目 ",t+1);
printf("0:続行 1:終了\n");
scanf("%d",&j);
if(j==1){
printf("\n");
return;
}
//行動するキャラクタの選択
i=0;
spdNum=0;
while(1){ //まだHPが0でないキャラクタの番号をspdIndexに入力
if(player[i].hpCurrent!=0){
spdIndex[spdNum]=i;
spdNum++;
}
i++;
if(i>=nin)break;
}
spdTotal=0;
for(i=0;i<spdNum;i++)
spdTotal+=player[spdIndex[i]].spd; //各(まだHPが0でないキャラクタ)spdの総和を求める
j=rand()%spdTotal; //擬似乱数で[0 ~ spdの総和-1]の範囲を選ぶ
for(i=0;i<spdNum;i++){ //攻撃を行うキャラクタの選択(詳細は下記参照)
if(j<player[spdIndex[i]].spd){
j=spdIndex[i];
break;
}
j-=player[spdIndex[i]].spd;
}
printf("\n%sのターン\n",player[j].name);
//攻撃
for(i=0;i<nin;i++){
if(i!=j)
player[i].hpCurrent-=player[j].atk; //攻撃を行うキャラクタ以外のキャラクタのHPを下げる
if(player[i].hpCurrent<0)player[i].hpCurrent=0; //マイナスになったら0とおく
}
//表示
show_state(1); //引数1 → NAMEとHPだけを表示
//終了条件
j=0;
for(i=0;i<nin;i++)
if(player[i].hpCurrent==0)j++; //HPが0のキャラクタの数を数える
if(j==nin-1)break; //一人以外がHP0であれば終了する
t++;
}
for(i=0;i<nin;i++)
if(player[i].hpCurrent!=0) //HPが0でないキャラクタの勝利
printf("%sの勝利\n\n",player[i].name);
}
//flgが0 → NAME,HP,ATTACK,SPEEDを表示 flgが1 → NAME,HPを表示 flgが2 → NAME,HP(初期値),ATTACK,SPEEDを表示
void show_state(int flg)
{
int i;
printf(" NAME ");
for(i=0;i<nin-1;i++)printf("%9.9s ",player[i].name);
printf("%9.9s\n",player[nin-1].name);
if(flg==2){
printf(" HP ");
for(i=0;i<nin-1;i++)printf("%9d ",player[i].hp);
printf("%9d\n",player[nin-1].hp);
}
else{
printf(" HP ");
for(i=0;i<nin-1;i++)printf("%9d ",player[i].hpCurrent);
printf("%9d\n",player[nin-1].hpCurrent);
}
if(flg==0||flg==2){
printf("ATTACK ");
for(i=0;i<nin-1;i++)printf("%9d ",player[i].atk);
printf("%9d\n",player[nin-1].atk);
printf(" SPEED ");
for(i=0;i<nin-1;i++)printf("%9d ",player[i].spd);
printf("%9d\n",player[nin-1].spd);
}
printf("\n");
}
void save()
{
int i,test;
char str[100];
FILE *fp;
printf("[セーブ画面]\n");
if(flgState!=1){
printf("セーブできませんでした(ステータスが入力されてません)\n\n");
return;
}
printf("ファイル名を入力してください\n");
scanf("%s",str);
fp=fopen(str,"wb"); //バイナリ形式での書き込み
fwrite(&nin,sizeof(int),1,fp);
for(i=0;i<nin;i++){
fwrite(player[i].name,sizeof(player[i].name),1,fp);
fwrite(&player[i].hp,sizeof(int),1,fp);
fwrite(&player[i].atk,sizeof(int),1,fp);
fwrite(&player[i].spd,sizeof(int),1,fp);
}
fclose(fp);
printf("セーブしました\n\n");
}
void load()
{
int i;
char str[100];
FILE *fp;
printf("[ロード画面]\n");
printf("ファイル名を入力してください\n");
scanf("%s",str);
fp=fopen(str,"rb"); //バイナリ形式での読み込み
fread(&nin,sizeof(int),1,fp);
for(i=0;i<nin;i++){
fread(player[i].name,sizeof(player[i].name),1,fp);
fread(&player[i].hp,sizeof(int),1,fp);
fread(&player[i].atk,sizeof(int),1,fp);
fread(&player[i].spd,sizeof(int),1,fp);
}
fclose(fp);
printf("ロードしました\n\n");
}
/*
1.対戦形式
1.戦闘開始(NAMEやHPが表示される)
2.キャラクタが一人ランダムに選ばれる(spdの高いキャラクタが選ばれやすい)
3.選ばれたキャラクタが他のキャラクタに攻撃
他のキャラクタは 選ばれたキャラクタのatk だけダメージを受ける
他のキャラクタのHP = 他のキャラクタのHP - 選ばれたキャラクタのatk
4.繰り返す
5.一人以外HPが0になったら終了
2.キャラクタの選択方法
例として、1,2,3番目のキャラクタの素早さspdを10,20,30の場合を考える。
spdTotalには10+20+30=60の値が入り、
擬似乱数のとりうる範囲は0~59となる。
このうち、
0~ 9 なら 1番目のキャラクタ
10~29 なら 2番目のキャラクタ
30~59 なら 3番目のキャラクタ
となる。
すなわち、素早さspdが高いほど、そのキャラクタのターンの確率が高くなる。
この例では
1番目のキャラクタのターンとなる確率=10/60
2番目のキャラクタのターンとなる確率=20/60
3番目のキャラクタのターンとなる確率=30/60
*/
/*
1.実際に動かすとこんな感じ(ステータス入力→セーブ→戦闘実行)
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
0
[ステータス入力画面]
作成するプレイヤーの数を決めてください(1-10)
5
プレイヤー1のステータスを設定してください
NAME:Reimu
HP:75
ATTACK:15
SPEED:65
プレイヤー2のステータスを設定してください
NAME:Marisa
HP:30
ATTACK:25
SPEED:35
プレイヤー3のステータスを設定してください
NAME:Mokou
HP:100
ATTACK:12
SPEED:30
プレイヤー4のステータスを設定してください
NAME:Aya
HP:50
ATTACK:10
SPEED:100
プレイヤー5のステータスを設定してください
NAME:Utsuho
HP:1
ATTACK:100
SPEED:1
作成したプレイヤーの確認を行います
NAME Reimu Marisa Mokou Aya Utsuho
HP 75 30 100 50 1
ATTACK 15 25 12 10 100
SPEED 65 35 30 100 1
この設定でよろしいですか?(Y/N)
y
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
2
[セーブ画面]
ファイル名を入力してください
savefile.save
セーブしました
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
1
[戦闘実行画面]
NAME Reimu Marisa Mokou Aya Utsuho
HP 75 30 100 50 1
ATTACK 15 25 12 10 100
SPEED 65 35 30 100 1
1回目 0:続行 1:終了
0
Ayaのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 65 20 90 50 0
2回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 65 5 75 35 0
3回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 65 0 60 20 0
4回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 65 0 45 5 0
5回目 0:続行 1:終了
0
Ayaのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 55 0 35 5 0
6回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 55 0 20 0 0
7回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 55 0 5 0 0
8回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 55 0 0 0 0
Reimuの勝利
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
4
続行するには何かキーを押してください . . .
2.実際に動かすとこんな感じ(ロード→戦闘実行)
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
3
[ロード画面]
ファイル名を入力してください
savefile.save
ロードしました
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
1
[戦闘実行画面]
NAME Reimu Marisa Mokou Aya Utsuho
HP 75 30 100 50 1
ATTACK 15 25 12 10 100
SPEED 65 35 30 100 1
1回目 0:続行 1:終了
0
Marisaのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 50 30 75 25 0
2回目 0:続行 1:終了
0
Mokouのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 38 18 75 13 0
3回目 0:続行 1:終了
0
Mokouのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 26 6 75 1 0
4回目 0:続行 1:終了
0
Mokouのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 14 0 75 0 0
5回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 14 0 60 0 0
6回目 0:続行 1:終了
0
Mokouのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 2 0 60 0 0
7回目 0:続行 1:終了
0
Reimuのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 2 0 45 0 0
8回目 0:続行 1:終了
0
Mokouのターン
NAME Reimu Marisa Mokou Aya Utsuho
HP 0 0 45 0 0
Mokouの勝利
[メニュー画面]
0:ステータス入力 1:戦闘実行 2:セーブ 3:ロード 4:ゲームの終了
4
続行するには何かキーを押してください . . .
*/