🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Q&A

4回答

1709閲覧

テトリスでのミノ(二次元配列)の回転について

blenderegg

総合スコア13

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

0グッド

0クリップ

投稿2019/12/02 11:16

編集2019/12/02 11:18

前提・実現したい

godotゲームエンジンを使用しています
pythonに似た言語を使用

テトリスでミノを回転させたいです

var array = [
[1,2],
[3,4]
]
これはミノではないですが、シンプルな二次元配列を用意しました。これを以下のように時計回りに回転させたいです。
var array = [
[3,1],
[4,2]
]

https://toburau.hatenablog.jp/entry/20140324/1395679650
90度の回転であれば、xとyを入れ替えればいいとあります。任意の角度の場合はsin cosが必要だと思います。
以下のようにしたのですが、望む結果にはなりません。
この、xとyを入れ替えるという部分がよく分かりませんので、アドバイスをお願いします。

var block = [ [1,2], [3,4] ] func _ready(): for y in block.size(): for x in block[y].size(): block[y][x] = block[x][y] block[x][y] = block[y][x] print(block)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

https://toburau.hatenablog.jp/entry/20140324/1395679650

で書かれているのは単なる2次元の回転行列の話であって,
【座標(x,y)を「原点周りに」θだけ回転させたら,回転後に(x',y')に行く】という話をしているだけです.

あなたがやろうとしていることは,配列の中身を回転させる話なので,「どこを中心に」回転させるのか,という事柄を考える必要があります.

xとyを入れ替える

とかいう謎の文言は一旦忘れて,配列indexを座標値とする世界の上での適切な (x,y)←→(x',y') の変換を導出して用いてください.


絵を描いてみました.
何やらxとかyとかいう言葉に振り回されているように見受けるので,(u,v)という新しい座標系を明示的に導入.(※(u,v)の座標系は別に下図の形じゃなくても自分が扱いやすいものを考えれば良い)

この座標系では,2x2の配列の4個の要素の「丁度ど真ん中」に原点をとっています.
回転作業をこの(u,v)の世界で考えてみますと,90度回転とは
あなたがどこかで目にした「x座標とy座標(まぁここではu座標とv座標ですが)を入れ替える,ただし一方の側は-1倍する」という話になっている,ということですね.
回転前の座標(u,v)と90度回転後の座標(u',v')の関係というのが,
u'=-v
v'=u
になっている,という話.

あとは,(u,v)←→(x,y) の対応関係(相互の変換)を用いれば「配列の中身を回転する処理」ができますよね.
「配列の中身を回す処理」によって,回転前に位置(x,y)にあった要素が回転後には位置(x',y')に移動するとき,この
(x,y)←回す→(x',y') という前後の座標の対応関係(変換)を,
(x,y)←→(u,v)←回す→(u',v')←→(x',y') として考えればよいわけです.
イメージ説明

投稿2019/12/04 09:02

編集2019/12/05 03:04
fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

最終目標と質問があっていないと思います。
テトリスであれば、配列を固定で持つのが良いです。

I ブロックの180°回転時に計算で処理すると「ズレ」ます。

投稿2019/12/04 02:20

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2019/12/04 02:42

■■■■ → 180度回転する → ■■■■ ズレとは何か.
退会済みユーザー

退会済みユーザー

2019/12/04 02:48

配列で回転やってみw
fana

2019/12/04 03:06

言わんとしていていることの想像は付くのですが,その話で質問者に伝わるのか?という観点でコメントしました. 要は「配列バッファ内で」の「パターンの原点」というのはどこになるのか的な話ですよね. 「テトリスで」ブロック回転を計算でやろうという話において当該原点を配列の[0][0]に固定で取るような処理を想定して問題提起されているんですよね.
fana

2019/12/04 03:08

(例えばIブロックのパターン表現に4x4サイズの配列を使って,その上でパターン回転をする世界の話ですよね,きっと.)
fana

2019/12/04 03:21

「この配列バッファでの処理というのは回転した"形状"を求めているのであって,パターンの位置(オフセット量)に関しては何ら定義していないのだ,ということをうっかり忘れてしまうとテトリス的にはまずい挙動になりますぞ」という予防的な御指摘,とでも書けば解りやすかったか.
退会済みユーザー

退会済みユーザー

2019/12/04 03:53

ちょっと何が言いたいのか理解できませんが、私の回答は私の意見として特に過不足ありません。
fana

2019/12/04 04:00 編集

この回答での「ズレ」というのが, □□□□ ■■■■ □□□□ □□□□ というデータを180度回転したときに □□□□ □□□□ ■■■■ □□□□ となり,回転前と■の位置が異なる,ということを指すのだと思ったのですが,違いましたか.(であれば,「ズレ」とは何ですか?)
退会済みユーザー

退会済みユーザー

2019/12/04 04:02

細かいことを書くつもりは無いです。 どちらかというと、この回答をトリガーに設計作業/調査作業をしてほしいので。
fana

2019/12/04 04:11 編集

>「ズレ」 が何を意味するのか,少なくとも読者1名(私)が把握できていないのですが,補足説明はいただけないということですね…とても残念です.(これでは「私が」トリガーにできないです…) > 配列で回転やってみw と言われたから(脳内で,ですが)やってみたのに…
退会済みユーザー

退会済みユーザー

2019/12/04 04:12

> 細かいことを書くつもりは無いです。 どちらかというと、この回答をトリガーに設計作業/調査作業をしてほしいので。
fana

2019/12/04 04:19

了解しました. この回答における「ズレ」の意味するところは最後までわかりませんでしたが, 全回転姿勢分のデータを固定で与える方法ならば,配列index座標系内における回転姿勢間の相対的な座標オフセット量をあらかじめ解決済みのデータを与えることができるため扱いが楽になる,という話だと勝手に解釈しつつ,それはその通りだと思うので高評価を押して終了します.質問者でもないのにお付き合いいただきありがとうございました.
fana

2019/12/04 05:17

おっと,「終了します」と書きましたが,質問者に誤解を与えそうな事柄に関する肝心なことを書き忘れたので,それだけ書いておきます. > 最終目標と質問があっていない なんてことは全くないと思います.最終的に解決すべき事柄は【パターン形状を定義する配列の座標系とゲームフィールド(?)の座標系との間の写像】であり,該写像に必要な3自由度のうちの1つの自由度に関する計算原理に関する質問なのですから,目標に対して妥当.
guest

0

90度の回転であれば、xとyを入れ替えればいいとあります。任意の角度の場合はsin cosが必要だと思います。

以下のようにしたのですが、望む結果にはなりません。
この、xとyを入れ替えるという部分がよく分かりませんので、アドバイスをお願いします。

90°だけを固定の方向に回転させたいのか、任意の角度に回転したいのか、分かりません。

90°だけ回転させたいなら言語が違いますがこちらが参考になると思います。

任意の角度に回転は仰る通り、sin cosが必要です。3次元のZ軸回転と同じなので、自分で調べましょう。

投稿2019/12/03 05:55

stdio

総合スコア3307

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blenderegg

2019/12/04 02:12

いえ、90度だけ回転させたいです。 テトリスに使用します。
stdio

2019/12/04 03:27

うん、なら参照のURLを参考にすれば出来ると思います。 言語は違うけど図があるから分かりやすいです。
blenderegg

2019/12/04 07:42

回答どうも。 このxとyを入れ替えるというのは、以下の配列でいうとどういうことですか? [ [1,2], [3,4] ] 行と列を入れ替えるということならば [ [2,1], [4,3] ] という結果になるので、90度回転とはならないです。
stdio

2019/12/05 00:52 編集

テトリスなら、マスを入れ替えるだけなので、90度回転をしているように見せかけることは可能です。 後、テトリスなら3次元配列を使って、4回転分の行列を保持する方が処理的には、やりやすいですよ。
guest

0

こういうことじゃないですか。

Python

1for y in block.size(): 2 for x in block[y].size(): 3 #時計回りのとき 4 xx = y #X座標をY座標に代入 5 yy = -x #Y座標の符号を反転してX座標に代入 6 tmp[yy][xx] = block[x][y] 7 8block = tmp

投稿2019/12/02 11:47

tatamyiwathy

総合スコア1045

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

blenderegg

2019/12/03 06:54

回答ありがとうございます 理解に時間がかかってます そもそもx座標とは何のことですか? [ [1,2], [3,4] ] この二次元配列の1と3のことですか?
fana

2019/12/03 07:14

ご自身が示したコードでもxとかyとかいう記述が見られるのだが…その意図は?
blenderegg

2019/12/04 02:59 編集

それはインデックスです yは行で、xはその行にはいる数字の位置を表しています
fana

2019/12/04 03:46

とりあえずこの話の範疇では 配列のインデックス=座標 と考えて良いと思います.(行方向のindexを「y座標」,列方向のindexを「x座標」と呼んでいる.) なので,その2次元配列の絵で言えば, 左上の値が1な要素のxy座標が(x,y)=(0,0), その右側の値が2な要素のxy座標は(x,y)=(1,0), 右下の値が4な要素のxy座標は(x,y)=(1,1) という.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問