効率的なループの方法について
効率的なループの方法について
単純な話なのですが、いつも、ここだけキレイに書けないので、どうしたらいいものかと思っています。
歩く画像をループさせるときとか、よく
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
こうなってしまいます。
うまくスマートに同じようにループさせる方法ないでしょうか?
歩く画像をループさせるときとか、よく
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:効率的なループの方法について
#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; }パッと思いついたソースですが、どうぞ
意味を取り違えてたらすみません><。
Re:効率的なループの方法について
普通は下駄履きさせるか、- にならないようにするか、
for(i = LOOP; i > 0;) printf("%d\n",--i);
の様に1周固定にして、回す回数を、ループさせると思いますが・・・
こんなのでもいいかも。
0,1,2,3 だけであれば、abs(i) じゃなくて、(unsigned) i でもいいかも。
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 でもいいかも。
Re:効率的なループの方法について
3 2 1 0 3 2 1 0
のようにパターンを連続させたいんですよね?
(i+3)%LOOPなら そんなかんじになりますが。
LOOPが 4なら (i+3)%LOOP + 1ってところでしょうか。
のようにパターンを連続させたいんですよね?
(i+3)%LOOPなら そんなかんじになりますが。
LOOPが 4なら (i+3)%LOOP + 1ってところでしょうか。
Re:効率的なループの方法について
>大工さん
ありがとうございます^^
そうですね、仰るとおりです。ただ、私はカウンタとして使う変数を別途用意せず、
単純に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と言う事でしょうか?
Re:効率的なループの方法について
>管理人さん。
unsigned int型の整数を出力する時は%dでは無く%uで指定します。でなければ、printf内では同bit列を持つint型整数とみなして出力します。
1111 1111
これは基本的にintなら-1,unsignedなら65535となります。
間違ってたらすいません。
unsigned int型の整数を出力する時は%dでは無く%uで指定します。でなければ、printf内では同bit列を持つint型整数とみなして出力します。
1111 1111
これは基本的にintなら-1,unsignedなら65535となります。
間違ってたらすいません。
Re:効率的なループの方法について
うぐ、しばらく放置してから書いたら、とっくに答えだされてた。
別の回答で、インクリメントのループを
とした場合、デクリメントは
で行うことができます。
あんまり似てませんかね^ ^
別の回答で、インクリメントのループを
const int mx = 12; int n = 0; n = (n + 1) % mx;
とした場合、デクリメントは
const int mx = 12; int n = 0; n = (n + (mx - 1)) % mx;
で行うことができます。
あんまり似てませんかね^ ^
Re:効率的なループの方法について
あ~そうでした、もうすっかり使わない表記を忘れました、ありがとうございます(_ _||)
そうか、内部的なビット配列は変わらないんですね。符号ビットをどのように捉えるか、その違いだけですね。
じゃ
int i=-1;
int dat[2][2の32乗];
で
dat[1][(unsigned)i]
と書くと・・。どこを指すんでしょう・・。
dat[0][2の32乗-2]
を指すんでしょうか、それとも
dat[1][2の32乗-1]
を指すんでしょうか・・。まぁこんな事しませんが^^;
そうか、内部的なビット配列は変わらないんですね。符号ビットをどのように捉えるか、その違いだけですね。
じゃ
int i=-1;
int dat[2][2の32乗];
で
dat[1][(unsigned)i]
と書くと・・。どこを指すんでしょう・・。
dat[0][2の32乗-2]
を指すんでしょうか、それとも
dat[1][2の32乗-1]
を指すんでしょうか・・。まぁこんな事しませんが^^;
Re:効率的なループの方法について
>dat[1][(unsigned)i]
>と書くと・・。どこを指すんでしょう・・。
試してみればいいのでは(^^;
この場合、int が 4byte void * が 4byte の事が多いので、
同じ場所であると思いますが、
(unsigned short) でキャストすれば、結果は出て来そうです。
PS、
前のやつで、
の方が、スマートだった気がします。
>と書くと・・。どこを指すんでしょう・・。
試してみればいいのでは(^^;
この場合、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); }
の方が、スマートだった気がします。
Re:効率的なループの方法について
# 管理人さん
>それは(i+3)%LOOPの部分がiをプラスにしているということでしょうか
そうです。それで負にならないようにしています。
>この件ではキャラがマイナスの座標にくると
こういう用途なら、座標からでなく、アニメーションカウンタを別途に持った方が
いいと思います。
そういう方式であれば、アニメーションを管理する構造体なりクラスなりを
作ってアニメーションそのものを汎用的にすることもできますし。
# Hermitさん
>方が、スマートだった気がします
iが -1の時とか、i%LOOPで負の剰余計算になるのですが、
(古いC言語だと、環境によって値が変わるので)これって微妙じゃないですか?
>それは(i+3)%LOOPの部分がiをプラスにしているということでしょうか
そうです。それで負にならないようにしています。
>この件ではキャラがマイナスの座標にくると
こういう用途なら、座標からでなく、アニメーションカウンタを別途に持った方が
いいと思います。
そういう方式であれば、アニメーションを管理する構造体なりクラスなりを
作ってアニメーションそのものを汎用的にすることもできますし。
# Hermitさん
>方が、スマートだった気がします
iが -1の時とか、i%LOOPで負の剰余計算になるのですが、
(古いC言語だと、環境によって値が変わるので)これって微妙じゃないですか?
Re:効率的なループの方法について
2の32乗の要素を持った配列は用意しようと思いませんでした(_ _||)
え~と、、大体4億3千万位だから・・。
4,300,000,000Bで4GBですか^^;
なるほど、ありがとうございます。
是非今後に活かしていきたいと思います。
え~と、、大体4億3千万位だから・・。
4,300,000,000Bで4GBですか^^;
なるほど、ありがとうございます。
是非今後に活かしていきたいと思います。
Re:効率的なループの方法について
> iが -1の時とか、i%LOOPで負の剰余計算になるのですが、
> (古いC言語だと、環境によって値が変わるので)これって微妙じゃないですか?
そうなんですか?
i が -1 の時は、i%4 は、-1 か、3 だと思うのですが、
他の数値になる可能性があるのでしょうか?
有る様だったら、その手は使えませんね!
> (古いC言語だと、環境によって値が変わるので)これって微妙じゃないですか?
そうなんですか?
i が -1 の時は、i%4 は、-1 か、3 だと思うのですが、
他の数値になる可能性があるのでしょうか?
有る様だったら、その手は使えませんね!
Re:効率的なループの方法について
除算は
B(A/B)+A%B==A
が成り立つように結果がでます。なおかつ、abs(A%B)がBよりも小さい用に定義されます。だから、-1か3になるはずです。
B(A/B)+A%B==A
が成り立つように結果がでます。なおかつ、abs(A%B)がBよりも小さい用に定義されます。だから、-1か3になるはずです。