-3

I started to learn Java recently, and currently I am working with exceptions.
Program is a game - Number Guessing.
Code below represents class Ticket.
Ticket has serial number, which consists of 8 numbers.
First 7 numbers are the ones chosen by player, and last number is number of ticket printed (it is static variable).
Inputs should be checked so that player can only choose numbers, and numbers must be between 1 and 90. Also, all numbers must be different (we don't consider number of ticket printed).

What question is really about is Scanner.
When I run program, scanner asks player for number two times before it is accepted, even if player types good number first.

Here is the code:

public class Ticket {

     private static int serialNum = 0;
     private int ticketNum[];

     Ticket() {
         Scanner sc = new Scanner(System.in);
         ticketNum = new int[8];
         this.serialNum += 1;
         this.ticketNum[7] = serialNum;
         System.out.println("Ticket numbers input...");

         for (int i = 0; i < 7; i++) {
             System.out.println("Choose " + (i + 1) + ". number: ");
             try {
                 if (!sc.hasNextInt()) {
                     throw new ValueException();
                 } else {
                     if (contains(ticketNum, sc.nextInt())) {
                         throw new DuplicateValueException();
                     }
                     if ((sc.nextInt() < 1) || (sc.nextInt() > 90)) {
                         throw new ValueException();
                     }
                 }
             } catch (ValueException e) {
                 System.out.println(e.Message());
                 i -= 1;
                 sc.nextLine();
                 continue;
             } catch (DuplicateValueException e) {
                 System.out.println(e.Message());
                 i -= 1;
                 sc.nextLine();
                 continue;
             }

             this.ticketNum[i] = sc.nextInt();
         }
     }

     public void printTicketNum() {
         System.out.println("Ticket serial number: ");
         for (int i = 0; i < this.ticketNum.length; i++) {
             System.out.print(ticketNum[i]);
         }
     }

     private boolean contains(int arr[], int val) {
         int flag = 0;
         for (int i = 0; i < arr.length - 1; i++) {
             if (arr[i] == val)
                 flag++;
         }
         if (flag > 0)
             return true;
         else
             return false;
     }

     public static void main(String[] args) {
         Ticket t1 = new Ticket();
         t1.printTicketNum();
     }
 }
Paolo Forgia
  • 5,804
  • 7
  • 39
  • 55
misty
  • 111
  • 12
  • 2
    `if((sc.nextInt()<1)||(sc.nextInt()>90)){` what do you think `nextInt()` does here? – Pshemo Aug 02 '16 at 13:21
  • Not only there, also in `contains(ticketNum,sc.nextInt())` – Tom Aug 02 '16 at 13:23
  • Also be careful in your `catch` blocks with: [Skipping nextLine() after using next(), nextInt() or other nextFoo() methods](https://stackoverflow.com/questions/13102045/skipping-nextline-after-using-next-nextint-or-other-nextfoo-methods) – Pshemo Aug 02 '16 at 13:23
  • @Pshemo look my comment below. – misty Aug 02 '16 at 13:33
  • So your intuition was correct :) Scanner can't know when `nextInt()` should return same value and when should it return next one which is why decision was made that it always should return next value (as its name states). If we want to reuse same value somewhere else we can store it in variable (but that is not Scanners job). – Pshemo Aug 02 '16 at 13:40

1 Answers1

4

Every time you call sc.nextInt(), you're fetching a new integer from the input. For example, in the block where you have

if(contains(ticketNum,sc.nextInt())){
    throw new DuplicateValueException();
}
if((sc.nextInt()<1)||(sc.nextInt()>90)){
    throw new ValueException();
}

you could actually be reading in three separate integers.

You don't want to do that. Instead, you could assign the integer that you fetch to a local variable

int input = sc.nextInt();

and just check the value of that variable each time you need to.

Dawood ibn Kareem
  • 68,796
  • 13
  • 85
  • 101
  • I suspected this was a problem. :D Thank you. – misty Aug 02 '16 at 13:30
  • Just one more question. Would that be error - if I had local variable input, which is int, but user types, let's say 'a'? – misty Aug 02 '16 at 13:36
  • 1
    Why don't you try it and see what happens? – Dawood ibn Kareem Aug 02 '16 at 13:38
  • See my nickname... I will try. – misty Aug 02 '16 at 13:38
  • I think it cannot be done that way. I have no option to check if it's an integer when error is already occurred. I should probably have local variable char. Am I right? – misty Aug 02 '16 at 13:43
  • Do you know how to use `try` and `catch`? If you know how you want your program to behave when the `InputMismatchException` happens, this can be a good way to achieve it. – Dawood ibn Kareem Aug 02 '16 at 13:45
  • I know. (I think it is in code above). I know what is InputMismatchException, but I am asked to use my own (custom) Exception class, so I can't see how InputMismatchException can help me in this. – misty Aug 02 '16 at 13:47
  • Well, you can always catch the `InputMismatchException` and then throw your own exception object. An alternative would be to read the input into a `String` and then try to parse an `int` out of it - but if you do that, you just end up with a `NumberFormatException` instead of an `InputMismatchException`, and you have all the same problems as before. – Dawood ibn Kareem Aug 02 '16 at 13:48
  • OK. Thank you again. I don't like this task, it doesn't seem elegant and super-logical. – misty Aug 02 '16 at 13:51
  • No, to be honest, I don't really like this aspect of Java either. The `Scanner` class has always seemed a bit clunky to me, but then, so are the alternatives. – Dawood ibn Kareem Aug 02 '16 at 13:53