ランキングの実装

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

ランキングの実装

#1

投稿記事 by 青成 » 5年前

私はシューティングゲームで避け切った時間を計測し、タイトル画面でランキングとして表示するプログラムを考えています。
制作環境はwindows7、VisualStudioExpress2012、DXライブラリです。
流れは、
タイトル画面(ランキングが表示されている)→ゲーム開始(タイム計測)→被弾するとリザルト画面へ(タイムの表示、ランキング更新)→タイトル画面
のような流れです。

stimeとranking[10]はグローバル変数として宣言してあります。
まずタイトル画面の処理ですが、

コード:

for(int i=0;i<RANKING_MAX;i++){
				DrawFormatString(120,100+(i*30),GetColor(255,255,255),"%d 位  %.1f 秒",i+1,ranking[i]);
			}
ここでズラッと1位から10位までのタイムを縦に表示します。

ゲーム中は

コード:

stime = (GetNowCount() - time)/1000;
で時間を取得しています。

そしてリザルト画面で

コード:

void ranking_sort(double score){
	       int i;
		   int j;
		  for(i=0;i<RANKING_MAX;i++){//1位から比較
				   //今の順位よりも高ければそれが今回の順位となる
				   //(1位より高ければ1位、1位より低く2位より高ければ2位、…)
			    if(score>ranking[i]){
		            for(j=RANKING_MAX -1;j>i;j--){//今回の順位以降のスコアをずらす
				        ranking[j]=ranking[j-1];
            }
            ranking[i]=score;//今回のスコアを記憶
	    break;//以降の順位は調べない
        }
				
    }
		  
}

void result(){
     ranking_sort(stime);
}
※ranking_sortはhttp://dixq.net/forum/viewtopic.php?f=3&t=14395のTatu様のプログラムを使用させて頂きました。

と書きました。
実行すると最初のタイトル画面では1位~10位まで0.0秒と表示。ゲームで5.0秒のタイムを出したとしリザルト画面を経てタイトルに戻ります。
そうすると1位~10位まで全て5.0秒というタイムになってしまいます。
そこからまたタイムを更新し、5.5秒の記録を出したとすると、1位~10位まで全て5.5秒のタイムが表示されます。タイムを更新しなければ何も変化なしです。
恐らくbreakが動作していないと思うのですが・・・
理想とする実行結果はタイムが長い順(降順)に1位から順番に表示していく、一つずつランキングの更新をしていく事です。

また、10位のタイムよりタイムが長ければ10位にタイムを代入。そこからバブルソートで順位を降順にソートする方法も考え組んでみました。

コード:

void ranking_sort2(double score){
	if(score > ranking[9]){ //ranking[9]より高ければranking[9]にその数を入れる
		ranking[9] = score;
	}

 int i,j;
double temp;
	
	for (i = 0;i < RANKING_MAX - 1;i++) {
		for (j = 0;j <RANKING_MAX - 1;j++) {
			if (ranking[j + 1] < ranking[j]) {
				temp = ranking[j];ranking[j] = ranking[j + 1];ranking[j + 1] = temp;
			}
		}
	}
}
バブルソートのプログラムは書籍から参照
このように書きましたが10位のタイムだけが更新され、1位~9位が0.0秒、10位が5.0秒という結果になってしまいます。そこからタイムを更新すると1位~9位が0.0秒、10位が5.5秒といった結果です。


ポインタやアドレスを扱うのでしょうか・・・。一通り見てみましたが配列(ranking[])に対してポインタを使う方法は探せませんでした。

なぜこのプログラムで実行がうまくいかないのか、どうすればランキングの実装ができるのか、ご教授下さい。よろしくお願いします。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ランキングの実装

#2

投稿記事 by へにっくす » 5年前

Tatuさんのコードで間違いないと思いますが。
以下のように組んだけど、ちゃんと出てますね。
rankingの型はdoubleでokですよね?

コード:

#include <stdio.h>

#define RANKING_MAX 10

double ranking[RANKING_MAX] = {0};

void ranking_sort(double score){
	int i;
	int j;
	for(i=0;i<RANKING_MAX;i++){//1位から比較
		//今の順位よりも高ければそれが今回の順位となる
		//(1位より高ければ1位、1位より低く2位より高ければ2位、…)
		if(score>ranking[i]){
			for(j=RANKING_MAX -1;j>i;j--){//今回の順位以降のスコアをずらす
				ranking[j]=ranking[j-1];
			}
			ranking[i]=score;//今回のスコアを記憶
			break;//以降の順位は調べない
		}
	}

}
 
int main()
{
	ranking_sort(10.0);
	ranking_sort(5.0);
	for (int i = 0; i < RANKING_MAX; i++)
	{
		printf("%d 位  %.1f 秒\n", i+1, ranking[i]);
	}
	return 0;
}
コンパイル&実行結果

コード:

C:\Users\***\Documents>cl 2.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

2.cpp
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:2.exe
2.obj

C:\Users\***\Documents>2
1 位  10.0 秒
2 位  5.0 秒
3 位  0.0 秒
4 位  0.0 秒
5 位  0.0 秒
6 位  0.0 秒
7 位  0.0 秒
8 位  0.0 秒
9 位  0.0 秒
10 位  0.0 秒

C:\Users\***\Documents>
VS2012 Expressならデバッグでブレークポイントをはり、変数の内容を調べることができるはずです。
ranking_sort関数の終わりにブレークしてみて、rankingの内容を表示してみてください。
そこで問題がなければ、ほかの処理で何か上書きしているのです。
オフトピック
インデントはそろえましょう。最低限の礼儀です。
written by へにっくす

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

Re: ランキングの実装

#3

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

青成 さんが書きました:また、10位のタイムよりタイムが長ければ10位にタイムを代入。そこからバブルソートで順位を降順にソートする方法も考え組んでみました。

コード:

void ranking_sort2(double score){
	if(score > ranking[9]){ //ranking[9]より高ければranking[9]にその数を入れる
		ranking[9] = score;
	}

 int i,j;
double temp;
	
	for (i = 0;i < RANKING_MAX - 1;i++) {
		for (j = 0;j <RANKING_MAX - 1;j++) {
			if (ranking[j + 1] < ranking[j]) {
				temp = ranking[j];ranking[j] = ranking[j + 1];ranking[j + 1] = temp;
			}
		}
	}
}
バブルソートのプログラムは書籍から参照
このように書きましたが10位のタイムだけが更新され、1位~9位が0.0秒、10位が5.0秒という結果になってしまいます。そこからタイムを更新すると1位~9位が0.0秒、10位が5.5秒といった結果です。
このプログラムだと、降順ではなく昇順にソートされると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: ランキングの実装

#4

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

青成 さんが書きました:そしてリザルト画面で

コード:

void ranking_sort(double score){
	       int i;
		   int j;
		  for(i=0;i<RANKING_MAX;i++){//1位から比較
				   //今の順位よりも高ければそれが今回の順位となる
				   //(1位より高ければ1位、1位より低く2位より高ければ2位、…)
			    if(score>ranking[i]){
		            for(j=RANKING_MAX -1;j>i;j--){//今回の順位以降のスコアをずらす
				        ranking[j]=ranking[j-1];
            }
            ranking[i]=score;//今回のスコアを記憶
	    break;//以降の順位は調べない
        }
				
    }
		  
}

void result(){
     ranking_sort(stime);
}
※ranking_sortはhttp://dixq.net/forum/viewtopic.php?f=3&t=14395のTatu様のプログラムを使用させて頂きました。

と書きました。
まさかとは思いますが、result()をリザルト画面で毎フレーム呼び出している、なんてことは無いですよね?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

青成

Re: ランキングの実装

#5

投稿記事 by 青成 » 5年前

へにっくすさんみけCATさん回答ありがとうございます。
オフトピック
インデントの件申し訳ありません、以後気を付けます
みけCAT さんが書きました:まさかとは思いますが、result()をリザルト画面で毎フレーム呼び出している、なんてことは無いですよね?
まさかでした。毎フレームと一度だけの処理を区別するのは難しいです・・・。

以下、メイン関数の中身です

コード:

switch(seans){
      case 10:
         //最初の画面
    case 20:
         //ゲーム開始
      case 30:
         result(); //ここでランキングの更新
      case 40:
         resultscreen(); //リザルト画面を表示(タイムなど)
}
前まではresultscreen()の中にresult()を入れていました。
そこで、タイトル画面(ランキングが表示されている)→ゲーム開始(タイム計測)→被弾するとランキングの更新→リザルト画面へ(タイムの表示)→タイトル画面のようにすると正しい実行結果が得られました。
無事、解決できました。へにっくすさんみけCATさんありがとうございました。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ランキングの実装

#6

投稿記事 by へにっくす » 5年前

青成 さんが書きました:以下、メイン関数の中身です

コード:

switch(seans){
      case 10:
         //最初の画面
    case 20:
         //ゲーム開始
      case 30:
         result(); //ここでランキングの更新
      case 40:
         resultscreen(); //リザルト画面を表示(タイムなど)
}
caseの後にbreak;がないので、意図しない流れになっている可能性があります。
seansが10のとき、20、30、40も実行しちゃいますよ。
C言語の基本なのですが大丈夫ですか?
written by へにっくす

青成

Re: ランキングの実装

#7

投稿記事 by 青成 » 5年前

すいません、書き方が悪かったみたいです。
switch文の中は今回の論点である部分だけを抜粋し、他は省略していました。
仰る通り、各caseの末にはbreakが入っています。

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: ランキングの実装

#8

投稿記事 by へにっくす » 5年前

青成 さんが書きました:すいません、書き方が悪かったみたいです。
switch文の中は今回の論点である部分だけを抜粋し、他は省略していました。
仰る通り、各caseの末にはbreakが入っています。
了解です。杞憂でよかった。
気を付けてくださいね。回答者として不安を感じてしまいますので。笑
written by へにっくす

閉鎖

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