競プロのライブラリ整理~サイコロ~


ICPC用にサイコロのライブラリを作成しました。本番ではサイコロが出なかったので悔しいですが、今後出る方の参考になれば嬉しいです。回転操作の実装などはうしさんのライブラリを参考にしています。
また、それぞれの面のアルファベットおよび回転の関数は自分のわかりやすい名前にしているので、使う際には都合の良いように書き換えてください。

サイコロの図

下図において、サイコロの面のuはup,dはdown,fはfront,bはback,lはleft,rはrightを表します。つまり下図においてy軸の負の方向が前面を表し,x軸の正の方向が右面を表します。他の面についても同様に英語に対応します。

コードの説明

サイコロを置くとき、反対側には来ない二面を指定するとサイコロの置き方は一意に決まります。また、サイコロの置き方は上の面を固定してから横の面の場合分けを考えることで決まるので、全部で24通りあります。その24通りをすべて書き出したのがクラス変数のstateになります。つまり、初期化の時点でわかっている2面の情報を与えることで初期化を行うことができます。また、初期化で与えられた二面を持つサイコロが存在しないときはエラー出力をするようにしています。そして、サイコロの初期位置座標で初期化する必要があることも注意してください。

初期化が行えると、あとは6方向の回転を実装するのみとなります。このとき、それぞれのRotate関数には大文字のアルファベットが末尾についておりそれぞれ回転方向を表します。また、y軸の正方向を北(North),負方向を南(South),x軸の正方向を東(East),負方向を西(West)としています。そして、座標を変えない回転方向は前面から見て左方向(Left),右方向(Right)としています。この関数内ではサイコロの面を入れ替えるとともに、座標を変える4方向の回転については座標の値も更新します。

コード

dice.py
# coding: UTF-8
import sys

class Dice:
    #サイコロの全状態(u,d,f,b,l,rの順)(u+d=f+b=l+r=7が成り立つ)
    state=[[1,6,2,5,4,3],[1,6,3,4,2,5],[1,6,4,3,5,2],[1,6,5,2,3,4],
           [2,5,1,6,3,4],[2,5,3,4,6,1],[2,5,4,3,1,6],[2,5,6,1,4,3],
           [3,4,1,6,5,2],[3,4,2,5,1,6],[3,4,5,2,6,1],[3,4,6,1,2,5],
           [4,3,1,6,2,5],[4,3,2,5,6,1],[4,3,5,2,1,6],[4,3,6,1,5,2],
           [5,2,1,6,4,3],[5,2,3,4,1,6],[5,2,4,3,6,1],[5,2,6,1,3,4],
           [6,1,2,5,3,4],[6,1,3,4,5,2],[6,1,4,3,2,5],[6,1,5,2,4,3]]

    #u,d,f,b,l,rをそれぞれ0,1,2,3,4,5としてstate1,state2に指定
    #value1,value2はそれぞれstate1,state2に対応する面の目
    #nowは初期位置の座標
    #適切でない場合はエラー出力
    def __init__(self,state1,value1,state2,value2,now):
        self.now=[now[0],now[1]]
        for i in range(24):
            if Dice.state[i][state1]==value1 and Dice.state[i][state2]==value2:
                self.u,self.d,self.f,self.b,self.l,self.r=Dice.state[i]
                break
        else:
            print('Error:Constructor\'s Argument is missing.',file=sys.stderr)
            exit()

    #上から見てy軸の+方向に回転(後面が下面に!)
    def RotateN(self):
        self.d,self.f,self.u,self.b=self.b,self.d,self.f,self.u
        self.now[1]+=1

    #上から見てy軸の-方向に回転(前面が下面に!)
    def RotateS(self):
        self.d,self.f,self.u,self.b=self.f,self.u,self.b,self.d
        self.now[1]-=1

    #上から見てx軸の+方向に回転(右面が下面に!)
    def RotateE(self):
        self.d,self.l,self.u,self.r=self.r,self.d,self.l,self.u
        self.now[0]+=1

    #上から見てx軸の-方向に回転(左面が下面に!)
    def RotateW(self):
        self.d,self.l,self.u,self.r=self.l,self.u,self.r,self.d
        self.now[0]-=1

    #前から見て左回転(反時計回り)
    def RotateL(self):
        self.f,self.l,self.b,self.r=self.r,self.f,self.l,self.b

    #前から見て右回転(時計回り)
    def RotateR(self):
        self.f,self.l,self.b,self.r=self.l,self.b,self.r,self.f

verifyした問題

AOJ Biased Dice
提出→http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4985962