ダーツのゲームを終了する方法を決定するために、Java で再帰関数を作成しようとしています。基本的にダーツは3本までで、ダブルでフィニッシュする必要があります。
ダーツx01のダブルアウトフィニッシュのルールを知らないと、この質問はわかりにくいですよね… 説明してみましょう。簡単にするために、ここでは雄牛の目を方程式から除外します。
ルール:
1) 1 番から 20 番まで投げることができるダーツが 3 本あります。
2) 1 回のヒットで、シングル、ダブル、またはトリプルのスコアを獲得できます。
例: シングル 20 = 20 ポイント、ダブル 20 = 40 ポイント、トリプル 20 = 60 ポイント
3) 1 回のターンで、最大 180 ポイントを獲得できます (3x トリプル 20 = 3*60 = 180)。180以上は無理です。これは、180 IS 未満が可能であることを意味するものではありません。たとえば、179 も同様に不可能です。次の最高のスコアは triple20+triple20+triple19 = 167 であるためです。
4) 通常、501 から開始し、残りのポイントがちょうど 0 になるまで 3 ダーツを投げます。
5) ダブルアウトでは、最後のダーツがダブルにヒットする必要があります。
たとえば、180 ポイントが残っている場合、最後のダーツはダブルでなければならないため、終了できません。したがって、最大 (ブルズアイを無視した場合) = triple20 + triple20 + double20 = 160 そして、スコアが 16 の場合、ダブル 8 をヒットすることで 1 ダーツの使用を終了できます。別の例として、スコアが 61 の場合、ヒットすることができます。トリプル17 + ダブル5 (= 51 + 10)
現在のコード
とにかく、以下は私がこれまでに持っているものです。必要なものとはほど遠いことはわかっていますが、何をしようとしても、いつも行き詰まります。おそらく誰かが別のアプローチについて彼の考えを共有することができます
private class Score{
int number; // the actual number, can be 1...20
int amount; // multiplier, can be 1, 2 or 3
public Score(int number, int amount){
this.number = number; // the actual number, can be 1...20
this.amount = amount; // multiplier, can be 1, 2 or 3
}
public int value()
{
return number * amount; // the actual score
}
public void increment()
{
if(this.amount == 0)
this.amount = 1;
this.number++;
if(this.number >= 20)
{
this.number = 0;
this.amount++;
if(this.amount >= 3)
this.amount = 3;
}
}
}
public ArrayList<Score> canFinish(int desired, ArrayList<Score> score){
// If this is the case -> we have bingo
if(eval(score) == desired) return score;
// this is impossible -> return null
if(eval(score) > 170) return null;
// I can't figure out this part!!
Score dart3 = score.remove(2);
Score dart2 = score.remove(1);
if(dart2.eval() < 60){
dart2.increment();
}
else if(dart3.eval() < 60){
dart3.increment();
}
score.add(dart2);
score.add(dart3);
return canFinish(desired, score);
}
public int eval(ArrayList<Score> scores)
{
int total = 0;
for(Score score : scores){
total += score.value();
}
return total;
}
私は単に呼び出したい:
ArrayList<Score> dartsNeeded = new ArrayList<Score>();
dartsNeeded.add(new Score(16, 2)); // Add my favourite double
dartsNeeded.add(new Score(0, 0));
dartsNeeded.add(new Score(0, 0));
// and call the function
dartsNeeded = canFinish(66, dartsNeeded);
// In this example the returned values would be:
// [[16,2],[17,2],[0,0]] -> 2*16 + 2*17 + 0*0 = 66
// So I can finish, by throwing Double 17 + Double 16
したがって、終了できない場合、関数は null を返しますが、終了の可能性がある場合は、目的のスコアを作成するために必要な 3 つのダーツでその ArrayList を受け取ります...
短い要約
問題は、上記のコードは 1 つのダーツを見つけるのに役立つだけで、2 つのダーツの組み合わせには役立たないことです。したがって、canFinish(66, darts) は機能しますが、canFinish(120, darts) は StackOverflow Exception を返します。120 の場合、triple20、double14、double16、またはその他の有効な組み合わせのようなものが得られると期待しています。