効率的なループの方法について

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

効率的なループの方法について

#1

投稿記事 by 管理人 » 18年前

単純な話なのですが、いつも、ここだけキレイに書けないので、どうしたらいいものかと思っています。

歩く画像をループさせるときとか、よく
0->1->2->3->0->1->2->3...というループを作りたい時があります。
これは

for(i=0;i<12;i++)
printf("%d\n",i%LOOP);

こう書けば出来ますが、カウンタがマイナスになったときは

for(i=3;i>-4;i--)
printf("%d\n",abs(i)%LOOP);

実行結果

3
2
1
0
1
2
3

こうなってしまいます。
うまくスマートに同じようにループさせる方法ないでしょうか?

大工

Re:効率的なループの方法について

#2

投稿記事 by 大工 » 18年前

#include <stdio.h>

int main(void) {

  int i, cnt;

  for(i = 0, cnt = 0; cnt < 12; i++, cnt++) {

      printf("%2d\n", i);
      if(3 == i) i = -1;
  }

  printf("-------------------------\n");

  for(i = 3, cnt = 0; cnt < 12; i--, cnt++) {

      printf("%2d\n", i);
      if(0 == i) i = 4;
  }

  return 0;
}
パッと思いついたソースですが、どうぞ

意味を取り違えてたらすみません><。

Hermit

Re:効率的なループの方法について

#3

投稿記事 by Hermit » 18年前

普通は下駄履きさせるか、- にならないようにするか、

for(i = LOOP; i > 0;) printf("%d\n",--i);
の様に1周固定にして、回す回数を、ループさせると思いますが・・・

こんなのでもいいかも。
#define LOOP 4
	for(i=3;i>-4;i--) {
		int j = i;
		while ( j < 0) j += LOOP * 100;
		printf("%d\n",j % LOOP); 
	}

0,1,2,3 だけであれば、abs(i) じゃなくて、(unsigned) i でもいいかも。

Justy

Re:効率的なループの方法について

#4

投稿記事 by Justy » 18年前

 3 2 1 0 3 2 1 0
 のようにパターンを連続させたいんですよね?

 (i+3)%LOOPなら そんなかんじになりますが。
 LOOPが 4なら (i+3)%LOOP + 1ってところでしょうか。

管理人

Re:効率的なループの方法について

#5

投稿記事 by 管理人 » 18年前

>大工さん
ありがとうございます^^
そうですね、仰るとおりです。ただ、私はカウンタとして使う変数を別途用意せず、
単純に1行の更に少ない部分だけで実現する方法が無いか探していましたm(_ _)m
変に短く書こうとするよりキレイに書いたほうがいいかもしれませんね^^;

>Hermitさん
ご回答ありがとう御座います。
なるほど、unsignedすればいいんですね。
私がしたかったのは、例えば、FF1やドラクエ1のように、
RPGマップ上をキャラがテクテク歩く場面のことで、
32ピクセルずつ区切られた区間は更に4つに区切られ、
最初の8ピクセルにいる時は、0の画像
 次の8ピクセルにいる時は、1の画像
 次の8ピクセルにいる時は、2の画像
 次の8ピクセルにいる時は、3の画像
これを繰り返す事でテクテク歩くように見えると思います。
img[4]で用意して、それぞれにキャラが歩く画像が入っているとすると
img[(ch.x%32)/8]
で簡単に書けると思います。
ただ、キャラが区間の途中で止まるようなゲームは足が上がった状態でとまったりすると思うので、
とういうのには使えませんが。
この件ではキャラがマイナスの座標にくると、マイナスの要素をさしたり、順番が狂ったりしてしまうと言う事でした。

他の件で、特にこのことを考えたのは、他トピ「ポイントカードの日付について」のプログラムを書いていたときです。
12月ループするカレンダーは次の月になるとき、
month = (++month)%12
で表せますが、戻る時、
month = (--month)%12
では表せないので、似たような表現が出来ないかと考えたからでした。

、、でHermitさんの仰るプログラムを書いてみたんですが、よくわからない状態に・・。

#include <stdio.h>

int main(void){

	unsigned short int num1 = -1;
	unsigned int num2 = -1;

	printf( "num1 = %d\n", num1 );
	printf( "num2 = %d\n", num2 );

	return 0;
} 

実行結果

num1 = 65535
num2 = -1

なんでunsigned intがマイナスになるんでしょう;
とんでもない勘違いをしてたらすみません(_ _||)

>Justyさん
ご回答ありがとう御座います。
なるほど、それは(i+3)%LOOPの部分がiをプラスにしているということでしょうか?
つまり
for(i=10;i>-10;i--)
なら
(i+10)%LOOPと言う事でしょうか?

tk-xleader

Re:効率的なループの方法について

#6

投稿記事 by tk-xleader » 18年前

>管理人さん。

unsigned int型の整数を出力する時は%dでは無く%uで指定します。でなければ、printf内では同bit列を持つint型整数とみなして出力します。

1111 1111

これは基本的にintなら-1,unsignedなら65535となります。

間違ってたらすいません。

tk-xleader

Re:効率的なループの方法について

#7

投稿記事 by tk-xleader » 18年前

すいません。上のbitについてはsizeof(int)=2である事を前提にしています。

GPGA

Re:効率的なループの方法について

#8

投稿記事 by GPGA » 18年前

表示がおかしいのはprintfの書式の問題です。
%dでなく%uを使用すれば問題ないでしょう。

GPGA

Re:効率的なループの方法について

#9

投稿記事 by GPGA » 18年前

うぐ、しばらく放置してから書いたら、とっくに答えだされてた。

別の回答で、インクリメントのループを
const int mx = 12;
int n = 0;
n = (n + 1) % mx;
 
とした場合、デクリメントは
const int mx = 12;
int n = 0;
n = (n + (mx - 1)) % mx;
 
で行うことができます。
あんまり似てませんかね^ ^

管理人

Re:効率的なループの方法について

#10

投稿記事 by 管理人 » 18年前

あ~そうでした、もうすっかり使わない表記を忘れました、ありがとうございます(_ _||)

そうか、内部的なビット配列は変わらないんですね。符号ビットをどのように捉えるか、その違いだけですね。
じゃ
int i=-1;
int dat[2][2の32乗];

dat[1][(unsigned)i]
と書くと・・。どこを指すんでしょう・・。
dat[0][2の32乗-2]
を指すんでしょうか、それとも
dat[1][2の32乗-1]
を指すんでしょうか・・。まぁこんな事しませんが^^;

Hermit

Re:効率的なループの方法について

#11

投稿記事 by Hermit » 18年前

>dat[1][(unsigned)i]
>と書くと・・。どこを指すんでしょう・・。
試してみればいいのでは(^^;

この場合、int が 4byte void * が 4byte の事が多いので、
同じ場所であると思いますが、
(unsigned short) でキャストすれば、結果は出て来そうです。


PS、
前のやつで、
#define LOOP 4
	for(i=3;i>-4;i--) {
		int j = i % LOOP;
		if ( j < 0) j += LOOP;
		printf("%d\n",j % LOOP); 
	}

の方が、スマートだった気がします。

Justy

Re:効率的なループの方法について

#12

投稿記事 by Justy » 18年前

# 管理人さん
それは(i+3)%LOOPの部分がiをプラスにしているということでしょうか
 そうです。それで負にならないようにしています。


この件ではキャラがマイナスの座標にくると
 こういう用途なら、座標からでなく、アニメーションカウンタを別途に持った方が
いいと思います。

 そういう方式であれば、アニメーションを管理する構造体なりクラスなりを
作ってアニメーションそのものを汎用的にすることもできますし。


# Hermitさん
方が、スマートだった気がします
 iが -1の時とか、i%LOOPで負の剰余計算になるのですが、
(古いC言語だと、環境によって値が変わるので)これって微妙じゃないですか?

管理人

Re:効率的なループの方法について

#13

投稿記事 by 管理人 » 18年前

2の32乗の要素を持った配列は用意しようと思いませんでした(_ _||)
え~と、、大体4億3千万位だから・・。
4,300,000,000Bで4GBですか^^;

なるほど、ありがとうございます。
是非今後に活かしていきたいと思います。

Hermit

Re:効率的なループの方法について

#14

投稿記事 by Hermit » 18年前

>  iが -1の時とか、i%LOOPで負の剰余計算になるのですが、
> (古いC言語だと、環境によって値が変わるので)これって微妙じゃないですか?

そうなんですか? 
i が -1 の時は、i%4 は、-1 か、3 だと思うのですが、
他の数値になる可能性があるのでしょうか?

有る様だったら、その手は使えませんね!

tk-xleader

Re:効率的なループの方法について

#15

投稿記事 by tk-xleader » 18年前

除算は

B(A/B)+A%B==A

が成り立つように結果がでます。なおかつ、abs(A%B)がBよりも小さい用に定義されます。だから、-1か3になるはずです。

Justy

Re:効率的なループの方法について

#16

投稿記事 by Justy » 18年前

i が -1 の時は、i%4 は、-1 か、3 だと思うのですが、
 あー、そうか、どちらの値でも動くわけですね。
 失礼しました。

閉鎖

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