简体   繁体   中英

Preventing the user from entering identical elements(within a malfunctioning try catch)

So the following code is like a simple game,where the objective to to guess the correct numbers(which are 1 to 5).Anything else is incorrect and the user is given a warning message if they enter similar numbers.The comments would explain the loops and variables declared.

The only problem I have with this code is that I inserted a try catch to take care of strings and that doesn't seem to work.If a string is entered,the while loop continues infinitely.

Also,I realize there are a loop pf looping and conditional statements present in my code,but I couldn't think of anything else.If you have any recommendations to reduce the number of loops and if statements,your help would be greatly appreciated.

 public class Tries {
            public static void main(String[]args)
            {


            boolean dataType=false;
            int Inp;
            Scanner a=new Scanner(System.in);
    //The arraylist,List, contains the input that the user enters.Only correct input is entered(1 to 5).
            ArrayList<Integer> List=new ArrayList<Integer>();

    //This determines how many times the for loop is going to execute.Say the user enters 4,and enters 4 correct inputs,the program will exit.The variable num basically determines what the size of the arraylist List is going to be.
                System.out.println("How many tries?");
                int num=a.nextInt();


                boolean datatype=false;

                    for(int j=0;j<num;j++)
                    {
    //This while loop is for the try catch.
                        while(!datatype)
                        {

                        Scanner sc=new Scanner(System.in);

    //This while loop ensures that the user re enters input when anything other than the correct numbers are entered.
                        while(List.size()!=num)
                        {
                            try
                            {
                                System.out.println("\nPick a number: ");
                                Inp=sc.nextInt();

                            if(Inp==1 || Inp==2 || Inp==3 || Inp==4 || Inp==5)
                            {

                                datatype=true;
                                System.out.println(j);

                                if(List.size()==0)
                                {
                                    List.add(Inp);
                                }
                                else if(List.size()>0)
                                {
                                        if(List.contains(Inp))
                                        {
                                            System.out.println("Already entered.Try again.");   
                                        }
                                        else if(!List.contains(Inp))    
                                        {
                                            List.add(Inp);
                                            System.out.println("Added");
                                            dataType=true;

                                            System.out.println(List);
                                        }
                                 }
                            }
                                else
                                {
                                    System.out.println("Option not available.");
                                    datatype=false;
                                }
                             }
                            catch(Exception JavaInputMismatch)
                            {
                                System.out.println("Option not available.Try again.");
                                datatype=false;
                            }
                        }
                    }
                }
            }
        }

So, when Inp=sc.nextInt(); fails because the user enters an invalid number, then an InputMismatchException gets thrown. Then you loop again, and eventually attempt to run Inp=sc.nextInt(); again.

The problem though is that the invalid number that was entered is still in the input stream waiting to be read. So in the next loop, when Inp=sc.nextInt(); is attempted again, it doesn't try to read in a new value, it just reads the previous invalid value without allowing you to type anything new. And this keeps happening over and over indefinitely.

The quick fix? You need to clear out the input stream to get rid of the invalid number before attempting to read a new one.

The simplest way to plug that fix in your program is by adding an sc.next(); call in your catch block like this:

catch(Exception JavaInputMismatch)
{
    sc.next(); // clear the bad token. Without this, it loops infinitely.
    System.out.println("Option not available.Try again.");
    datatype=false;
}

There are certainly quite a few other changes/improvements I would make to the program, but I'll admit that I lack the motivation at the moment to address those. Hopefully this will at least unblock you.

EDIT: I guess I can add a few high level suggestions that can help you:

  • As was already commented, you shouldn't have 2 Scanner instances reading from System.in .
  • I would recommend dropping the whole try-catch to detect an invalid number, and instead use sc.hasNextInt() to check before reading the number with sc.nextInt() . Even if you did keep the catch block, I would recommend you make the exception type as specific as possible (eg catch(InputMismatchException e) ) instead of the catch-all Exception . Otherwise, you risk catching irrelevant exceptions and handling them the wrong way.
  • You should be able to drop the datatype boolean variable and its associated loop. It's enough that you are looping as long as your list is not full.
  • In fact, if I'm understanding this correctly, you can probably simplify your loops by only keeping the one that does while(List.size()!=num) . I think you can safely get rid of the loop that does for(int j=0;j<num;j++) .
  • Minor detail, but you can express if(Inp==1 || Inp==2 || Inp==3 || Inp==4 || Inp==5) more succinctly like this instead: if(Inp >= 1 && Inp <= 5) .
  • And finally, the logic that determines whether to add the number to the list or not doesn't need to do a bunch of conditions based on the size of the list.

Something like this is sufficient:

if (List.contains(Inp)) {
    System.out.println("Already entered.Try again.");
} else {
    List.add(Inp);
    System.out.println("Added");
    System.out.println(List);
}

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM