ページ 11

並び順

Posted: 2009年11月30日(月) 14:02
by しいたけ
こんにちは。
作成しているもので、教えてほしいことがあるので投稿させていただきました。
当方の環境は、WindowsXP。コンパイラはVC2008。DXライブラリを使用しています。

一組目と二組目での並び順を表示するプログラムを作成しています。

int x[5];
int y[5];
retu1[3]
retu2[3]

xとyは座標となっています。
例えば

1 2
3 4 5

という並びならば、
retu1[0] = 1
retu1[1] = 2
retu2[0] = 3
retu2[1] = 4
retu2[2] = 5
となっています。そして、これ以上増やすことはできません。

そこで悩んでしまったのが、この並びを判定するプログラムです。
現在は、
if(kazu == 3) // 選ばれた人数。4人選ばれたらkazu == 4となる
{
 if(retu1[0] == 1)
 {
  if(retu1[1] == 2)
  {
   if(retu2[0] == 3)
   {
    x[0] = 0;
    y[0] = 0;
    x[1] = 10;
    y[1] = 0;
    x[2] = 0;
    y[2] = 10;
    func1(x[0], y[0]); // retu1[0]の表示
    func2(x[1], y[1]); // retu1[1]の表示
    func3(x[2], y[2]); // retu2[0]の表示
   }
  }
 }
}

結果
1 2
3
としています。(func は表示をさせる関数です。実際には画像を表示させています。)
もしも並びが

1 2
3 4 5

と、連番ならば簡単になるかもしれませんが、このプログラムは

3 1 5
2 4

という並びもできるようにしています。
プログラムでは
if(kazu == 5)
{
 if(retu1[0] == 3)
 {
  if(retu1[1] == 1)
  {
   if(retu1[2] == 5)
   {
    if(retu2[0] == 2)
    {
     if(retu2[1] == 4)
     {
      x[0] = 0;
      y[0] = 0;
      x[1] = 10;
      y[1] = 0;
      x[2] = 20;
      y[2] = 0;
      x[3] = 0;
      y[3] = 10;
      x[4] = 10;
      y[4] = 10;
      func3(x[0], y[0]); // retu1[2]の表示
      func1(x[1], y[1]); // retu1[0]の表示
      func5(x[2], y[2]); // retu1[1]の表示
      func2(x[3], y[3]); // retu2[1]の表示
      func4(x[4], y[4]); // retu2[0]の表示
     }
    }
   }
  }
 }
}
このように記述しています。
ですが、これだと一つ一つ判定させていくと大変で膨大な数になってしまいます。
これを何とか簡単に書くことは出来ないでしょうか?お力を貸してください。

Re:並び順

Posted: 2009年11月30日(月) 14:52
by softya
ごめんなさい。並びのルールがイマイチ分かりません。
列と数から、どのようにして並び順を作っているのかルール性が分かりません。
x[0] = 0;y[0] = 0;とfunc3(x[0], y[0]); // retu1[2]の表示ってのも関連性が良く分かりません。
ルールを箇条書きにしてもらえないでしょうか。

Re:並び順

Posted: 2009年11月30日(月) 18:08
by しいたけ
softya様。分かりづらくて申し訳ありません。読み返してみると確かに分からないですね。


・func1(int x, int y)~func5(int x, int y)という関数があり、画像を表示させる関数。引数は上に書いてあるソースのx,yが入る。x, yは座標で、この座標を元に画像を表示させる。

・retu1,retu2 の i に入る数値は0,1,2で、左詰にする。

・retu1[0] == 1の場合、func1を動かす。retu[0] == 2の場合、func2を動かす。

・retu1[1] == 3 の場合func3を動かす。[/url]の中が1か2の場合、[0]には1~5の数値のどれかが入っていて、func1~func5のどれかが動いている。絶対にretu[0]に値が入っていないのに、retu[1] == 3だけでは動かしてはいけない。(二つ上の左詰ということです。)

・x, y は、
retu1であり、
[0]の場合、x = 0, y = 0;
[1]の場合、x = 10, y = 0;
[2]の場合、x = 20, y = 0;
retu2であり
[0]の場合、x = 0, y = 10;
[1]の場合、x = 10, y = 10;
[2]の場合、x = 20, y = 10;
と、左から順に表示させるような座標の値を入れる。

・kazuとは、5人までの制限であり、kazuが3の場合三人。kazuが5の場合は五人で並んでいるということを表しています。また、5人以上は並べないようになっています。

以上がルールとなっています。

プログラム書かずに簡単に言うと、5人の中から何人か選択して、それを一列目か二列目に並べる(表示させる)
列は一列に三人まで、必ず左詰にする。
ということです。最初からこう書いた方が分かりやすかったですね。すみません...

Re:並び順

Posted: 2009年11月30日(月) 18:39
by non
確認ですが、retu1[/url]やretu2[/url]には既に表示したい番号が格納されており、
その番号が格納されるretu1やretu2のindexにより表示される位置(x,y座標)が決まっている。
で、この格納されている番号(1~5)に応じてfunc1~func5の関数を呼び出す。
で、あってますか?

あってるとしたら、仕様を次のように変更することは可能ですか?
1 retu1[/url]やretu2[/url]に、番号が入ってない場合は0が入っていると考えて良いか。

2 retu1[/url]とretu2[/url]の配列を一つにまとめて、retu[2][3]ではいけないのか。
  または、1次元配列にして retu[6]ではいけないのか。

3 func1~func5は別の関数名でなければいけないのか?
 例えば、func(番号、x、y)の引数ではいけないのか?

Re:並び順

Posted: 2009年11月30日(月) 19:44
by しいたけ
non様

>retu1[/url]やretu2[/url]には既に表示したい番号が格納されて...
はい、その通りです。
厳密に言うと、他の場所(ここで書いていないところ)で1から5までの数値を入れています。ここは今回のこととはあまり関係ないので省略しました。


1 それは、retu1[0]や、retu2[3]の値ということですよね。その通りで、番号が入っていない場合は0になっています。(0で初期化しています)

2 二次元配列も考えていたのですが、自分ではどういうプログラムにしようか分からずこうしてしまいました。当然、二次元配列でも問題ありません。retu[6]は考えませんでした。後々、一組目と二組目で違うことをしようと思っているのですが、その場合retu[0~2]とretu[3~5]で同じことが出きるならば、問題ありません。

3 func1~func5は個別に違う動作をさせます。なので、座標(何番目か)だけを取得して後は、別々の動作をさせるためにまとめることはできません。

以上です。宜しくお願いします。

Re:並び順

Posted: 2009年11月30日(月) 20:49
by non
こんなんでどうでしょ。
#include <stdio.h>
void func(int no,int x,int y)
{
	printf("func%d( %d , %d )\n",no,x,y);
}
int main(void)
{
	struct point{
		int y;
		int x;
	};
	struct point p[6]={{0,0},{0,10},{0,20},{10,0},{10,10},{10,20}};
	int retu[6]={3,1,5,2,4,0};
	int i;
	for(i=0;i<6;i++)
		if(retu!=0)
			func(retu,p.x,p.y);
	return 0;
}

>3 func1~func5は個別に違う動作をさせます。なので、座標(何番目か)だけを取得して後は、別々の動作をさせるためにまとめることはできません。

であれば、funcの関数内でswitch文でわけてください。

Re:並び順

Posted: 2009年11月30日(月) 23:36
by しいたけ
non様

ありがとうございます。全体を一つの列で考えると、確かにこう考えられますね。
ただ、列の並び方なのですが、これは固定ではなく指定することができるようにしています。
1 2 3 4 5 の中から一人ずつ選択していき、一列目か二列目に左詰で入れていくというものです。
つまり

3 1 5
2 4

になることもあれば、

3 1
5 2 4

になることもあります。
こういったために列を二つ作っていました。大変申し訳ございません。non様の書いていただいたソースを元に改変していたらこのことを思い出しました。

この場合は、やはり列を二つ作ると分かりやすいかと思うのですが、どのようにすれば良いのでしょうか。
お手数ですが、宜しくお願いします。

Re:並び順

Posted: 2009年11月30日(月) 23:58
by softya
nonさんに、ほとんどやっていただきましたが、2列版を書いてみました。
こんな感じで良いんですよね?
#include <stdio.h>

void func(int no,int x,int y)
{
	printf("func%d( %d , %d )\n",no,x,y);
}

int main(void)
{
	struct point{
		int y;
		int x;
	};

	struct point p[2][6]={ {{0,0},{0,10},{0,20}}, {{10,0},{10,10},{10,20}} };

	int retu[2][3]={ {3,1,0}, {2,4,5} };
	int i,j;
	for(i=0;i<2;i++) {
		for(j=0;j<3;j++) {
			if(retu[j]!=0) {
				func(retu[j],p[j].x,p[j].y);
			}
		}
	}
	return 0;
}

Re:並び順

Posted: 2009年12月01日(火) 00:11
by しいたけ
softya様

ありがとうございます。
こちらを元にソースを改変してみます。

それと、後一つ。これが長いコードを書いていた原因となるところであり、躓いていたところでした。
例えば、
3 1 5
2 4
の並びの場合、

二列目の 2, 4のxを 5, 15にしたいのです。

3 1 5
 2 4
こういった具合になります。

仮に列に一人しかいなかったら

  1
2 5 4
こういった具合になります。(1のxは10になります

つまり、列にいる人数に応じて、xの数値を変えたいのです。
もし宜しければ、こちらの方も宜しくお願いします。
お手数おかけしてすみません。

Re:並び順

Posted: 2009年12月01日(火) 00:40
by softya
いや、次々仕様を変更されても・・・。
ある程度まず自力でやってみてください。
ヒントと言うか参考になるコードは私とnonさんので色々とヒントになると思います。
やった上で分からない件はお答えします。
すいまんせん、今日は寝ます。おやすみなさい。

Re:並び順

Posted: 2009年12月01日(火) 05:31
by しいたけ
softya様

確かにそうですね。すみません。
二次元配列のコードを書いていただいて少し見えてきたので、勢いで質問してしまいました。
自分で少しやってみます。

Re:並び順

Posted: 2009年12月01日(火) 09:12
by non
> non様
>
> 3 1 5
> 2 4
>
> になることもあれば、
>
> 3 1
> 5 2 4
>
> になることもあります。
> こういったために列を二つ作っていました。

int retu[6]={3,1,0,5,2,4};
にすれば、良いだけのこと。2次元配列の方がわかりやすいならそれでもいいけど、
仕様は、なぜそうしなければいけないのかをよく考えて決めるようにしましょう。
後で、追加された仕様を見ると、
struct point p[6]={{0,0},{0,10},{0,20},{10,0},{10,10},{10,20}};
これも、必要ないですね。座標は計算で求めることになりそうです。
もしくは、配置パターンに応じた座標を用意するかです。