CSV読み込みについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
イマダニ
記事: 145
登録日時: 7年前

CSV読み込みについて

#1

投稿記事 by イマダニ » 7年前

二ヶ月前にこんな質問をしたものです。

アクションゲームにおける敵キャラとマップの管理
http://dixq.net/forum/viewtopic.php?f=3&t=11517

C#勉強とマップエディタ作りの息抜きに軽くリンゴ拾いゲームを作り、
この際だからCSVについての勉強もついでにやっちゃおうと思い、
落ちてくるリンゴをCSVで管理する試みをしました。
今回読み込みたいCSVの中身はこんな感じです。

/カウンタ,種類,x座標,y座標,y加速度
/cnt,knd,x座標,y座標,vy
100,0,124,10,5
110,0,300,20,5
120,0,480,10,5
130,0,100,15,5
140,0,230,13,5
150,0,550,7,5
160,0,340,10,5
170,0,80,15,5
180,0,100,25,5
190,0,440,22,5

そしてこれを読み込もうと試みたソースコードがこちら

コード:

#include "DxLib.h"
#include "Key.h"
#include "apple.h"

int aimg[2];//リンゴ画像変数
int backimg1,backimg2;//背景画像変数
int stage_count=1;//ゲーム全体のカウント。今の所リンゴ関係でしか使わないのでとりあえずここに

//画像ロード関数
void aload(){
	LoadDivGraph("img/apple.png",2,2,1,31,31,aimg);
	backimg1=LoadGraph("img/haikei1.bmp");
	backimg2=LoadGraph("img/haikei2.png");
}

//ゲームカウントなどの計算関数
void aculc(){
	stage_count++;
}

//csv読み込み関数。よくわからないのでとりあえず龍神録のをまんま真似しました。
void aload_story(A_FILE a_file[APPLE_ORDER_MAX]){
	int n,num,i,fp;
	char fname[32]={"dat/リンゴ.csv"};
	int input[64];
	char inputc[64];

	fp=FileRead_open(fname);
	if(fp==NULL){
		printfDx("read error\n");
		return;
	}
	for(i=0;i<2;i++)
		while(FileRead_getc(fp)!='\n');

	n=0,num=0;
	while(1){
		for(i=0;i<64;i++){
			inputc[i]=input[i]=FileRead_getc(fp);
			if(inputc[i]=='/'){
				while(FileRead_getc(fp)!='\n');
				i=-1;
				continue;
			}
			if(input[i]==','||input[i]=='\n'){
				inputc[i]='\0';
				break;
			}
			if(input[i]==EOF){
				goto EXFILE;//終了
			}
		}
		switch(num){
			case 0: a_file[n].cnt =atoi(inputc);break;
			case 1: a_file[n].knd =atoi(inputc);break;
			case 2: a_file[n].x   =atoi(inputc);break;
			case 3: a_file[n].y   =atoi(inputc);break;
			case 4: a_file[n].vy  =atoi(inputc);break;
		}
		num++;
		if(num==5){
			num=0;
			n++;
		}
	}
EXFILE:
	FileRead_close(fp);
}

//からっぽなリンゴ検索関数
int apple_num_search(){
	APPLE apple[APPLE_MAX];
	for(int i=0;i<APPLE_MAX;i++){
		if(apple[i].flag==false){
			return i;
		}
	}
	return -1;
}

//読み込んだ数値をリンゴに代入する関数。
void aenter(APPLE apple[APPLE_MAX],A_FILE a_file[APPLE_ORDER_MAX]){
	int i,j;
	for(j=0;j<APPLE_ORDER_MAX;j++){
		if(a_file[j].cnt==stage_count){
			if((i=apple_num_search())!=-1){
				apple[i].cnt     =0;
				apple[i].flag    =true;
				apple[i].dropflag=true;
				apple[i].x       =a_file[j].x;
				apple[i].y       =a_file[j].y;
				apple[i].vy		 =a_file[j].vy;
				apple[i].vx		 =0;
				apple[i].knd	 =a_file[j].knd;
			}
		}
	}
}

//リンゴの動き
void amove(APPLE apple[APPLE_MAX]){    
	for(int i=0;i<APPLE_MAX;i++){
		if(apple[i].dropflag==true){//dropflagが建ったら
			apple[i].y+=apple[i].vy;//5下へ加速
		}
	}
}

//リンゴ描画関数
void agraph(APPLE apple[APPLE_MAX]){
	for(int i=0;i<APPLE_MAX;i++){
		if(apple[i].flag==true){
			DrawRotaGraphF(apple[i].x,apple[i].y,1.0f,0.0f,aimg[apple[i].knd],TRUE);
		}
	}
}
で、特に問題なくコンパイルできたのですが、

リンゴがいつまでたっても現れません。

これはCSVファイルを読み込めてないのでしょうか?
アドバイスお願いします。

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: CSV読み込みについて

#2

投稿記事 by dic » 7年前

ブレークポイントを設定して、
値が読み込めているのか?
動作しているのか?
描画されているのか?
この3つを調べればいいと思います
60行目
104行目
113行目
です

イマダニ
記事: 145
登録日時: 7年前

Re: CSV読み込みについて

#3

投稿記事 by イマダニ » 7年前

返信ありがとうございます!
さっそく、ブレークポイント設置して、デバッグをしてみました
呼び出し履歴のところを見ればいいんですよね?
まず60行目はこう出ました。

・60行目
> ringo-.exe!aload_story(A_FILE * a_file=0x0023a4b8) 行 60 C++
ringo-.exe!WinMain(HINSTANCE__ * hInstance=0x00800000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00253ebe, int nCmdshow=1) 行 25 + 0xc バイト C++
ringo-.exe!__tmainCRTStartup() 行 263 + 0x2c バイト C
ringo-.exe!WinMainCRTStartup() 行 182 C
kernel32.dll!7632ed6c()
[下のフレームは間違っているか、または見つかりません。kernel32.dll に対して読み込まれたシンボルはありません。]
ntdll.dll!7774377b()
ntdll.dll!7774374e()


起動したウィンドウは真っ暗でした。

そして104と113は呼び出し履歴には特に何も出ず、普通にリンゴが落ちてこないキャラが横に動くだけのゲームがコンパイルされました。
60行目に異常があるのはわかるんですが、呼び出し履歴に書かれている意味がわかりません……
どういう意味なんでしょうかこれ?

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: CSV読み込みについて

#4

投稿記事 by dic » 7年前

呼び出し履歴を見てもあまり意味はないです
ウォッチ で変数の中身を確認してください

画像がサンプルで 変数 a, b は初期化していますが
変数 c は初期化していないので、未知の数が入っています

あと、画像がよみこまれているか、画面内にリンゴの座標はあるかですね
確認するのは
添付ファイル
WS000016.JPG

イマダニ
記事: 145
登録日時: 7年前

Re: CSV読み込みについて

#5

投稿記事 by イマダニ » 7年前

ウォッチに何も出ない……

デバッグ、ウィンドウ、のウォッチ1でいいんですよね?

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: CSV読み込みについて

#6

投稿記事 by dic » 7年前

ウォッチの名前のところをクリックして
みたい変数の名前を入力してください

イマダニ
記事: 145
登録日時: 7年前

Re: CSV読み込みについて

#7

投稿記事 by イマダニ » 7年前

できました!

60行目
num 0 int
a_file[n].cnt 100 int
a_file[n].y -9.2559631349317831e+061 double
a_file[n].knd -858993460 int
a_file[n].vy -9.2559631349317831e+061 double
a_file[n].x -9.2559631349317831e+061 double

なんかカウント以外とんでもない数値が入っちゃってます

わふ

Re: CSV読み込みについて

#8

投稿記事 by わふ » 7年前

いまどきは
strtok()
は使わないんですかね? トークン分解は便利なんですけど。

イマダニ
記事: 145
登録日時: 7年前

Re: CSV読み込みについて

#9

投稿記事 by イマダニ » 7年前

いろいろ試行錯誤した結果、

コード:

//使われてないリンゴ検索関数
int apple_num_search(){
	APPLE apple[APPLE_MAX];
	for(int i=0;i<APPLE_MAX;i++){
		if(apple[i].flag==false){
			return i;
		}
	}
	return -1;
}

//読み込んだ数値をリンゴに代入する関数。
void aenter(APPLE apple[APPLE_MAX],A_FILE a_file[APPLE_ORDER_MAX]){
	int i,j;
	for(j=0;j<APPLE_ORDER_MAX;j++){
		if(a_file[j].cnt==stage_count){
			printf("a_file[j].cnt=%d\n",a_file[j].cnt);
			printf("stage_count=%d\n",stage_count);
			if((i=apple_num_search())!=-1){
				apple[i].cnt	 =0;
				apple[i].flag    =true;
				apple[i].dropflag=true;
				apple[i].x       =a_file[j].x;
				apple[i].y       =a_file[j].y;
				apple[i].vy		 =a_file[j].vy;
				apple[i].vx		 =0;
				apple[i].knd	 =a_file[j].knd;
			}			
		}
	}
}
この部分でapple各メンバに読み込んだデータが代入されてないことがわかりました。
それでstagecountとa_file[j].cntがおかしいのかなと思い、printfで表記してみました。
すると

stagecount=100;
a_file[j].cnt=100;
stagecount=110;
a_file[j].cnt=110;
stagecount=120;
a_file[j].cnt=120;
stagecount=130;
a_file[j].cnt=130;

とエクセル通りに動いていました。
でもなぜか

コード:

void agraph(APPLE apple[APPLE_MAX]){
	for(int i=0;i<APPLE_MAX;i++){
		if(apple[i].flag==true){
			DrawRotaGraphF(apple[i].x,apple[i].y,1.0f,0.0f,aimg[apple[i].knd],TRUE);
		}
	}
	for(int i=0;i<APPLE_MAX;i++){
			printf("apple[i].flag=%d\n",apple[i].flag);
			printf("apple[i].y=%f\n",apple[i].y);
	}
}
代入関数の後に書かれている描画関数で各変数の中身を確認したところ
apple.flag=0;
apple.y=0.000000

とどれも代入されておらず、memsetで初期化された状態でした。
なにがいけないんでしょう?
int apple_num_search()ですかね?
でもint apple_num_search()に特に問題はないし……
メインに問題があるんでしょうか?

コード:

#include "DxLib.h"
#include "Key.h"
#include "play.h"
#include "apple.h"

int func_state;

int ProcessLoop(){
	if(ProcessMessage()!=0) return -1;
	if(ClearDrawScreen()!=0) return -1;
	UpdateKey();
	return 0;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdshow){
	
	AllocConsole();
	freopen("CONOUT$", "w", stdout); //標準出力をコンソールにする
	printf( "これでprintfが使えます\n" );   //←お試し用 
	
	ChangeWindowMode(TRUE),DxLib_Init(),SetDrawScreen(DX_SCREEN_BACK);

	PLAY play;
	APPLE apple[APPLE_MAX];
	A_FILE a_file[APPLE_ORDER_MAX];

	while(ProcessLoop()==0){
		switch(func_state){
			case 0:
				pload(&play);//プレイヤー画像
				aload();//リンゴ画像
				func_state=99;
				break;
			case 99:
				pini(&play);//playをmemsetで初期化
				aini(apple,a_file);//appleとa_fileをmemsetで初期化
				aload_story(a_file);//excel読み込み
				func_state=100;
				break;
			case 100:
				pmove(&play);//プレイヤーの移動制御
				aenter(apple,a_file);//エクセルをapple各メンバに代入
				amove(apple);//リンゴの移動制御
				hgraph_back();//背景描画
				pgraph(play);//プレイヤー描画
				agraph(apple);//りんご描画
				hgraph_mae();//背景描画
				aculc();//stage_countインクリメント
				break;
			default:
				printfDx("不明なfunc_state");
				break;
		}

		if(CheckKey(KEY_INPUT_ESCAPE)==1)break;
		ScreenFlip();
	}

	DxLib_End();
	return 0;
}
アドバイスお願いします

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: CSV読み込みについて

#10

投稿記事 by dic » 7年前

コード:

            printf("a_file[j].cnt=%d\n",a_file[j].cnt);
            printf("stage_count=%d\n",stage_count);
            if((i=apple_num_search())!=-1){
                apple[i].cnt     =0;
printf で表示した とありますが 表示しているのはa_file[j] です
「 j 」 です
したの代入するときは 「 i 」 ですが、大丈夫ですか?

また、「 i 」が APPLE_MAX の範囲内の値でしょうか?
確認してみてください

dic
記事: 582
登録日時: 9年前
住所: 宮崎県

Re: CSV読み込みについて

#11

投稿記事 by dic » 7年前

あと

コード:

//使われてないリンゴ検索関数
int apple_num_search(){
    APPLE apple[APPLE_MAX];
    for(int i=0;i<APPLE_MAX;i++){
        if(apple[i].flag==false){
            return i;
        }
    }
    return -1;
}
ここの関数では、初期化されていない変数 APPLE apple[APPLE_MAX] が参照されています


推測すると以下のような使い方がいいのではないのでしょうか

コード:

//使われてないリンゴ検索関数
int apple_num_search( APPLE apple[APPLE_MAX] ){
    for(int i=0;i<APPLE_MAX;i++){
        if(apple[i].flag==false){
            return i;
        }
    }
    return -1;
}

// 追加
あと、No1 の記事の90行目あたりにブレークポイントを設定して
そのブレークポイントでとまるか確認してみてください

イマダニ
記事: 145
登録日時: 7年前

Re: CSV読み込みについて

#12

投稿記事 by イマダニ » 7年前

コード:

//使われてないリンゴ検索関数
int apple_num_search(APPLE apple[APPLE_MAX]){
	for(int i=0;i<APPLE_MAX;i++){
		if(apple[i].flag==false){
			return i;
		}
	}
	return -1;
}

//読み込んだ数値をリンゴに代入する関数。
void aenter(APPLE apple[APPLE_MAX],A_FILE a_file[APPLE_ORDER_MAX]){
	int i,j;
	for(j=0;j<APPLE_ORDER_MAX;j++){
		if(a_file[j].cnt==stage_count){
			if((i=apple_num_search(apple))!=-1){
				apple[i].cnt	 =0;
				apple[i].flag    =true;
				apple[i].dropflag=true;
				apple[i].x       =a_file[j].x;
				apple[i].y       =a_file[j].y;
				apple[i].vy		 =a_file[j].vy;
				apple[i].vx		 =0;
				apple[i].knd	 =a_file[j].knd;
			}
		}
	}
}
としたらリンゴが降ってきました!dicさんの言うとおりです!
引数のところに書かないで、関数の中に書いたから、同じ名前だけど違う構造体を新しく宣言しちゃってたんですね。
結局、なにがいけなかったのか自力でつきとめることはできませんでしたが、
dicさんのおかげでデバッグの使い方とその重要性が学べました。いままで使ってなかったのが恥ずかしい……
ありがとうございました!

イマダニ
記事: 145
登録日時: 7年前

Re: CSV読み込みについて

#13

投稿記事 by イマダニ » 7年前

解決にチェックマークをいれ忘れました……
すいません!

閉鎖

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