【龍神録】スコアソートプログラム

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

【龍神録】スコアソートプログラム

#1

投稿記事 by アメヒルネ » 6年前

お久しぶりです。アメヒルネという者です。

今現在、STGのスコアソートに関して、大変悩んでおります。
と、いうのも、コードだけでは自分ではどこが間違っているかわからないのに、思った通りの動作をしてくれないのです。
以下から、具体的にお話しします。長くなりますがご了承ください。

今回質問したいのは、タイトルの通り、「スコアソート」です。
(というのも、ハイスコアの更新とかそのあたりもですが…汗)

≪やりたいこと≫
・ハイスコアを4機体分に分けて登録する。必要があれば、ゲーム終了のたびに更新する
・機体総合で、ハイスコアとキャラネーム(東方でいう、自由に名前を記入できるアレ)を表示する。
 必要があれば、ゲーム終了時に更新する。
≪問題≫
ハイスコアもスコアソートも更新されない。

簡潔にまとめてみた物が、これです。
以下、関連のあるソースコードになります。

↓main.cpp

コード:

	//前略
		case 101://ポーズ画面処理
				pause();
				break;

			case 102://未実装のゲームオーバー画面操作
				graph_main();
				continue_game();
				break;

			case 103://リザルト表示
				graph_main();
				d_result();
				break;

			case 104://未実装のステージ移行操作
				stage_count=0;
				stage++;
				func_state=100;
				break;

			case 110://メニュー画面前の処理
				loading();
				delete_bgm();
				ini();	
				hiscore_write();
				func_state=19;
				if (sort_rec()!=-1)	func_state=130;
				break;

			case 130://スコアネーム入力画面
				nameinput();
				break;

			case 999://終了前のファイル出力。増やす可能性大
				hiscore_write();
				func_state=1000;
				break;
↓result.cpp

コード:

    //前略
void write_new_score(){

	FILE *fp;
	int hash;

	fp = fopen( "score/hiscore.dat" , "wb+" );			//hiscore.datを新規作成する

	for(int i=0;i<CHAR_KIND_MAX;i++){
		fprintf(fp,"%d\n",100000);				//4機分全てにハイスコア「100000」を登録
	}

	hash=400000%HASH;
	fprintf(fp,"%d\n",hash);

	fclose(fp);

}

int read_score(){

	FILE *fp;
	int hash,scanscore;

	all=0;

	fp = fopen( "score/hiscore.dat" , "rb" );				//4機体分のハイスコア登録
	
	for(int j=0;j<CHAR_KIND_MAX;j++){
		fscanf(fp,"%d",&scanscore);
		hiscore[j] = scanscore;
		all += hiscore[j];
	}

	fscanf(fp,"%d",&hash);

	fclose(fp);

	return hash;

}

void score_ini(){

	//ハイスコアを登録する
	int hash=0,truehash=0;
	FILE *fp;
	FILE *fps;

	if( ( fp = fopen( "score/hiscore.dat","rb"))==NULL){	//hiscore.datが見つからなかった場合
		write_new_score();
	}

	hash = read_score();

	truehash = all%HASH;

	if(truehash!=hash){
		write_new_score();
		read_score();
	}

	//レコードを登録する

	if( ( fps = fopen( filename, "rb") ) == NULL )	{
		for(int i=0;i<10;i++){
			rec_score[i].hiscore = 100000;
			sprintf( rec_score[i].name, "ナナシのシューター" );
		}
	}
	else{
		fread( &rec_score, sizeof(rec_score), 1, fps);
		fclose( fps );
	}

}

void hiscore_write(){

	FILE *fp;
	FILE *fps;

	//ハイスコアの書き出し
	int all=0,hash;

	for(int i=0;i<CHAR_KIND_MAX;i++){
		if(i==use_char){
			if(hiscore[i] < ch.hiscore)	hiscore[i]=ch.hiscore;
		}
	}

	fp = fopen( "score/hiscore.dat" , "wb" );
	for(int j=0;j<CHAR_KIND_MAX;j++){
		fprintf(fp,"%d\n",hiscore[j]);
		all+=hiscore[j];
	}

	hash=all%HASH;
	fprintf(fp,"%d\n",hash);

	fclose(fp);

	//レコード書き出し
	sort_rec();
	fps = fopen( filename, "wb");
	fwrite( &rec_score, sizeof(rec_score), 1, fps);
	fclose( fps );

}

int sort_rec(){

	int j;

	for(int i=0;i<10;i++){
		if( ch.hiscore>rec_score[i].hiscore ){
			for(j=9;j<i;j--){
				rec_score[j].chara_num	= rec_score[j-1].chara_num;
				rec_score[j].hiscore	= rec_score[j-1].hiscore;
				sprintf( rec_score[j-1].name, "%s", rec_score[j].name);
			}
			rec_score[i].chara_num	= use_char;
			rec_score[i].hiscore	= ch.hiscore;
			sprintf( rec_score[i].name, "%s",char_name);
			return i;
		}
	}

	return -1;

}
なにかご不明な点がありましたら、連絡お願いいたします。

アバター
amehirune
記事: 181
登録日時: 7年前
住所: どっか
連絡を取る:

Re: 【龍神録】スコアソートプログラム

#2

投稿記事 by amehirune » 6年前

失礼しました。
先ほどはログインができてない様子でしたので、そのまま投稿してしまいました…。

このトピックは、私が立てました。
ほら、来いよ!! 誤字や矛盾を指摘したい奴から、前に出てこいよぉおおおおおおおッ!!!
※都合により、不定期でしか現れません。即返などはできませんのでご了承ください※

初級者
記事: 200
登録日時: 10年前

Re: 【龍神録】スコアソートプログラム

#3

投稿記事 by 初級者 » 6年前

バイナリーモードでオープンしているファイルに対して
fscanf
fprintf
で読み書きしているところに
違和感を感じます。

アバター
ookami
記事: 214
登録日時: 10年前
住所: 東京都

Re: 【龍神録】スコアソートプログラム

#4

投稿記事 by ookami » 6年前

amehiruneさん、

1.
sort_rec関数の、
for(j=9;j<i;j--){

for(j=9;j>i;j--){
では?

2.
case 110://メニュー画面前の処理

hiscore_write();

if (sort_rec()!=-1) func_state=130;

となっていますが、hiscore_write関数の中でもsort_recを呼び出しているので、ch.hiscoreが2回ランクインしてしまう気がします。

アバター
amehirune
記事: 181
登録日時: 7年前
住所: どっか
連絡を取る:

Re: 【龍神録】スコアソートプログラム

#5

投稿記事 by amehirune » 6年前

返答ありがとうございます。
初級者 さんが書きました:バイナリーモードでオープンしているファイルに対して
fscanf
fprintf
で読み書きしているところに
違和感を感じます。
自分の学校で使っている教科書ではこのように解説してあったのでこの通りにしていました。
別にバイナリにする必要性も感じなくなったので、バイナリにはしないようにしました。
ookami さんが書きました:amehiruneさん、

1.
sort_rec関数の、
for(j=9;j<i;j--){

for(j=9;j>i;j--){
では?

2.
case 110://メニュー画面前の処理

hiscore_write();

if (sort_rec()!=-1) func_state=130;

となっていますが、hiscore_write関数の中でもsort_recを呼び出しているので、ch.hiscoreが2回ランクインしてしまう気がします。
ご指摘ありがとうございます。
修正いたしました。が、まだ更新されません。。。
ほら、来いよ!! 誤字や矛盾を指摘したい奴から、前に出てこいよぉおおおおおおおッ!!!
※都合により、不定期でしか現れません。即返などはできませんのでご了承ください※

アバター
amehirune
記事: 181
登録日時: 7年前
住所: どっか
連絡を取る:

Re: 【龍神録】スコアソートプログラム

#6

投稿記事 by amehirune » 6年前

menu.cppのini();で初期化されているのが原因だと考え、
呼び出す順番を変更したところ、
きちんと更新されるようにはなったのですが…。
今度は別のエラーが発生しました。

2回~3回分、なぜか一気に登録されるようになっています。
[hr]1:ナナシのシューター 10000点
2:ナナシのシューター 10000点
3:ナナシのシューター 10000点
4:ナナシのシューター 10000点
5:ナナシのシューター 10000点
6:ナナシのシューター 10000点
7:ナナシのシューター 10000点
8:ナナシのシューター 10000点
9:ナナシのシューター 10000点
10:ナナシのシューター 10000点[hr]
だったのが、「Test007」という名前で140000点を記録すると
[hr]1:Test007 140000点
2:Test007 140000点
3:ナナシのシューター 10000点
4:ナナシのシューター 10000点
5:ナナシのシューター 10000点
6:ナナシのシューター 10000点
7:ナナシのシューター 10000点
8:ナナシのシューター 10000点
9:ナナシのシューター 10000点
10:ナナシのシューター 10000点[hr]
となってしまいます。
ほら、来いよ!! 誤字や矛盾を指摘したい奴から、前に出てこいよぉおおおおおおおッ!!!
※都合により、不定期でしか現れません。即返などはできませんのでご了承ください※

アバター
ookami
記事: 214
登録日時: 10年前
住所: 東京都

Re: 【龍神録】スコアソートプログラム

#7

投稿記事 by ookami » 6年前

amehiruneさん、
前の返信で、
>>hiscore_write関数の中でもsort_recを呼び出しているので、ch.hiscoreが2回ランクインしてしまう気がします。
>修正いたしました。が、まだ更新されません。。。
⇒ここで修正したコードをアップしてください。単にランクインの処理を2回呼んでしまっているのだと思います。

アバター
amehirune
記事: 181
登録日時: 7年前
住所: どっか
連絡を取る:

Re: 【龍神録】スコアソートプログラム

#8

投稿記事 by amehirune » 6年前

↓main.cpp

コード:

			case 101://ポーズ画面処理
				pause();
				break;

			case 102://未実装のゲームオーバー画面操作
				graph_main();
				continue_game();
				break;

			case 103://リザルト表示
				graph_main();
				d_result();
				break;

			case 104://未実装のステージ移行操作
				stage_count=0;
				stage++;
				func_state=100;
				break;

			case 110://メニュー画面前の処理
				loading();
				delete_bgm();
				hiscore_write();
				score_ini();//ハイスコアの読み込み
				ini();				
				func_state=19;
				break;

			case 130://スコアネーム入力画面
				nameinput();
				break;

			case 999://終了前のファイル出力。増やす可能性大
				func_state=1000;
				break;

			default:
				printfDx("不明なfunc_state\n");
				break;
↓score.cpp

コード:

void write_new_score(){

	FILE *fp;
	int hash;

	fp = fopen( "score/hiscore.dat" , "w+" );			//hiscore.datを新規作成する

	for(int i=0;i<CHAR_KIND_MAX;i++){
		fprintf(fp,"%d\n",10000);				//4機分全てにハイスコア「100000」を登録
	}

	hash=40000%HASH;
	fprintf(fp,"%d\n",hash);

	fclose(fp);

}

int read_score(){

	FILE *fp;
	int hash,scanscore;

	all=0;

	fp = fopen( "score/hiscore.dat" , "r" );				//4機体分のハイスコア登録
	
	for(int j=0;j<CHAR_KIND_MAX;j++){
		fscanf(fp,"%d",&scanscore);
		hiscore[j] = scanscore;
		all += hiscore[j];
	}

	fscanf(fp,"%d",&hash);

	fclose(fp);

	return hash;

}

void score_ini(){

	//ハイスコアを登録する
	int hash=0,truehash=0;
	FILE *fp;
	FILE *fps;

	if( ( fp = fopen( "score/hiscore.dat","r"))==NULL){	//hiscore.datが見つからなかった場合
		write_new_score();
	}

	hash = read_score();

	truehash = all%HASH;

	if(truehash!=hash){
		write_new_score();
		read_score();
	}

	//レコードを登録する

	if( ( fps = fopen( filename, "r") ) == NULL )	{
		for(int i=0;i<10;i++){
			rec_score[i].hiscore = 10000;
			sprintf( rec_score[i].name, "ナナシのシューター" );
		}
	}
	else{
		fread( &rec_score, sizeof(rec_score), 1, fps);
		fclose( fps );
	}

}

void hiscore_write(){

	FILE *fp;
	FILE *fps;

	//ハイスコアの書き出し
	int all=0,hash;

	for(int i=0;i<CHAR_KIND_MAX;i++){
		if(i==use_char){
			if(hiscore[i] < ch.hiscore)	hiscore[i]=ch.hiscore;
		}
	}

	fp = fopen( "score/hiscore.dat" , "w" );
	for(int j=0;j<CHAR_KIND_MAX;j++){
		fprintf(fp,"%d\n",hiscore[j]);
		all+=hiscore[j];
	}

	hash=all%HASH;
	fprintf(fp,"%d\n",hash);

	fclose(fp);

	//レコード書き出し
	sort_rec();
	memset(&ch,0,sizeof(ch_t));
	fps = fopen( filename, "w");
	fwrite( &rec_score, sizeof(rec_score), 1, fps);
	fclose( fps );

}

int sort_rec(){

	int j;

	for(int i=0;i<10;i++){
		if( ch.hiscore>rec_score[i].hiscore ){
			for(j=9;j>i;j--){
				rec_score[j].chara_num	= rec_score[j-1].chara_num;
				rec_score[j].hiscore	= rec_score[j-1].hiscore;
				sprintf( rec_score[j-1].name, "%s", rec_score[j].name);
			}
			rec_score[i].chara_num	= use_char;
			rec_score[i].hiscore	= ch.hiscore;
			sprintf( rec_score[i].name, "%s", char_name);
			return i;
		}
	}

	return -1;

}
ここに記載されてない個所に、sort_rec();を呼び出している場所がないか、確認してまいります。
ほら、来いよ!! 誤字や矛盾を指摘したい奴から、前に出てこいよぉおおおおおおおッ!!!
※都合により、不定期でしか現れません。即返などはできませんのでご了承ください※

アバター
ookami
記事: 214
登録日時: 10年前
住所: 東京都

Re: 【龍神録】スコアソートプログラム

#9

投稿記事 by ookami » 6年前

うーん、
sort_rec()関数のランクイン時のif文で必ずreturnしているので、この関数単体で二重登録することはなさそうですね。
sort_rec()関数を呼んでいるのはhiscore_write()関数のみ。hiscore_write()関数を呼んでいるのは、「case 110」のところだけ、という認識でよいでしょうか。
だとすると、提示されていない部分の問題な気がしますね。
「case 110」のところが2回呼ばれているとか。
環境はVisualStudioでしょうか。ブレークポイントは活用されていますか?

暫定対処として、ランクイン時のif文のreturn前に ch.hiscore = 0 としてしまえば二重に登録されなくなる気はします。根本的な解決ではないですが...

直接は関係ないですが、sort_rec()関数の
sprintf( rec_score[j-1].name, "%s", rec_score[j].name);

sprintf( rec_score[j].name, "%s", rec_score[j-1].name);
ではないでしょうか?
(あと、strcpyでよいのでは?)

アバター
amehirune
記事: 181
登録日時: 7年前
住所: どっか
連絡を取る:

Re: 【龍神録】スコアソートプログラム

#10

投稿記事 by amehirune » 6年前

ookami さんが書きました:うーん、
sort_rec()関数のランクイン時のif文で必ずreturnしているので、この関数単体で二重登録することはなさそうですね。
sort_rec()関数を呼んでいるのはhiscore_write()関数のみ。hiscore_write()関数を呼んでいるのは、「case 110」のところだけ、という認識でよいでしょうか。
だとすると、提示されていない部分の問題な気がしますね。
「case 110」のところが2回呼ばれているとか。
環境はVisualStudioでしょうか。ブレークポイントは活用されていますか?
確認しました。提示していない部分に、sort_rec();をランクインさせてる場所がありました。
それを削除したことで、バグが治りました。ありがとうございます。解決とさせていただきます。

はい、環境はVC++2008のEEです。

ブレークポイントは…使い方が…(泣)
ookami さんが書きました:直接は関係ないですが、sort_rec()関数の
sprintf( rec_score[j-1].name, "%s", rec_score[j].name);

sprintf( rec_score[j].name, "%s", rec_score[j-1].name);
ではないでしょうか?
(あと、strcpyでよいのでは?)
ああぁぁぁ…本当ですね。すぐに変更します。
strcpyがいいかな、とも思っていたのですが、インクルードするファイルを追加するのが面倒なのでsprintfを使ってます(ぉぃ)
ほら、来いよ!! 誤字や矛盾を指摘したい奴から、前に出てこいよぉおおおおおおおッ!!!
※都合により、不定期でしか現れません。即返などはできませんのでご了承ください※

閉鎖

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