続続・Javaでサイコロ(六面体)のアクションを考えてみる

f:id:ts0818:20190504230158j:plain

勘の良い方はもうお気づきやもしれませんが、そう!
ついに、サイコロが2つに増えてしまうってパターンですね、どうもボクです。 

というわけで、今回も、サイコロのアクションについてです。

 

全然関係ない話ですが、「三匹が斬る!」 シリーズを子供の頃に見てたな~、と思ってたら、Amazon でDVD販売してるんですね。


続続・三匹が斬る! DVD-BOX

⇧  役所広司とか若っ!

 

はい、すみません、脱線しました。

では、レッツトライ~。

 

サイコロが同じであるか、そうでないか、それが問題だ

ということで、2つのサイコロがあり、その作りが 同じかどうかってのを判定するって問題ですね。

judge.u-aizu.ac.jp

⇧  例のごとく、上記サイト様の問題です。

Eclipseを起動し、適当なJavaプロジェクト、クラスを作成。(前からのを流用してるんですが、「Dice01.java」を「Dice.java」にリファクタリングで名前を変更してます。)

f:id:ts0818:20190505110950p:plain

ソースコードはこんな感じ。

Dice.java

package dto;

public class Dice {
  private int number[];
  private int work[];

  public Dice() {

  }

  public Dice(String[] args) {
    number = new int[args.length];
    work = new int[args.length];
    // サイコロの初期化
    for (int i = 0; i < args.length; i++) {
      number[i] = Integer.parseInt(args[i]);
    }
  }

  public void rollDice(char action, int num) {
    for (int i = 0; i < num; i++) {
      this.work[i] = this.number[i];
    }

    switch (action) {
    case 'E':
      // West→Top, South→South, Top→East, Bottm→West, North→North, East→Bottom
      setNumber(work[3], work[1], work[0], work[5], work[4], work[2]);
      break;
    case 'N':
      // South→Top, Bottom→South, East→East, West→West, Top→Nouth, Nouth→Bottom
      setNumber(work[1], work[5], work[2], work[3], work[0], work[4]);
      break;
    case 'S':
      // North→Top, Top→South, East→East, West→West, Bottom→North, South→Bottom
      setNumber(work[4], work[0], work[2], work[3], work[5], work[1]);
      break;
    case 'W':
      // East→Top, South→South, Bottom→East, Top→West, North→North, West→Bottom
      setNumber(work[2], work[1], work[5], work[0], work[4], work[3]);
      break;
    default :
      break;
    }
  }

  public void setNumber(int n1, int n2, int n3, int n4, int n5, int n6) {
    this.number[0] = n1;
    this.number[1] = n2;
    this.number[2] = n3;
    this.number[3] = n4;
    this.number[4] = n5;
    this.number[5] = n6;
  }
  
  public int[] getNumber () {
    return this.number;
  }

  public int takeTopNumber() {
    return this.number[0];
  }
  
  public int takeSouthNumber() {
    return this.number[1];
  }
  
  public int takeEastNumber() {
    return this.number[2];
  }
  
  public boolean equals(Object obj, char[] order) {
    if (obj == this) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (!(obj instanceof Dice)) {
      return false;
    }
    
    Dice another = (Dice)obj;
    
    boolean isSame = false;
    for (int i = 0; i < order.length; i++) {
      this.rollDice(order[i], another.getNumber().length);

      for (int j = 0; j < another.getNumber().length; j++) {
        if (this.number[j] == another.number[j]) {          
          isSame = true;
          
        } else {
          isSame = false;
          break;
        }
      }
      if (isSame) {
        break;
      }

    }    
    return isSame;
  }
}

Dice.java

package main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import dto.Dice;

public class TestDice03 {

  public static void main(String[] args) {
    // TODO 自動生成されたメソッド・スタブ
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    try {
      String[] diceNumber01 = br.readLine().split("\\s");
      String[] diceNumber02 = br.readLine().split("\\s");
      
      Dice dice01 = new Dice(diceNumber01);
      Dice dice02 = new Dice(diceNumber02);
      
      String order = "NNNNWNNNWNNNENNNENNNWNNN";
      char[] orderChar = order.toCharArray();
      if (dice01.equals(dice02, orderChar)) {
        System.out.println("Yes");
      } else {
        System.out.println("No");
      }

    } catch (IOException e) {
      // TODO 自動生成された catch ブロック
      e.printStackTrace();
    } 
  }
}

んで、実行。

f:id:ts0818:20190505112638p:plain 

入力値は、

Input

1行目に1つ目のサイコロの各面の整数が、ラベルの順番に空白区切りで与えられます。
2行目に2つ目のサイコロの各面の整数が、ラベルの順番に空白区切りで与えられます。

サイコロ 3 | プログラミング入門 | Aizu Online Judge

ということで、 

f:id:ts0818:20190505112043p:plain

f:id:ts0818:20190505112557p:plain

できました~。

他の方のソースコードを参考にさせていただかせているのですが、一番、分からなかったのが、サイコロを振る方向の条件網羅んとこ。

『NNNNWNNNWNNNENNNENNNWNNN』でいけるらしいと。 

⇩  確か、サイコロの作りはこうであると。

次の展開図から得られるサイコロを転がすシミュレーションを行うプログラムを作成してください。 

f:id:ts0818:20190504164312p:plain

サイコロの各面には図のとおりに 1 から 6 のラベルが割りあてられています。

入力としてサイコロの各面のラベルに対応する整数と、転がす命令の列が与えられるので、サイコロの上面の整数を出力してください。シミュレーションの初期状態は、図のとおりのラベルの位置でサイコロが置かれているものとします。

サイコロ 1 | プログラミング入門 | Aizu Online Judge

なので、『NNNNWNNNWNNNENNNENNNWNNN』は、おそらく、

「NNNN」「WNNN」「WNNN」「ENNN」「ENNN」「WNNN」の6パターンで調べきれるんだと、というかよく思いつくな、こんなん全く思い浮かばんわ...

f:id:ts0818:20190505114038p:plain

⇧  みたいなサイコロで考えてみると、

「NNNN」で、Topが「1」の場合を調査し、

「WNNN」で、Topが「3」の場合を調査し(最初の「W」でTopが「3」になる)、

「WNNN」で、Topが「5」の場合を調査し(最初の「W」でTopが「5」になる)、 

「ENNN」で、Topが「6」の場合を調査し(最初の「E」でTopが「6」になる)、 

「ENNN」で、Topが「4」の場合を調査し(最初の「E」でTopが「4」になる)、 

「WNNN」で、Topが「2」の場合を調査し(最初の「W」でTopが「2」になる)、 

で、すべての場合について調べられるということかと、というか上記の仮説が合ってるか検証するために実物のサイコロが欲しいかな...。

まぁ、モヤモヤ感がどんどんと蓄積していくだけで、自分にまったく成長が見られないですが(哀)。

今回はこのへんで。