こんにちは。
Pythonぜサイコロを回転させるプログラムを作りたいのですが、
「上」なら上方向に一回転
「右」なら右方向に一回転
というようにサイコロを回転させたとします。
この時、一回転ごとに下にくる面が何か、を出力したいです。
私が30分考える限りでは、下面の数字と正面の数字を得て、それらについて全て場合分けする、というやり方しか思いつきませんでした。
このやり方だと6×5×上下右左で120通り自分で場合分けしなければいけません。
それよりもサイコロという形の特性を用いた良い解き方が必ずあるはずです。ただし私には思いつきませんでした。
知恵を拝借したいです。
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
... [上下前後右左]を作って、それぞれ4方向に回転させた時に各値がどう変わるかで4通りの場合分けでいいことに気づきました。...
はい、それで良いと思います。
dict で サイコロを表現し、 4方向の回転のメソッドを定義してみました。
python3
1def up(dice): 2 f, u, d, b = [dice["front"], dice["up"], dice["down"], dice["back"]] 3 dice["front"] = d 4 dice["up"] = f 5 dice["down"] = b 6 dice["back"] = u 7 return dice 8 9def down(dice): 10 f, u, d, b = [dice["front"], dice["up"], dice["down"], dice["back"]] 11 dice["front"] = u 12 dice["up"] = b 13 dice["down"] = f 14 dice["back"] = d 15 return dice 16 17def left(dice): 18 f, l, r, b = [dice["front"], dice["left"], dice["right"], dice["back"]] 19 dice["front"] = r 20 dice["left"] = f 21 dice["right"] = b 22 dice["back"] = l 23 return dice 24 25def right(dice): 26 f, l, r, b = [dice["front"], dice["left"], dice["right"], dice["back"]] 27 dice["front"] = l 28 dice["left"] = b 29 dice["right"] = f 30 dice["back"] = r 31 return dice 32 33def show(dice): 34 print(" ", dice["up"], " ") 35 print(dice["left"], dice["front"], dice["right"], dice["back"]) 36 print(" ", dice["down"], " ") 37 print() 38 39def init_dice(): 40 return { 41 "front": 1, "back": 6, 42 "up": 3, "right": 5, "down": 4, "left": 2 43 } 44 45dice = init_dice() 46show(dice) 47dice = up(dice) 48show(dice) 49dice = down(dice) 50show(dice) 51 52dice = init_dice() 53dice = left(dice) 54show(dice) 55dice = right(dice) 56show(dice)
サイコロの展開図を表示するようにしてます。
追記
展開図の様子を 2次元配列(Matrix) で表現し、回転操作を Matrix の乗算で表現することも可能と思います。
追記2
numpy を使って行列の演算で書いて見ました。(乗算だけでできると思っていたが、足し算やその他の演算も使いました)
m.py
python3
1import numpy as np 2 3def up(dice, repeat=1): 4 front_ary = np.array([ 5 [0, 0, 0, 0], 6 [0, 1, 0, 0], 7 [0, 0, 0, 0], 8 [0, 0, 0, 0] 9 ]) 10 11 for i in range(0, repeat % 4): 12 d1 = np.matmul(dice, front_ary)[[1, 2, 3, 0]] 13 d2 = np.matmul(front_ary, dice) 14 d2[1,1] = 0 15 dice = d1 + d2 16 dice[1,3] = dice[3, 1] 17 return dice 18 19def down(dice, count = 1): 20 return up(dice, -count) 21 22def left(dice, repeat=1): 23 return up(dice.transpose(), repeat).transpose() 24 25def right(dice, count = 1): 26 return left(dice, -count) 27 28dice = np.array([ 29 [0, 3, 0, 0], 30 [2, 1, 5, 6], 31 [0, 4, 0, 0], 32 [0, 6, 0, 0] 33]) 34print(dice) 35print(up(dice)) 36print(down(up(dice))) 37print() 38 39print(dice) 40print(left(dice)) 41print(right(left(dice)))
投稿2018/11/15 14:35
編集2018/11/16 14:40総合スコア22324
0
サイコロは、hayataka2049さんの指摘の通り、相対する面の合計は7なので4種類になります。(組み合わせは8種類ありますが、回転させると同じになる)したがって、初期設定時にどのサイコロを使うか、上面と正面の値が何か、が決定すると6面の値が決定するので、以後は回転の向きと方向によって値をずらしていけばいいことになります。
つまり、babblemanさんのいう場合分けは4種類×2パターンに整理できると思います。(サイコロが決定していて、上面の値が決まっていると正面が取りうる値は2パターンになる)
理想はサイコロの立体形状をデータに表現して、回転を計算する方法が理想の気がします(これなら「上」や「右」角度で表現できるので、場合分けが不要)がコードが想像できませんでした
投稿2018/11/16 01:26
総合スコア3376
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
サイコロの形は一天地六(1と6が上下として、5234が東西南北に対応)
基本的には4回要るんじゃないかなぁ。
2連続で同じ方向に回したときは自明ですね。100回連続で同じ方向に回しても自明です。上手く使うと計算ケチれるのかな?
最終的に何が入力で何を出力にすれば良い問題なのか実はよくわからない・・・。
投稿2018/11/15 16:28
編集2018/11/15 16:41総合スコア30933
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
少し考えてみたのですが、初期状態のサイコロ配列
[上下前後右左]を作って、それぞれ4方向に回転させた時に各値がどう変わるかで4通りの場合分けでいいことに気づきました。
ただ、賢いやり方とは言えないと思います。
投稿2018/11/15 13:16
総合スコア107
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/15 13:53
2018/11/15 14:07
2018/11/15 14:17 編集
2018/11/15 14:21
2018/11/15 14:24
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。