ある確率で間違えるFizz Buzz

プログラミングの練習問題にFizzBuzz問題がありますが、Wikiのページ[Fizz Buzz](https://ja.wikipedia.org/wiki/Fizz_Buzz)を見たところ、遊び方が書いてありました。一例として「FizzBuzz遊び」をプログラミングしてみました。

#FizzBuzzクラス

FizzBuzzは次の2つのstaticメソッドを持ちます。

<dl>
  <dt>public static String replyStablyBasedOn(int i)</dt>
  <dd>引数iに対して、Fizz Buzzにおいての正しい返事を返します。</dd>
  <dt>public static String replyUnStablyBasedOn(int i)</dt>
  <dd>引数iに対して、Fizz Buzzにおいての正しい返事を<strong>ランダム</strong>に返します。</dd>
</dl>

ソースは以下です。

```Java:FizzBuzz.java
package fizzbuzz;

import java.util.Random;

public class FizzBuzz {

    private static final String FIZZ_BUZZ = "FizzBuzz";

    private static final String FIZZ = "Fizz";

    private static final String Buzz = "Buzz";

    public static String replyStablyBasedOn(int i) {

        String s = null;

        if (i % 3 == 0 && i % 5 == 0) {
            s = FIZZ_BUZZ;
        } else if (i % 3 == 0) {
            s = FIZZ;
        } else if (i % 5 == 0) {
            s = Buzz;
        } else {
            s = String.valueOf(i);
        }

        return s;

    }

    private static final Random random = new Random();

    public static String replyUnStablyBasedOn(int i) {

        String s = null;
        int key = random.nextInt(4);
        switch (key) {
        case 0:
            s = FIZZ_BUZZ;
            break;
        case 1:
            s = FIZZ;
            break;
        case 2:
            s = Buzz;
            break;
        case 3:
            s = String.valueOf(i);
            break;
        }

        return s;

    }



}
```

#HumanFizzBuzzクラス

ソースを見た方が早いかもしれませんが、以下がメソッドの説明です。

<dl>
  <dt>public HumanFizzBuzz(String name, int stableRange)</dt>
  <dd>nameはプレーヤーの名前です。stableRangeは0から100までの整数を指定します。0に近いほど間違えやすくなります。</dd>
  <dt>public String replyFrom(int i)</dt>
  <dd>引数iに対して、Fizz Buzzにおいての正しい返事を<strong>ランダム</strong>に返します。</dd>
  <dt>public String getName</dt>
  <dd>プレーヤーの名前を返します。</dd>
</dl>

replyFrom()は工夫してコンストラクタで指定したstableRangeが100に近いほど、ある程度間違えないようにしています。

以下がソースです。

```Java:HumanFizzBuzz.java
package fizzbuzz;

import java.util.Random;

public class HumanFizzBuzz {

    private String name;

    private int stableRange;

    private final int BOUND = 100;

    private final Random random = new Random();

    public HumanFizzBuzz(String name, int stableRange) {
        this.name = name;
        this.stableRange = stableRange;
    }

    public String replyFrom(int i) {

        int randomNum = random.nextInt(BOUND);

        String s = null;
        if (randomNum < stableRange) {
            s = FizzBuzz.replyStablyBasedOn(i);
        } else {
            s = FizzBuzz.replyUnStablyBasedOn(i);
        }

        return s;

    }

    public String getName() {
        return name;
    }

}
```

#Testクラス

「FizzBuzz遊び」をするクラスです。5人のプレーヤーで「FizzBuzz遊び」をします。

以下がソースです。

```Java:Test.java
package fizzbuzz;

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {

        List<HumanFizzBuzz> list = new ArrayList<>();
        list.add(new HumanFizzBuzz("A", 90));
        list.add(new HumanFizzBuzz("B", 90));
        list.add(new HumanFizzBuzz("C", 90));
        list.add(new HumanFizzBuzz("D", 90));
        list.add(new HumanFizzBuzz("E", 90));

        int index = 0;
        int i = 1;
        HumanFizzBuzz humanFizzBuzz;
        while (list.size() > 1) {

            index = index % list.size();

            // 返事
            humanFizzBuzz = list.get(index);
            String reply = humanFizzBuzz.replyFrom(i);

            // 答え合わせ
            String correctAnswer = FizzBuzz.replyStablyBasedOn(i);
            System.out.printf("%3d番目 正解: %-8s %sさんの返事: %-8s",
                    i, correctAnswer, humanFizzBuzz.getName(), reply);
            if (correctAnswer.equals(reply)) {
                index ++;
            } else {
                System.out.printf(" 退場です。");
                list.remove(humanFizzBuzz);

                // 残りを表示
                if (list.size() > 1) {
                    System.out.println();
                    System.out.print("残り: ");
                    for (HumanFizzBuzz h : list) {
                        System.out.print(h.getName() + " ");
                    }
                }
            }
            System.out.println();

            i ++;
        }

        System.out.println("勝者: " + list.get(0).getName());

    }

}
```

以下が実行結果の一例です。

```Java:結果
  1番目 正解: 1        Aさんの返事: 1       
  2番目 正解: 2        Bさんの返事: 2       
  3番目 正解: Fizz     Cさんの返事: Fizz    
  4番目 正解: 4        Dさんの返事: 4       
  5番目 正解: Buzz     Eさんの返事: Buzz    
  6番目 正解: Fizz     Aさんの返事: Fizz    
  7番目 正解: 7        Bさんの返事: 7       
  8番目 正解: 8        Cさんの返事: 8       
  9番目 正解: Fizz     Dさんの返事: Fizz    
 10番目 正解: Buzz     Eさんの返事: Buzz    
 11番目 正解: 11       Aさんの返事: 11      
 12番目 正解: Fizz     Bさんの返事: Fizz    
 13番目 正解: 13       Cさんの返事: 13      
 14番目 正解: 14       Dさんの返事: 14      
 15番目 正解: FizzBuzz Eさんの返事: FizzBuzz
 16番目 正解: 16       Aさんの返事: 16      
 17番目 正解: 17       Bさんの返事: 17      
 18番目 正解: Fizz     Cさんの返事: Fizz    
 19番目 正解: 19       Dさんの返事: 19      
 20番目 正解: Buzz     Eさんの返事: Buzz    
 21番目 正解: Fizz     Aさんの返事: Buzz     退場です。
残り: B C D E 
 22番目 正解: 22       Bさんの返事: 22      
 23番目 正解: 23       Cさんの返事: 23      
 24番目 正解: Fizz     Dさんの返事: Fizz    
 25番目 正解: Buzz     Eさんの返事: Buzz    
 26番目 正解: 26       Bさんの返事: 26      
 27番目 正解: Fizz     Cさんの返事: Fizz    
 28番目 正解: 28       Dさんの返事: 28      
 29番目 正解: 29       Eさんの返事: 29      
 30番目 正解: FizzBuzz Bさんの返事: FizzBuzz
 31番目 正解: 31       Cさんの返事: 31      
 32番目 正解: 32       Dさんの返事: 32      
 33番目 正解: Fizz     Eさんの返事: Fizz    
 34番目 正解: 34       Bさんの返事: 34      
 35番目 正解: Buzz     Cさんの返事: Buzz    
 36番目 正解: Fizz     Dさんの返事: Fizz    
 37番目 正解: 37       Eさんの返事: 37      
 38番目 正解: 38       Bさんの返事: 38      
 39番目 正解: Fizz     Cさんの返事: Fizz    
 40番目 正解: Buzz     Dさんの返事: Buzz    
 41番目 正解: 41       Eさんの返事: FizzBuzz 退場です。
残り: B C D 
 42番目 正解: Fizz     Bさんの返事: Fizz    
 43番目 正解: 43       Cさんの返事: 43      
 44番目 正解: 44       Dさんの返事: 44      
 45番目 正解: FizzBuzz Bさんの返事: Buzz     退場です。
残り: C D 
 46番目 正解: 46       Cさんの返事: 46      
 47番目 正解: 47       Dさんの返事: 47      
 48番目 正解: Fizz     Cさんの返事: FizzBuzz 退場です。
勝者: D
```

上記ではDさんが勝ちましたが、実行するごとに結果は変わります。