3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FOR文の向きを意識する必要性

Last updated at Posted at 2018-06-01

皆様初めまして。
タイトルの通り、繰り返し処理の方向を考えないと
ハマる(何が悪いか分からない)と言う話しです。

コンパイルは通るけど動作がおかしい!と
3,4時間苦悩してました。

DXライブラリを一部使っているので軽く説明を交えながら。
(全部載せると無駄も長いので一部)
以下問題のソース↓

bad.cpp
while(1){
       if (CheckHitKey(KEY_INPUT_DOWN) == 1) {
			count++;
			if (count % 5 == 0) {
				for (i = 0; i < 20; i++) {
					for (j = 0; j < 10; j++) {
						if (masu[i][j] == 1 && masu[i+1][j] == 0) {
							masu[i + 1][j] = 1;
							masu[i][j] = 0;
						}
					}
				}
			}
		}
        if (CheckHitKey(KEY_INPUT_UP) == 1) {
			count++;
			if (count % 5 == 0) {
				for (i = 0; i < 20; i++) {
					for (j = 0; j < 10; j++) {
						if (masu[i][j] == 1 && masu[i - 1][j] == 0) {
							masu[i - 1][j] = 1;
							masu[i][j] = 0;
						}
					}
				}
			}
		}
		if (CheckHitKey(KEY_INPUT_RIGHT) == 1) {
			count++;
			if (count % 5 == 0) {
				for (i = 0; i < 20; i++) {
					for (j = 0; j < 10; j++) {
						if (masu[i][j] == 1 && masu[i][j+1] == 0) {
							masu[i][j+1] = 1;
							masu[i][j] = 0;
						}
					}
				}
			}
		}
		if (CheckHitKey(KEY_INPUT_LEFT) == 1) {
			count++;
			if (count % 5 == 0) {
				for (i = 0; i < 20; i++) {
					for (j = 0; j < 10; j++) {
						if (masu[i][j] == 1 && masu[i][j-1] == 0) {
							masu[i][j-1] = 1;
							masu[i][j] = 0;
						}
					}
				}
			}
		}
}

上下左右キーで配列内の数値を入れ替える物で、
上から各キーが押されたら、カウントする変数に加算し、
一定時間押されたら自分(この場合0)を全配列から探し、
0が見つかったら移動先が移動できる条件(この場合0)
なら、移動先と現在の数値を入れ替えるというもの。

ぱっと見は違和感がない。(最初は自分の配列の上下左右を入れ替えればいいと思ってたため向きなどを考えてなかった)
だが 実行してみると上キーと左キーは動くのだけれども
下キーは一回押したら現在の位置から真下に
右にいたっては右下に必ずいってしまう。

考えていたら、ある事に気が付いた。
masu[i][j+1] = 1;
masu[i+1][j] = 1;
右キーと下キーのどちらも、現在の配列より+で移動先に入れていた。
そこから繰り返し処理の流れ(方向)と現在の配列より一歩先を変更する処理が重なり、ぶっとんだ移動のしかたをしているのではと予測した。

イメージ ↓

a.png

これを回避するためには、
Iの向きとJの向きを変えてやれば、解決する。
具体的には右と下に行きたいときは、データの入れ替えと逆にしてやれば解決する。

イメージ2 ↓

image.png

以上のことを踏まえて直すと右キーと下キーはこうなる。

good.cpp
    if (CheckHitKey(KEY_INPUT_DOWN) == 1) {
			count++;
			if (count % 5 == 0) {
				for (i = 20; i >= 0 ; i--) {
					for (j = 10; j >= 0; j--) {
						if (masu[i][j] == 1 && masu[i+1][j] == 0) {
							masu[i + 1][j] = 1;
							masu[i][j] = 0;
					    }
					}
				 }
			 }
    }
    if (CheckHitKey(KEY_INPUT_RIGHT) == 1) {
			count++;
			if (count % 5 == 0) {
				for (i = 20; i >= 0; i--) {
					for (j = 10; j >= 0; j--) {
						if (masu[i][j] == 1 && masu[i][j+1] == 0) {
							masu[i][j+1] = 1;
							masu[i][j] = 0;
						}
					}
				 }
			 }
     }

これで上下左右すっきり移動することができました。
このように注意しないとどこかではまるかもしれません。
(そもそもこんな考えのもの使う機会がない)

【まとめとか感想】

画像とか後半しんどくなって適当になってきた。

この記事書くのに初めてとはいえ
一時間半かかっているので
いいねください。

3
1
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?