レベルアップ関数

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あるちゃん

レベルアップ関数

#1

投稿記事 by あるちゃん » 9年前

標準のC言語で、経験値をためてレベルアップをし、
さらにステータスの初期値が変わるという関数を作っています。

各レベルの初期値を二次元配列にしたり、経験値・レベルをグローバル関数にしたりしましたが、上手くいかず煮詰まっています。
あと、どの作例でも、レベル2や3から始まったり
一定以上達すると、レベルが急降下したり、二段飛ばしでレベルが上がったりするなどの
問題があります;;

玄人の皆さんに申し訳ありませんが、よろしければお知恵を拝借いただけますよう、よろしくお願いします。

↓ 作例 1 初期パラメータを switch()で切替え。経験値、レベルとグローバルに。

コード:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

#define MAX_LEVEL 3  //とりあえず試作なので「レベル3」を最大に

typedef struct character  //キャラクタのパラメータを構造化 (もっと増やしたい)
{
	int hp;
	int max_hp;
}character;

character init_player[];
character player;

int levelup[]={0, 50, 100}; // レベルアップに必要な経験値

int exp=0;  //グローバルにした経験値変数

int level=0;  //初期レベル「0」

int lvup=1;


void main(void)
{
	player = init_player[]={100, 100};
	while(1){
		printf("現体力 : %d, 最大体力 : %d, 経験値 : %d, レベル : %d\n", player.hp, player.max_hp, exp, level);
	getch();
	exp += 10;
		if(exp>=levelup[level]){
			level = level+lvup; //レベルが上がる処理が、単純に「1」足してもなぜか上手くいかない?

			switch(level)
			{
			case 1: init_player[]={100,100}; //「式が必要です」というエラーが出ます
				break;

			case 2: init_player[]={200, 200};
				break;

			case 3: init_player[]={300, 300}
					break;
			}
		}
	}
}




↓ 作例2 作例1と比べて、switch()を使わずに、各レベルの初期パラメータを二次元配列にしています

コード:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

#define MAX_LEVEL 3 //試作なので、とりあえず最大レベルは「3」(どこに設置すればいいのか分からない・・・)

typedef struct character  //キャラクタのパラメータを構造化 現在HPと最大HP
{
	int hp;
	int max_hp;
}character;

character init_player[3][2] = {{100, 100}, //各レベルのパラメータを二次元配列に
			       {200, 200},
			       {300, 300},};


character player;

int levelup[]={0, 50, 100,}; //レベルアップに必要な経験値

int exp=0; //グローバル化された経験値

int level=1; //初期レベル

int lvup=1;


void main(void)
{
			player = init_player[level-2][2];
	while(1){
		printf("現体力 : %d, 最大体力 : %d, 経験値 : %d, レベル : %d\n", player.hp, player.max_hp, exp, level);
	getch();
	exp += 10;
		if(exp>=levelup[level]){
			level = level;
			printf("レベルが %d に上がった\n", level);
			player = init_player[level-1][2];      //配列で[1]を入れると、実質2番目なので、あえて1引いたり・・・
		}
	}
}

↓ 作例3 

コード:


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

#define MAX_LEVEL 6

typedef struct character  //今回は経験値、レベル、なども構造体の中に
{
	int hp;
	int max_hp;
	int exp;
	int level;
	int lvup;
}character;

character init_player[][4]={{100, 100, 0, 1, 0},    //二次元配列にした各レベルの初期パラメータ
						 {200, 200, 0, 1, 1},
						 {300, 300, 0, 2, 1},
						 {400, 400, 0, 3, 1},
						 {500, 500, 0, 4, 1},
						 {600, 600, 0, 5, 1},
						};

character player = init_player[player.level-1][4];

int levelup[MAX_LEVEL]={0, 50, 100, 150, 150, 200}; //レベルアップに必要な経験値

int main(void)
{
	while(1){
		printf("現体力 : %d, 最大体力 : %d, 経験値 : %d, レベル : %d\n", player.hp, player.max_hp, player.exp, player.level);
	getch();
	player.exp += 10;
		if(player.exp>=levelup[player.level]){
			player.level = player.level + player.lvup;
			printf("レベルが %d に上がった\n", player.level-1);
					player = init_player[player.level-1][4];
      
     //レベルの上がり方が急激だったり、思うようにならなかったり、色々ごちゃごちゃいじくってしまいました;;
		}
	}
}


box
記事: 2002
登録日時: 14年前

Re: レベルアップ関数

#2

投稿記事 by box » 9年前

とりあえず、
 ・コードのよけいな箇所に入っている全角空白を取り除いて、回答しようとする側で
  何も手を加えなくても動作検証ができる状態にする
 ・字下げが乱れていて読みづらい箇所を適切に修正する
このあたりを直して再提出、というところでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

Yv

Re: レベルアップ関数

#3

投稿記事 by Yv » 9年前

こんにちは
例が多くあり混乱されているようですが,問題を整理すると

経験値を足す→レベルを上げる→初期値ステータスを変更する

という、3つの手続きを連続して行うケースです。冷静に考えればそれほど難しくないはずです。
値を保存するデータ構造(配列)と,そのデータを操作する処理を分けて考えましょう
あと配列の扱いが怪しそうなので単純にしてみてください。二次元配列は結構厄介です。

1. 経験値を足す処理は,変数の値を増やすだけです。
2. レベルを上げる処理は,現在の経験値を読み込み、その値を基に適切なレベルを計算して設定します。
3. 初期ステータスを上げる処理は,現在のレベルを読み込み,その値を基に適切な初期ステータスを登録します
これを順番に並べれば大まかな流れができます

コード:

int main()
{
    while(1){
        AddExp();
        SetLevel();
        SetInitParam(); 
        printf(...);
    }
}
あとはその中を"正しく"動作するように実装していく作業になります。
SetLevelの中ではexp変数の数値を変える必要がない、ということを意識して
仕事を分担させてみてください

---
実際は、初期値の変更はレベルが上がった瞬間に一度だけ行うはずの処理です。
その場合の骨格は

コード:

int main()
{
    while(1){
        AddExp();
        if(LevelUp()){
            SetInitParam(); 
        }
        printf(...);
    }
}
とするのかもしれません(個人の自由なので)
LevelUpはレベルが上がった瞬間だけtrueを返すような処理にします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: レベルアップ関数

#4

投稿記事 by みけCAT » 9年前

あるちゃん さんが書きました:標準のC言語で
  • conio.hは標準(N1256)のC言語にはありません。
  • エントリポイントをvoid main(void)とするのは標準のC言語には無く、implementation-definedです。
  • (//を用いたコメントはC99では使えますが、C89では使えません)
作例1について
  • expという名前はeのx乗を求める関数と被るのであまりよくないです。(これは作例2でも同じです)
  • init_player[] = {100, 100};という書き方は無効です。player = {100, 100};も無効です。1個ずつ代入するといいでしょう。
  • 配列の確保された範囲の外にはアクセスしてはいけません。範囲外になっていないかのチェックをつけましょう。
  • init_playerの用途がよくわからなかったので、とりあえず消しました。

コード:

#include<stdio.h>
#include<stdlib.h>

#define MAX_LEVEL 3  //とりあえず試作なので「レベル3」を最大に

typedef struct character   //キャラクタのパラメータを構造化  (もっと増やしたい)
{
	int hp;
	int max_hp;
}character;

character player;

int levelup[]={0, 50, 100};  // レベルアップに必要な経験値

int ex=0;    //グローバルにした経験値変数

int level=0;   //初期レベル「0」

int lvup=1;


int main(void)
{
	player.hp = 100;
	player.max_hp = 100;
	while(1){
		printf("現体力 : %d, 最大体力 : %d, 経験値 : %d, レベル : %d\n", player.hp, player.max_hp, ex, level);
		getchar();
		ex += 10;
		if(level<MAX_LEVEL && ex>=levelup[level]){
			level = level+lvup;

			switch(level)
			{
			case 1:
				player.hp = 100;
				player.max_hp = 100;
				break;

			case 2:
				player.hp = 200;
				player.max_hp = 200;
				break;

			case 3:
				player.hp = 300;
				player.max_hp = 300;
				break;
			}
		}
	}
	// 無限ループなので、ここに処理は来ない。よってreturnは省略する
}
作例2について
  • characterの二次元配列を用いるのであれば、それぞれの要素はcharacter型でなければならない。
    今回は二次元配列ではなく、一次元配列にするべきである。
  • level = 1のときlevel - 2は-1なので、最初のinit_player[level - 2]は範囲外であり、アクセスしてはいけない。
  • init_player[3][2]と宣言されている時、init_player[level - 1][2]は配列の範囲外であり、アクセスしてはいけない。
  • 作例1と同様に、levelup[level]が範囲外でないかのチェックが必要である。
  • 同じ型の構造体変数同士は直接代入できる。

コード:

#include<stdio.h>
#include<stdlib.h>

#define MAX_LEVEL 3  //試作なので、とりあえず最大レベルは「3」(どこに設置すればいいのか分からない・・・)

typedef struct character   //キャラクタのパラメータを構造化  現在HPと最大HP
{
	int hp;
	int max_hp;
}character;

character init_player[3] = {  //各レベルのパラメータを配列に
	{100, 100},
	{200, 200},
	{300, 300}
};


character player;

int levelup[]={0, 50, 100};  //レベルアップに必要な経験値

int ex=0;  //グローバル化された経験値

int level=1;  //初期レベル

int lvup=1;


int main(void)
{
	player = init_player[level-1];
	while(1){
		printf("現体力 : %d, 最大体力 : %d, 経験値 : %d, レベル : %d\n", player.hp, player.max_hp, ex, level);
		getchar();
		ex += 10;
		if(level<MAX_LEVEL && ex>=levelup[level]){
			level = level + 1;
			printf("レベルが %d に上がった\n", level);
			player = init_player[level-1];            //配列で[1]を入れると、実質2番目なので、あえて1引いたり・・・
		}
	}
	// 無限ループでここに処理は来ないので、returnは省略
}
作例3について
  • init_playerの定義が作例2と同様に不適切である。
  • playerの宣言時の初期化はcompile-time constantである必要があり、init_playerの要素の値は使えないようだ。
  • characterのメンバのexpは、標準関数と明確に区別できるので問題ない。
  • 初期状態のplayer.lvupが0だと、必要な経験値を貯めてもレベルが上がらない。
  • この構造では、init_player[n].lvup==1のとき、init_player[n].level == n+1になっていないとおかしくなってしまう。
  • 今までと同様に、levelup[player.level]が範囲外でないかのチェックが必要である。
  • 「レベルがnに上がった」と表示する時、わざわざ本当のレベル-1を表示するべきではない。
  • この実装だと作例1、作例2と違ってレベルが上がる時に経験値が0(init_playerで指定した値)になってしまうが、これは意図した仕様か?

コード:

#include<stdio.h>
#include<stdlib.h>

#define MAX_LEVEL 6

typedef struct character   //今回は経験値、レベル、なども構造体の中に
{
	int hp;
	int max_hp;
	int exp;
	int level;
	int lvup;
}character;

character init_player[]={        //配列にした各レベルの初期パラメータ
	{100, 100, 0, 1, 1},
	{200, 200, 0, 2, 1},
	{300, 300, 0, 3, 1},
	{400, 400, 0, 4, 1},
	{500, 500, 0, 5, 1},
	{600, 600, 0, 6, 1}
};

character player = {100, 100, 0, 1, 1};

int levelup[MAX_LEVEL]={0, 50, 100, 150, 150, 200};  //レベルアップに必要な経験値

int main(void)
{
	while(1){
		printf("現体力 : %d, 最大体力 : %d, 経験値 : %d, レベル : %d\n", player.hp, player.max_hp, player.exp, player.level);
		getchar();
		player.exp += 10;
		if(player.level<MAX_LEVEL && player.exp>=levelup[player.level]){
			player.level = player.level + player.lvup;
			printf("レベルが %d に上がった\n", player.level);
			player = init_player[player.level-1];
		}
	}
	// 無限ループによりここに制御は来ないので、returnは省略する
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

あるちゃん

Re: レベルアップ関数

#5

投稿記事 by あるちゃん » 9年前

返事が遅くなりました。
皆様の懇志御丁寧な解説のおかげで、無事レベルアップ関数を実装することができました。
これで得たことを糧に、製作物の完成を目指します。
ありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る