Algorithm for a small straight in Yahtzee not working for specific dice roll

Viewed 117

I have created a method to calculate whether 5 dice rolls make a small straight in Java. According to my task, a small straight is defined by rolling 4 consecutive numbers in any order.

I am using an array that tracks the frequency of the rolls in my method. arr[0] being the quantity of 1 dice rolled, arr[1] the quantity of 2 dice rolled, etc.

It works for all of my test cases except when the numbers rolled are 3, 4, 5, 5, 6.

The frequency array for the case that will not work is [0, 0, 1, 1, 2, 1].

public int getSmallStraightScore() {
    int score = 0;
    int count = 0;
    int[] x = getRollFrequency();
    for (int i = 0; i < x.length; i++) {
        if (x[i] != 0) {
            count++;
        } else if (count == 4) {
            score = 30;
            break;
        }
    }
    return score;
}

I have tried changing else if (count >= 4) which does not work either.

I can't use anything like a hash table as it has to be in vanilla Java.

3 Answers

There are more test cases which will fail. E.g. 1,2,3,5, x with x != 4 will return 30 which is wrong. Also 3, 4, 5, 6, x whith x between 3 and 6 will fail.

Why? Because your if else is wrong (but it is close to be correctly). The count is only checked if there is no match and count isn't reset.

Here is how it should look like:

if (x[i] != 0) {
    count++;
} else {
    count = 0; // reset count if no match
}
if (count >= 4) { // always check and not just if there is no match
    score = 30;
    break;
}

You could simplify (and also eliminate the score variable):

if (x[i] > 0) {
    if (++count == 4)
        return 30;
} else {
    count = 0;
}

Or:

return x[2] > 0 && x[3] > 0 && (x[1] > 0 && (x[0] > 0 || x[4] > 0) || x[4] > 0 && x[5] > 0) ? 30 : 0;

You need to check for two cases :

First : check for 0,1,2,3 (first four rolls)

Second : check for 1,2,3,4 (next four rolls)

These cases cover the five rolls.

Try this:

public int getSmallStraightScore() {
    int[] x = getRollFrequency();
    int count = 0;
    for (int i = 0; i < x.length; i++) {
        if (x[i] == 0) {   // prefer affirmative comparisons
            count = 0;     // no need for break
        } else if (++count == 4) { // in-line increment and compare
            return 30;     // clear "found" result
        }
    }
    return 0;              // clear "not found" result
}

This is the simplest/least code approach.

The break statement has been removed, reducing the cyclomatic complexity, and the score variable has been eliminated; a further simplification.

Related