ページ 11

Cの標準ソート関数

Posted: 2011年5月15日(日) 17:09
by 小心者
初投稿ですがご回答よろしくお願いします
http://simd.jugem.jp/?eid=116
こちらのサイトを参考に構造体をソートしているのですが
ある数を引いた数でソートするということはできませんか?

例えば

コード:

typedef struct{
       int a
       int i
}TEST;

TEST sort[2]={
    {10,20}
    {30,40}
};
このような構造体があるとします これをソートすることはできるんですが
iを基準にソートするとき20-10,30-15の数値でソートしたいのです
つまり結果は10と15になりその結果の数値でソートをしたいのです

難しいかもしれませんがよろしくお願いします 
意味が分からないようでしたら、詳しく説明いたします

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 17:31
by h2so5
小心者 さんが書きました: iを基準にソートするとき20-10,30-15の数値でソートしたいのです
つまり結果は10と15になりその結果の数値でソートをしたいのです
-10,-15といった数字はどこから出てきたのですか?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 18:00
by フリオ
 
 それから、20、30も、どのような規則で決まるのか、を書いてください。

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 20:27
by 小心者
すいません 誤記でした
20-10、40-35です
どこから出てきたということですがどれくらいの値を引くかはどうでもよいのです
今回の例で-10と-35をあげさせていただきました

20-10=10、40-35=5となり
計算結果の値の10と5を比べると5の方が小さいです
この値を元にiを昇順でソートすると20→40となります
そうゆうことがしたいのですができますか?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 20:42
by h2so5
小心者 さんが書きました: どこから出てきたということですがどれくらいの値を引くかはどうでもよいのです
今回の例で-10と-35をあげさせていただきました
どうでもいいと言っても、実際に引く数値は何か意味のある数値なんですよね?
意味のない数字なら、最初から引いた後の数値を構造体に入れておけばいいのではないですか?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 20:51
by 小心者
何度もすいません  では、この技術を知って何をしたいかを書きますね
実は画像の描画順の並び替えをしたいのです
その際に画像の左下の座標を基準にソートしたいのですが
最初から引いた数値で構造体をつくってしまうと
その引いた数値の場所に画像が表示されますよね
そういうことはしたくないのです    
ですのでソートするときだけ引いた数値を参照して表示する時は引いていない数値を使うということが
したいのです     少々、長くなってしまいましたができますか?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 21:06
by h2so5
仰りたいことは分かりました。
比較関数を少しいじくれば実現できます。
今までiの数値で比較していたところを、単純に i - a での比較に置き換えればいいのです。

しかし疑問なんですが、
小心者 さんが書きました: その際に画像の左下の座標を基準にソートしたいのですが
左下の座標を基準にと言っても、x座標とy座標の差でソートする意味はあるんでしょうか?
(i , a がそれぞれ x , y に対応すると仮定してですが)
変な描画順になると思われます。

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 21:06
by box
元のデータと同じ形式を持つソート用の配列を用意し、
その配列に、あらかじめゲタをはかせた値を放り込んでからソートすればよいのでは?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 21:33
by softya(ソフト屋)
単純にソートキーと実際の座標のメンバ変数を分ければ良い話だと思います。

[追記]
構造体に、元の画像の情報がないとソート後には配列の並びが変わるので元の情報との整合性が取れなくなります。

コード:

typedef struct{
       int key; ← ソートキー。座標の画像のサイズから計算した値。つまり、20-10
       int index; ← 元になる画像情報・表示座標が格納された配列の添字。
}TEST;
この構造体配列をソートして、[0]からindexで示す画像を表示処理すれば思う順番に描画されるはずです。

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 21:36
by 小心者
h2so5 さんが書きました:左下の座標を基準にと言っても、x座標とy座標の差でソートする意味はあるんでしょうか?
(i , a がそれぞれ x , y に対応すると仮定してですが)
変な描画順になると思われます。
申し訳ないのですがi-aではありません
具体的に申しますとi-zとなっておりzに入る数字は画像の縦の長さになります
比較関数のいじり方も分からないのですがどのように実現できるのでしょうか?


box さんが書きました:元のデータと同じ形式を持つソート用の配列を用意し、
その配列に、あらかじめゲタをはかせた値を放り込んでからソートすればよいのでは?
馬鹿なので理解できません
もう少し詳しくご教授願えませんか?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 21:48
by box
小心者 さんが書きました:

コード:

TEST sort[2]={
    {10,20},
    {30,40},
};
と同じ構造を持つTEST型の配列(仮に名前をaaaとでもします)を

コード:

TEST aaa[2];
のように用意します。
次に、配列aaaの各要素に対して、配列sortの内容をもとに、
質問者さんの考えどおりに値をセットします。ここが、「ゲタをはかせる」って意味。
どういう値をセットするかは、こちらにはわかりません。質問者さんのプログラムしだい。
そして、配列aaaをソートします。

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 23:08
by たかぎ
小心者 さんが書きました:具体的に申しますとi-zとなっておりzに入る数字は画像の縦の長さになります
比較関数のいじり方も分からないのですがどのように実現できるのでしょうか?
Cのqsort関数では、zの値が静的に決まらないのであれば非局所オブジェクトを使わざるを得ず、使用状況によってはリエントラント性の問題が生じるので手放しには推奨できません。
非標準関数のqsort_sやqsort_rを使えるのであれば、それを使った方が楽に解決します。

実はCでなくC++であれば、関数オブジェクトを使えば簡単に問題が解決します。
最近は、たとえ部分的にでもC++0xに対応している処理系も普通に使えるようになってきたので、ラムダ式を使えば簡単に実装できたりもします。

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 23:19
by 小心者
softya(ソフト屋) さんが書きました:単純にソートキーと実際の座標のメンバ変数を分ければ良い話だと思います。

[追記]
構造体に、元の画像の情報がないとソート後には配列の並びが変わるので元の情報との整合性が取れなくなります。

コード:

typedef struct{
       int key; ← ソートキー。座標の画像のサイズから計算した値。つまり、20-10
       int index; ← 元になる画像情報・表示座標が格納された配列の添字。
}TEST;
この構造体配列をソートして、[0]からindexで示す画像を表示処理すれば思う順番に描画されるはずです。
提示されたものはこういうことでしょうか?

コード:

   
 typedef struct{
    int key;
    int x;
    int y;
    char *image;
 }test;
  
test test1[2] = {
    {20,41,"あああ.bmp"},
    {-20,40,"いいい.bmp"}
    };

    for (int i = 0; i < 2; i++) {
        LoadGraphScreen( test1[i].x , test1[i].y , test1[i].image , TRUE ) ;
        };

あってますでしょうか?初心者なもので

それとtest1の値の設定のところで
yから10を引いた数値でソートしようと思い
test test1[2] = {
{test1[1].y-10,20,41,"あああ.bmp"},
{-20,40,"いいい.bmp"}
};
このように書いたのですがエラーが出ます
どのように記述すればいいのでしょうか?

Re: Cの標準ソート関数

Posted: 2011年5月15日(日) 23:30
by softya(ソフト屋)
ちゃんと書くとしたら、表示座標はキャラが移動するので毎回かわりますよね。
だとしたら、ソートキーは毎回変わりますので毎回計算しないといけません。

キャラの移動
 ↓
ソートキー計算
 ↓
ソート
 ↓
表示

が毎フレーム必要です。

それとLoadGraphScreenはタイトル画面とかの表示用でゲーム中に使用するのは向きません。
ロード処理(LoadGraph)はまとめて初期化時とメインループの表示(DrawGraph)に分けて行います。

ゲームに関する基本的な組み方は、ここの管理人であるDixqさんが作っていらっしゃるコンテンツを一通り読まれることをお勧めします。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/

[追記]
ちなみに、

コード:

test test1[2] = {
{test1[1].y-10,20,41,"あああ.bmp"},
{-20,40,"いいい.bmp"}
};
は、自己参照で動的に変化するものが定数として書かれているのでNGです。
keyは、プログラム中に計算を書いてください。

Re: Cの標準ソート関数

Posted: 2011年5月16日(月) 00:24
by ISLe
いわゆるバードビューで表示する画像の描画順を求めるためにソートしたいのかなと。勝手な想像ですけど。
もしそうなら画像の左上座標を基準にするのではなく、ベースライン上の座標を基準にしたほうが良いのでは。

描画するときに上にずらして描画するほうが余分な情報をたらい回ししなくて済むと思います。
キャラクタがジャンプしてたり空を飛んでいたりとか画像の縦サイズよりもさらに上にずらして描画しなくてはならないときでもベースラインは変わらないので。

Re: Cの標準ソート関数

Posted: 2011年5月16日(月) 22:49
by 小心者
>>ISleさん
はいその通りバードビューです ベースラインってのがよく分からないんですが
あらかじめ表示座標に縦の長さを足しておいてそこに表示しろってことですよね
なるほどそのような手法もありましたか・・・ どちらがいいのか考えて見ます

>>ソフト屋さん
構造体の中に式を書いちゃ駄目なんですね
メモリー読み込みのこともありがとうございました

それと、もうひとつ気になったんですがこの表示方法で表示フラグを導入するにはどうすればいいですかね
普通の表示方法なら
if(flag=1)DrawGraphScreen(画像A)
if(flag=2)DrawGraphScreen(画像B)
こんな風に記述できますがこのやり方だと効率のいい表示フラグ参照が思い浮かびません
教えてください すいません

Re: Cの標準ソート関数

Posted: 2011年5月16日(月) 23:42
by softya(ソフト屋)
小心者 さんが書きました:それと、もうひとつ気になったんですがこの表示方法で表示フラグを導入するにはどうすればいいですかね
普通の表示方法なら
if(flag=1)DrawGraphScreen(画像A)
if(flag=2)DrawGraphScreen(画像B)
こんな風に記述できますがこのやり方だと効率のいい表示フラグ参照が思い浮かびません
教えてください すいません
どういう意味の表示フラグでしょうか?
キャラクタの存在・非存在ならそもそもソート配列に登録しなければ良いことです。
アニメーションパターンなら、パターン番号を構造体に持てばよいだけです。
[訂正]それとも私が勘違いしてますか?

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 00:38
by ISLe
小心者 さんが書きました:はいその通りバードビューです ベースラインってのがよく分からないんですが
あらかじめ表示座標に縦の長さを足しておいてそこに表示しろってことですよね
ベースラインというのは地面との接点を含む水平線のことです。
空中に浮いているときは垂線を垂らして地面と交わる点を接点とします。

描画順を決めるのに表示座標と画像サイズだけでは上手くいかないパターンがありますし、ベースライン基準で管理したほうがあらかじめ何かしておくとか必要なくなってプログラムの構造がシンプルになると思います。

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 18:32
by 小心者
>>ISLeさん
あーそれがベースラインって言うんですか!
自分は横座標をx、奥行きをy、そして高さをhにしてy+h=縦座標の表示位置にしております
(↑多分このことですよね・・・) ありがとうございます 
わざわざ画像まで用意していただき、勉強になります

>>ソフト屋さん
いえいえ、勘違いなどされておりませんよ その通りです
配列に入れなければいいのかな~というのは浮かんだのですが比較関数と構造体をいくつも作るのは
面倒くさいな~と思ったもので・・・  いい考えはありませんかね(生意気言って申し訳ないです)
もう一つ質問なのですが画像の反転描写など様々な描画関数を使いたくなった場合、どうしましょう

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 18:41
by softya(ソフト屋)
小心者 さんが書きました:いえいえ、勘違いなどされておりませんよ その通りです
配列に入れなければいいのかな~というのは浮かんだのですが比較関数と構造体をいくつも作るのは
面倒くさいな~と思ったもので・・・  いい考えはありませんかね(生意気言って申し訳ないです)
もう一つ質問なのですが画像の反転描写など様々な描画関数を使いたくなった場合、どうしましょう
反転なら反転フラグで済む話ですね。
同時に起こるエフェクトの種類や組み合わせで必要なフラグ変数の数も変わると思います。

あとキャラクタの管理構造体とソート構造体は分けた方が後々良いでしょう。
最初の頃に書いたように、ソート構造体にはキャラクタの管理構造体の添字番号かポインタを持てば最低限のサイズの構造体に出来ます。

コード:

typedef struct{
       int key; ← ソートキー。座標の画像のサイズから計算した値。つまり、20-10
       int index; ← 元になる画像情報・表示座標が格納された配列の添字。
}TEST;

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 21:11
by box
小心者 さんが書きました: if(flag=1)DrawGraphScreen(画像A)
if(flag=2)DrawGraphScreen(画像B)
っていうか、そもそもこういうif文を書いている時点で「なんかまずいんじゃないかなぁ」
なんて思ったりしてます。

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 22:06
by 小心者
box さんが書きました:っていうか、そもそもこういうif文を書いている時点で「なんかまずいんじゃないかなぁ」
なんて思ったりしてます。
単文だからまずいということでしょうか?それともセミコロンがないとかエラー的なことでしょうか?
まぁ、その辺は自分も短縮した形で書きましたし多分、心配無用・・・だと思います
softya(ソフト屋) さんが書きました:反転なら反転フラグで済む話ですね。
同時に起こるエフェクトの種類や組み合わせで必要なフラグ変数の数も変わると思います。
フラグ変数が書けません(フラグ変数は分かりますが、どこに記述すればいいか・・・)

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 22:11
by softya(ソフト屋)
小心者 さんが書きました:フラグ変数が書けません(フラグ変数は分かりますが、どこに記述すればいいか・・・)
こちらの意味は理解されていますか?
softya(ソフト屋) さんが書きました:あとキャラクタの管理構造体とソート構造体は分けた方が後々良いでしょう。
最初の頃に書いたように、ソート構造体にはキャラクタの管理構造体の添字番号かポインタを持てば最低限のサイズの構造体に出来ます。
とりあえず、小心者さんが考えている形の簡単な足元順のソートのサンプルコードを今の知識に範囲で書いてもらってよいでしょうか?
それをもとに改善点を書いたほうが分りやすいと思いますのでお願いします。

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 22:11
by box
小心者 さんが書きました: 単文だからまずいということでしょうか?それともセミコロンがないとかエラー的なことでしょうか?
おっと、そうきましたか。
カッコの中に書いてある
flag=1
という式は、
flag

1
を代入して、その結果(1)を評価します。つまり、
if(flag=1)
っていうif文は、ぶっちゃけ
if(1)
って書いたのと同じです。
flag

1
とを比較「していません」。

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 22:17
by 小心者
>>boxさん
あーーーやっちましました ごめんなさい 文法どころの話じゃなかったです、、、、ちゃっかりちゃっかり
if(flag==1)←こうですね

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 23:21
by 小心者

コード:

#include "DxLib.h"
 
 typedef struct{
    int x;
    int y;
    char *image;
 }test;  

 typedef struct{
    int key;
    int index;
 }sort;

int comp( const void *c1, const void *c2);
 
// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        LPSTR lpCmdLine, int nCmdShow )
{          
        ChangeWindowMode( TRUE ) ;
 
    if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
    {
        return -1 ;         // エラーが起きたら直ちに終了
    }
    
    
    test test1[2] = {
    {20,41,"あああ.bmp"},
    {-20,40,"いいい.bmp"}
    };
    
    sort sort1[2] = {
    {test1[1].y-20,1},
    {test1[2].y-20,2}
    }; 
    
    qsort(sort1,2,sizeof(sort),comp);
    
    for (int i = 0; i < 2; i++) {
        LoadGraphScreen( test1[i].x , test1[i].y , test1[i].image , TRUE ) ;
        };
    
    
    // 絵を打つ
 
    WaitKey() ;             // キー入力待ち
 
    DxLib_End() ;               // DXライブラリ使用の終了処理
 
    return 0 ;              // ソフトの終了 
}
 
int comp( const void *c1, const void *c2){
          sort sort2 = *(sort *)c1;
          sort sort3 = *(sort *)c2;
 
          int tmp1 = sort2.key;   
          int tmp2 = sort3.key;
 
          return tmp1 - tmp2;
}
ソフト屋さんの提示されたキャラ構造体とソート構造体をわける技法を取り込んでみたのですが
これじゃあ、ソートされた値が使われてませんよね・・・ どうしましょう・・・

Re: Cの標準ソート関数

Posted: 2011年5月17日(火) 23:49
by 小心者
ふと気付いてiと書いてある部分をindexにしみたのですが変わりませんでした
何か根本的な間違いがあるのでしょうか?

Re: Cの標準ソート関数

Posted: 2011年5月18日(水) 00:36
by softya(ソフト屋)
私の書いたことがほとんど反映されていませんので、実例で示します。
「C言語~ゲームプログラミングの館~」
http://dixq.net/g/14.html
をベースにしました。

まず、配列の添字の使い方が全面的に間違っています。2要素の配列の添字は0と1です1と2ではありませんでの注意してください。
それと次の指摘点も反映させています。ISLeさんの言うベースラインには対応させていません。
softya(ソフト屋) さんが書きました:ちゃんと書くとしたら、表示座標はキャラが移動するので毎回かわりますよね。
だとしたら、ソートキーは毎回変わりますので毎回計算しないといけません。

キャラの移動
 ↓
ソートキー計算
 ↓
ソート
 ↓
表示

が毎フレーム必要です。

それとLoadGraphScreenはタイトル画面とかの表示用でゲーム中に使用するのは向きません。
ロード処理(LoadGraph)はまとめて初期化時とメインループの表示(DrawGraph)に分けて行います。

ゲームに関する基本的な組み方は、ここの管理人であるDixqさんが作っていらっしゃるコンテンツを一通り読まれることをお勧めします。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/

コード:

#include "DxLib.h"

typedef struct{
	int x;
	int y;
	char* file;
	int image;
}test;  

typedef struct{
	int key;
	int index;
}sort;

int comp( const void *c1, const void *c2);

#define CHARS_MAX 2

char Key[256];

// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode( TRUE ) ;

	if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
	{
		return -1 ;         // エラーが起きたら直ちに終了
	}

	//	描画先を裏画面に設定
	SetDrawScreen( DX_SCREEN_BACK );

	test test1[CHARS_MAX] = {
		{20,56,"aka.png"},
		{21,40,"siro.png"}
	};

	//	ロード
	for( int i=0 ; i<CHARS_MAX ; i++ ) {
		test1[i].image = LoadGraph(test1[i].file);
	}

	//	ここからメインループ
	while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
		//↑メッセージ処理         ↑画面をクリア          ↑キーボード入力状態取得       ↑ESCが押されていない
		sort sort1[CHARS_MAX];

        if( Key[ KEY_INPUT_UP ]  == 1 )      //上ボタンが押されたら
            test1[0].y-- ;                            //yの値を1減らす
        if( Key[ KEY_INPUT_DOWN ]  == 1 )    //下タンが押されたら
            test1[0].y++ ;                            //yの値を1増やす
            
		//	ソートキーの作成
		for( int i=0 ; i<CHARS_MAX ; i++ ) {
			sort1[i].key = test1[i].y-20;
			sort1[i].index = i;
		}

		//	ソートを行う。
		qsort(sort1,CHARS_MAX,sizeof(sort),comp);

		//	ソートされた順番に表示
		for( int i=0 ; i<CHARS_MAX ; i++ ) {
			int index = sort1[i].index;
			DrawGraph( test1[index].x , test1[index].y , test1[index].image , TRUE ) ;
		}
		ScreenFlip();//裏画面を表画面に反映
	}

	DxLib_End() ;               // DXライブラリ使用の終了処理

	return 0 ;              // ソフトの終了 
}

int comp( const void *c1, const void *c2){
	sort sort2 = *(sort *)c1;
	sort sort3 = *(sort *)c2;

	int tmp1 = sort2.key;   
	int tmp2 = sort3.key;

	return tmp1 - tmp2;
}
aka.pngとsiro.pngはこちらにあった32x32の画像です。

Re: Cの標準ソート関数

Posted: 2011年5月18日(水) 17:33
by ぴょうぴんぽぽ
表示フラグはどこですか?

Re: Cの標準ソート関数

Posted: 2011年5月18日(水) 17:42
by softya(ソフト屋)
ぴょうぴんぽぽ さんが書きました:表示フラグはどこですか?
ぴょうぴんぽぽさんと小心者さんは同一人物でしょうか?
もし同じ方なら無用な混乱のもとなので名前の統一をお願いします。
フォーラムルールにも記載してありますので確認をお願いします。

同じか方だと仮定して答えると、小心者さんのコード自体が表示フラグ以前にゲームとしての仕組みが出来ていないので実装していません。
小心者さんが表示フラグやら、エフェクトフラグの仕様と言うかゲームプログラムの仕組みを理解した後でないと書くわけには行きませんので。
[補足]まず、ご自分で実装してみてください。

それと、「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」 http://dixq.net/g/
は一通り読まれて理解されましたか?
この後に進むには基本・入門だけは読んで理解してる事を前提にしないと進めないと思います。

Re: Cの標準ソート関数

Posted: 2011年5月18日(水) 22:02
by ぴょうぴんぽぽ
あ、いえ自分も初心者でここのトピックを見ていて気になったもので・・・
「ぴょうぴんぽぽ」は小心者さんの名前を借りさせていただきました(ぱ行にした)

表示フラグのことで画像を持っていないので試すことが出来ないんですけど
多分、構造体の中にソート構造体にchar型のflag変数をつくって文字列を代入し
if(sort.flag)なんてことをすればできるのではないのでしょうか?
複数の関数を使いたい場合もfor文のなかで分岐をさせて関数を使い分けるのではないでしょうか?

あっている間違っている指摘ください 気になるので
それとキャラ構造体とソート構造体を分けているのはなぜですか?
ソート構造体のコピーなど、なんか手間があるように見えるので(初心者にはそう見える)

Re: Cの標準ソート関数

Posted: 2011年5月18日(水) 22:27
by softya(ソフト屋)
ぴょうぴんぽぽさん、私にメールを頂けますか?お伝えしたいことがあります。 
メールアドレスは、画像です(すいません。アドレスを手で打ち込んでください)。

Re: Cの標準ソート関数

Posted: 2011年5月18日(水) 23:39
by softya(ソフト屋)
ぴょうぴんぽぽ さんが書きました:表示フラグのことで画像を持っていないので試すことが出来ないんですけど
多分、構造体の中にソート構造体にchar型のflag変数をつくって文字列を代入し
if(sort.flag)なんてことをすればできるのではないのでしょうか?
複数の関数を使いたい場合もfor文のなかで分岐をさせて関数を使い分けるのではないでしょうか?


文字列を持つのは効率的ではないです。「文字列を代入しif(sort.flag)なんてことを」はC言語の文法として問題があります。
int型で0がOFF、1がONで良いんじゃないでしょうか?

「for文のなかで分岐をってところが不明確」ですが、表示の中で行うならenumでパターン定義してswitchで分岐で良いんじゃないでしょうか?

ぴょうぴんぽぽ さんが書きました:それとキャラ構造体とソート構造体を分けているのはなぜですか?
ソート構造体のコピーなど、なんか手間があるように見えるので(初心者にはそう見える)


ソート対象の構造体が大きくなるとそれだけ遅くなるからです。
あとソート構造体とキャラクタ管理構造体で同じデータを持つのは無駄ですね。

Re: Cの標準ソート関数

Posted: 2011年5月19日(木) 23:29
by 小心者

コード:


#include "DxLib.h"
 
typedef struct{
    int x;
    int y;
    char* file;
    int image;
}test;  
 
typedef struct{
    int key;
    int index;
    int flag;
}sort;
 
int comp( const void *c1, const void *c2);
 
 
char Key[256];
 
// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode( TRUE ) ;
 
    if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
    {
        return -1 ;         // エラーが起きたら直ちに終了
    }
 
    //  描画先を裏画面に設定
    SetDrawScreen( DX_SCREEN_BACK );
 
    test test1[2] = {
        {20,56,"あああ.bmp"},
        {21,40,"いいい.bmp"}
    };
 
    //  ロード
    for( int i=0 ; i<2 ; i++ ) {
        test1[i].image = LoadGraph(test1[i].file);
    }
 
    //  ここからメインループ
    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
        //↑メッセージ処理         ↑画面をクリア          ↑キーボード入力状態取得       ↑ESCが押されていない
        sort sort1[2];
 
        if( Key[ KEY_INPUT_UP ]  == 1 )      //上ボタンが押されたら
            test1[0].y-- ;                            //yの値を1減らす
        if( Key[ KEY_INPUT_DOWN ]  == 1 )    //下タンが押されたら
            test1[0].y++ ;                            //yの値を1増やす
            
        sort1[0].flag=1;
	
	//  ソートキーの作成
        for( int i=0 ; i<2 ; i++ ) {
            sort1[i].key = test1[i].y-20;
            sort1[i].index = i;
        }
 
        //  ソートを行う。
        qsort(sort1,2,sizeof(sort),comp);
 
        //  ソートされた順番に表示
        for( int i=0 ; i<2 ; i++ ) {
          if(sort1[i].flag==1){  
	    int index = sort1[i].index;
            DrawGraph( test1[index].x , test1[index].y , test1[index].image , TRUE ) ;
          }
	}
        ScreenFlip();//裏画面を表画面に反映
    }
 
    DxLib_End() ;               // DXライブラリ使用の終了処理
 
    return 0 ;              // ソフトの終了 
}
 
int comp( const void *c1, const void *c2){
    sort sort2 = *(sort *)c1;
    sort sort3 = *(sort *)c2;
 
    int tmp1 = sort2.key;   
    int tmp2 = sort3.key;
 
    return tmp1 - tmp2;
}
if文を書いてみました 自分の予想している実行結果はあああ.bmpだけ表示ですが
いいい.bmpも表示されてしまいます なぜでしょうか?
(sort1[0].flagに1を代入していてsort[1].flagは0のままですのでいいいは表示されないと思うのですが)

for文の中で描画関数を使い分けなければ描画順を操作することが出来ないと思うのですが
この考えは間違っているのでしょうか?    switch文のを一度、書いてみます

Re: Cの標準ソート関数

Posted: 2011年5月20日(金) 00:45
by softya(ソフト屋)
最初にsort1[1].flagが代入されていないので値が最初不定です。
sortの都合上、途中で値が1になるのでsort1[0].flag共々1になっていします。
かならず配列の中身を全部埋めてください。

代入するなら

コード:

        sort1[0].flag=1;
        sort1[1].flag=0;
と明確に値を設定すれば直ります。

Re: Cの標準ソート関数

Posted: 2011年5月22日(日) 00:53
by 小心者
ありがとうございます
最後に・・・
「enumでパターン定義して」と仰りましたがenumがよく分かりません
普通のswitch文じゃ駄目なんでしょうか?

コード:


#include "DxLib.h"
 
typedef struct{
    int x;
    int y;
    char* file;
    int image;
}test;  
 
typedef struct{
    int key;
    int index;
    int flag;
    int byouga;
}sort;
 
int comp( const void *c1, const void *c2);
 
 
char Key[256];
 
// プログラムは WinMain から始まります
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow )
{
    ChangeWindowMode( TRUE ) ;
 
    if( DxLib_Init() == -1 )        // DXライブラリ初期化処理
    {
        return -1 ;         // エラーが起きたら直ちに終了
    }
 
    //  描画先を裏画面に設定
    SetDrawScreen( DX_SCREEN_BACK );
 
    test test1[3] = {
        {20,56,"あああ.bmp"},
        {21,40,"いいい.bmp"},
        {22,52,"ううう.bmp"}
    };
 
    //  ロード
    for( int i=0 ; i<2 ; i++ ) {
        test1[i].image = LoadGraph(test1[i].file);
    }
    
     LoadDivGraph(test[2].file, 10 , 4 , 3, 48 , 56 , test1[2].image);      
    
     //  ここからメインループ
    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
        //↑メッセージ処理         ↑画面をクリア          ↑キーボード入力状態取得       ↑ESCが押されていない
        sort sort1[3] = {
                  {test[0]-20 , 0 , 1 , 1},
                  {test[1]-23 , 1 , 1 , 1},
                  {test[2]-32 , 2 , 1 , 2}
        };                      

 
        if( Key[ KEY_INPUT_UP ]  == 1 )                  
             sort1[2].byouga = 3                               

        //  ソートを行う。
        qsort(sort1,3,sizeof(sort),comp);
 
        //  ソートされた順番に表示
        for( int i=0 ; i<3 ; i++ ) {
          if(sort1[i].flag==1){  
            int index = sort1[i].index;
            switch(sort[i].byouga){
              case 1;
                DrawGraph( test1[index].x , test1[index].y , test1[index].image , TRUE ) ;
                break;
              case 2;
                DrawGraph( test1[index].x , test1[index].y , test1[index].image[ a ] , TRUE ) ;
                break;
              case 3;
                DrawTurnGraph( test1[index].x , test1[index].y , test1[index].image[ a ] , TRUE ) ;
                break;
           } 
         } 
    }
        ScreenFlip();//裏画面を表画面に反映
    }
 
    DxLib_End() ;               // DXライブラリ使用の終了処理
 
    return 0 ;              // ソフトの終了 
}
 
int comp( const void *c1, const void *c2){
    sort sort2 = *(sort *)c1;
    sort sort3 = *(sort *)c2;
 
    int tmp1 = sort2.key;   
    int tmp2 = sort3.key;
 
    return tmp1 - tmp2;
} 


aの値が設定されていなかったりしますが・・・

Re: Cの標準ソート関数

Posted: 2011年5月22日(日) 00:58
by softya(ソフト屋)
enumで書くのがきれいな書き方ってだけです。
難しかったら、とりあえず使わなくてもOKです。

ところで、test1[index].image[ a ]が意味不明ですね。
あと、byougaはtest構造体にあった方が後々良い気もしますが、これ以上拡張しないなら無視して良いです。

Re: Cの標準ソート関数

Posted: 2011年5月22日(日) 01:16
by 小心者
aは画像切り替えの為の変数のつもりだったのですが・・・
描画関数の使い方、間違っていましたかね ごめんなさい

とりあえず「構造体が大きすぎるとソートに時間がかかる」という
ソフト屋さんの助言に基づいてbyougaとflagはキャラ構造体に持っていくことにします

長い間、助けてくださりありがとうございました
他の皆さんも知恵を貸していただき感謝いたします