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

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

ただいまの
回答率

90.48%

  • Java

    14097questions

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

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

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 4,028

do_jyo

score 21

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

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

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

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

public int fightMath(int one, int two) {

 if(one == 0 && two == 0) { result = 0; }
 else if(one == 0 && two == 1) { result = 0; }
 else if(one == 0 && two == 2) { result = 1; }
 else if(one == 0 && two == 3) { result = 2; }
 else if(one == 1 && two == 0) { result = 0; }
 else if(one == 1 && two == 1) { result = 0; }
 else if(one == 1 && two == 2) { result = 2; }
 else if(one == 1 && two == 3) { result = 1; }
 else if(one == 2 && two == 0) { result = 2; }
 else if(one == 2 && two == 1) { result = 1; }
 else if(one == 2 && two == 2) { result = 3; }
 else if(one == 2 && two == 3) { result = 3; }
 else if(one == 3 && two == 0) { result = 1; }
 else if(one == 3 && two == 1) { result = 2; }
 else if(one == 3 && two == 2) { result = 3; }
 else if(one == 3 && two == 3) { result = 3; }

 return result;
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

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

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

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

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

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

Sample.java
public class Sample {
    public static void main(String[] args) {
        int[] hands = {-2, -1, 1, 2};

        for( int one : hands) {
            for( int two : hands) {
                System.out.printf("[%d, %d] => %d\n", one, two, fightMath(one, two));
            }
            System.out.printf("¥n");
        }
    }

    // val の符号を調べる。
    // @retrun -1: 負の値, 1: 正の値
    static int sign(int val) {
        return val < 0 ? -1 : 1;
    }

    // @param x  player one の手 (-2, -1, 1, 2)
    // @param y  player two の手 (-2, -1, 1, 2)
    // @return:  (ビット2: y の勝ち負け、ビット1: x の勝ち負け) とした整数を返す。
    static int fightMath(int x, int  y) {
        assert(x != 0);
        assert(y != 0);
        int win_x = 0;  // 0: 負け, 1: 勝ち
        int win_y = 0;  // 0: 負け, 1: 勝ち
        int val = x * y;

        if (val > 0) {
            win_x = win_y = (sign(val) == sign(x)) ? 1 : 0;
        } else if (val == -2) {
            win_x = (x < 0) ? 1 : 0;
            win_y = 1 - win_x;
        } else {
            win_x = (x > 0) ? 1 : 0;
            win_y = 1 - win_x;
        }
        return win_x + win_y * 2;
    }
}
このプログラムを走らせると次の様な出力になります。

$ 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/27 10:41

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

    キャンセル

+2

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

入力と出力の関係がコードを見てもよくわからなかったので、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;
 }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

関連した質問

  • 解決済

    Java BigInteger 素数確認メソッドの処理について

    自分が作った素数確認メソッドの処理問題があって、それを修正したいのだが・・・どこが問題起きてるのかわからない・・・よろしければ、訂正後のソース部分を載せてください。お願いします。

  • 解決済

    文字列の数値かそれ以外かの判断

    いつもお世話になっております。 受け取ったString文字列が数値かそうでないか、を判断するコードを作る課題があったので、自分なりに作りました。 こちらです↓ /*  コマンド

  • 受付中

    staticなmethodのメリットとは

    java初心者です。 staticという言葉に混乱しています。 staticなフィールドを持つクラスを作成したときに そのクラスから作成されたインスタンスが共通のクラスを持つ事で

  • 解決済

    文字列の解析処理について

    こんにちは。 与えられた文字列を分解する処理を行う下記のソースについて、ご意見を頂ければと思います。 前提・実現したいこと使用言語:Java 与えられる文字列には、「&」また

  • 解決済

    ListViewでのCheckBoxにチェックが付かない

    前提・実現したいこと 現在ListViewで一覧を表示しているのですが、項目のLongClickからチェックボックスが表示され、複数選択出来るようなものを作りたいと思っています。

  • 解決済

    リスト内の値の比較をして出力したい

     前提・実現したいこと Javaの学習をしており練習に以下のようなプログラムを作成しようとしています 1.入力した値を比較し最もゼロに近く値を出力する 2.正と負の値で絶対値が同じ

  • 解決済

    privateのフィールドに外部クラスからアクセスする

     前提・実現したいこと こんばんは、Javaについての質問です。 とあるJavaの問題を解いていて、ある程度自力で調べてはみたものの、どうしても分からず困っています。 お助け願いま

  • 受付中

    Java:「じゃんけんゲーム」でコンパイルしてもスコアが反映されない状態です。ソースコードでおかしい...

    失礼いたします。 今社内の研修でJavaを使用して「じゃんけんゲーム」を制作しております。 処理内容はこちらです。 ・playerとCPUの2人でじゃんけんをする。 ・pl

同じタグがついた質問を見る

  • Java

    14097questions

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