質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

12688閲覧

Java:if文が多すぎるコードを改善したい

do_jyo

総合スコア17

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2014/08/22 14:43

Javaのコードの書き換えに苦戦しています。

以下のコードだと、一応思うようには動作するのですが、if文が多すぎるコードになってしまって綺麗ではないな..と思っています。

もう少し綺麗な式に直す方法があれば教えていただけませんか?

やりたいこと:
少ない文字で同時にいくつかの値を返すゲームを作りたい。
2人のプレイヤーが4つのアクションボタンをそれぞれ持っており、結果は(0-3)の配列から算出する。
メソッド引数'one'と'two'で受け取った数値から勝敗を判断し、戻り値として 0=両者の負け、1=プレイヤー1の勝ち、2=プレイヤー2の勝ち、3=両者の勝ち、のどれかを返すというものです。

lang

1public int fightMath(int one, int two) { 2 3 if(one == 0 && two == 0) { result = 0; } 4 else if(one == 0 && two == 1) { result = 0; } 5 else if(one == 0 && two == 2) { result = 1; } 6 else if(one == 0 && two == 3) { result = 2; } 7 else if(one == 1 && two == 0) { result = 0; } 8 else if(one == 1 && two == 1) { result = 0; } 9 else if(one == 1 && two == 2) { result = 2; } 10 else if(one == 1 && two == 3) { result = 1; } 11 else if(one == 2 && two == 0) { result = 2; } 12 else if(one == 2 && two == 1) { result = 1; } 13 else if(one == 2 && two == 2) { result = 3; } 14 else if(one == 2 && two == 3) { result = 3; } 15 else if(one == 3 && two == 0) { result = 1; } 16 else if(one == 3 && two == 1) { result = 2; } 17 else if(one == 3 && two == 2) { result = 3; } 18 else if(one == 3 && two == 3) { result = 3; } 19 20 return result; 21}

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

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

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

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

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

guest

回答3

0

ベストアンサー

計算量(比較演算を含む) は、質問文中の方法では、
最悪 16 回の比較、平均で 8 回
です。

最初の回答にあるように勝敗決定表を用意して、その表を引くことで、計算量を常に一定にできます。

しかし
もっとケース分けが膨大な量 (100 * 100) になる、
決定表に未使用のセルが大量に発生する、
ような場合は、勝敗決定を ある程度 プログラムロジックで書く必要がでてきます。

質問のゲームの場合だと、 プレーヤーの手は何らかの物理的な操作に結びついて
いるとおもわれるので、その物理的な挙動にそったロジックを書けばよいです。
もしかすると、計算式1つで、勝敗の計算ができることもあるかもしれません。
(ここでの質問では、ゲームの手の物理的なモデルが不明なので、その例を私が示すことはできませんが)

そこで、以下に、なるべく 計算量がすくなくなるように少し工夫した例をしめします。
質問文では、プレーヤの手は [1,2,3,4] ですが、それを [-2, -1, 1, 2] に変更しています。
そうすると、このゲームでは 勝敗結果が 0, 3 の場合のチェックが簡単にできるからです。
もっとうまい値や判定方法をみつければ、勝敗結果が 1, 2 の場合についても もっと単純にできそうな気がしますが、今はここまでで...

Sample.java

lang

1public class Sample { 2 public static void main(String[] args) { 3 int[] hands = {-2, -1, 1, 2}; 4 5 for( int one : hands) { 6 for( int two : hands) { 7 System.out.printf("[%d, %d] => %d\n", one, two, fightMath(one, two)); 8 } 9 System.out.printf("¥n"); 10 } 11 } 12 13 // val の符号を調べる。 14 // @retrun -1: 負の値, 1: 正の値 15 static int sign(int val) { 16 return val < 0 ? -1 : 1; 17 } 18 19 // @param x player one の手 (-2, -1, 1, 2) 20 // @param y player two の手 (-2, -1, 1, 2) 21 // @return: (ビット2: y の勝ち負け、ビット1: x の勝ち負け) とした整数を返す。 22 static int fightMath(int x, int y) { 23 assert(x != 0); 24 assert(y != 0); 25 int win_x = 0; // 0: 負け, 1: 勝ち 26 int win_y = 0; // 0: 負け, 1: 勝ち 27 int val = x * y; 28 29 if (val > 0) { 30 win_x = win_y = (sign(val) == sign(x)) ? 1 : 0; 31 } else if (val == -2) { 32 win_x = (x < 0) ? 1 : 0; 33 win_y = 1 - win_x; 34 } else { 35 win_x = (x > 0) ? 1 : 0; 36 win_y = 1 - win_x; 37 } 38 return win_x + win_y * 2; 39 } 40}

このプログラムを走らせると次の様な出力になります。

$ javac Sample.java $ java -ea Sample [-2, -2] => 0 [-2, -1] => 0 [-2, 1] => 1 [-2, 2] => 2 [-1, -2] => 0 [-1, -1] => 0 [-1, 1] => 2 [-1, 2] => 1 [1, -2] => 2 [1, -1] => 1 [1, 1] => 3 [1, 2] => 3 [2, -2] => 1 [2, -1] => 2 [2, 1] => 3 [2, 2] => 3

投稿2014/08/24 10:18

katoy

総合スコア22324

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

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

do_jyo

2014/08/27 01:41

回答ありがとうございました!試してみようと思います!
guest

0

色々な方法があると思いますが、結果が限られたパターンの数値になることが前提であれば、以下のような固定の配列を変換テーブルのようなイメージで1つ作ってしまって、添え字に引数をセットして結果を取り出す形にすればコード量が減らせると思います。

lang

1final int[][] result = new int[][] { 2 { 0, 0, 1, 2 }, 3 { 0, 0, 2, 1 }, 4 { 2, 1, 3, 3 }, 5 { 1, 2, 3, 3 } 6}; 7return result[one][two];

投稿2014/08/23 01:20

veeyepee

総合スコア197

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

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

0

入力と出力の関係がコードを見てもよくわからなかったので、Excelで表を作ると、

  • 0を返す時:両者とも0か1
  • 1を返す時:{0,2},{1,3},{2,1},{3,0}
  • 2を返す時:{0,3},{1,2},{2,0},{3,1}
  • 3を返す時:両者とも2か3

となりました。これから次のようにできると思います(これが決してベストな方法だとは思っていませんが・・・)。

public int fightMath(int one, int two) { if((one == 0 || one == 1) && (two == 0 || two == 1)) return 0; else if((one == 2 || one == 3) && (two == 2 || two == 3)) return 3; else return evaluate(one, two); } public int evaluate(int one, int two) { switch(one) { case 0: if(two == 2) return 1; else if(two == 3) return 2; break; case 1: if(two == 2) return 2; else if(two == 3) return 1; break; case 2: if(two == 0) return 2; else if(two == 1) return 1; break; case 3: if(two == 0) return 1; else if(two == 1) return 2; break; } }

投稿2014/08/23 16:10

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問