m.rossi m.rossi - 3 months ago 18
Java Question

How to check if three numbers are guessed?

Hi everyone on this community.
I'm a Java newbie. This is no homework, I'm really passionate about programming and I really want to learn more. I am stuck with one exercise.

Basically I have to create a simple lottery game.
The user has to input one number from 0 to 999, a three digit number.


  • If the guess is exactly the same, the prize is 10.000 $,

  • If the guess is about the same (digits guessed but not in order) the
    prize is 3,000 $

  • If the guess is not really the same (digits guessed == 1) the prize
    is 1,000 $.



Here's my code so far: I don't know how to deal with condition 2 and 3. Could I have some hint or comment?

import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);

System.out.println("Please enter a three digit number");
int guess = input.nextInt();


//generate number:
int lottery = (int)(Math.random() * 1000);

if ((guess > 999) || (guess < 100)) {
System.out.println("The number is not a three digit number. The system will exit NOW.");
System.exit(1);
}

else {
// extract digits from lottery number

int lotteryDigit1 = lottery / 100;
int lotteryDigits = lottery % 100;
int lotteryDigit2 = lottery / 10;
int lotteryDigit3 = lottery % 10;


// extract digits from guessed number

int guessDigit1 = guess / 100;
int remainingDigits = guess % 100;
int guessDigit2 = guess / 10;
int guessDigit3 = guess % 10;

System.out.println("The lottery number is: " + lottery);

// check the guess:

if (guess == lottery) {
System.out.println("Exactly what the number was.");
}

else if {
// digits guessed, but not in exact order (eg. 332 = 233)
}

else if {
// only one digit is guessed (eg. 332 = 442)

}

}

}
}


Could I have some comment on the code? Is it readable or horribly written? I really don't have a clue since I am really just new to programming. Thanks.

Answer

With an array, you can count how many digits the real number and the guessed number contains, and perform comparisons with that. First make two arrays of length 10 (one slot for each digit), then increase each relevant "slot" by 1 for every digit in the real number. Do the same for the guess, and compare.

I'm recommending this approach because it will scale for guesses with 4, 5, or even 15 digits, whereas coding these checks by hand will quickly turn into a problem with lots of duplicate code.

If, for some reason, you're not allowed to use arrays, you could manually do the counting - it sounds tempting to check if each digit exists in the other set of digits, but you'll run into trouble with duplicate digits (consider 112, which, when compared to 122, would contain "all" the digits; just not in the right amounts!). This will lead to a lot of duplicate code.

It'd be something like this...

int matchingDigits = 0;
if ( guessDigit1 == lotteryDigit1 || guessDigit1 == lotteryDigit2 || guessDigit1 == lotteryDigit3) {
    matchingDigits++;
}
if ( guessDigit2 == lotteryDigit1 || guessDigit2 == lotteryDigit2 || guessDigit2 == lotteryDigit3) {
    matchingDigits++;
}
if ( guessDigit3 == lotteryDigit1 || guessDigit3 == lotteryDigit2 || guessDigit3 == lotteryDigit3) {
    matchingDigits++;
}

As you can see, it's a lot of duplicate code, and it doesn't properly handle the 112 vs 122 case. To properly handle that, you'd have to split each check apart and cross out numbers you've already "used"... which is possible, but leads to really lengthy code.

Here's how you'd do it...

boolean digit1Used = false;
boolean digit2Used = false;
boolean digit3Used = false;
int matchingDigits = 0;
if ( guessDigit1 == lotteryDigit1) {
    matchingDigits++;
    digit1Used = true;
} else if ( guessDigit1 == lotteryDigit2) {
    matchingDigits++;
    digit2Used = true;
} else if ( guessDigit1 == lotteryDigit3) {
    matchingDigits++;
    digit3Used = true;
}

if ( guessDigit2 == lotteryDigit1 && !digit1Used) {
    matchingDigits++;
    digit1Used = true;
} else if ( guessDigit2 == lotteryDigit2 && !digit2Used) {
    matchingDigits++;
    digit2Used = true;
} else if ( guessDigit2 == lotteryDigit3 && !digit3Used) {
    matchingDigits++;
    digit3Used = true;
}

if ( guessDigit3 == lotteryDigit1 && !digit1Used) {
    matchingDigits++;
} else if ( guessDigit3 == lotteryDigit2 && !digit2Used) {
    matchingDigits++;
} else if ( guessDigit3 == lotteryDigit3 && !digit3Used) {
    matchingDigits++;
}

Note that I left out the checks for digitUsed in the first checks and the sets for digitUsed for the third set of checks - because we're not going to use them anymore. As you can see, it's really long AND it's basically faking arrays. Hence why it's not recommended to do so.

Imagine that solution for a 15 digit array! It'd be (N + 1 + (N*3*N) + N + N) lines long - 15 for digitUsed declarations, 1 for the matching digits, 15 digit comparisons of 3 lines for 15 digits, plus 15 closing braces and 15 blank lines in between - a total of 721 lines! That's why you should use arrays for this, and not checking it by hand.

If you've learned about methods already, I suggest you put the digit matcher in a separate function; that way you can keep your digit matching logic and the result-to-prize matching logic somewhat separated.