0

My program keeps running after the timer kicks in... I want no more input to be taken after timer kicks in and go to the showResult() function... But program jumps back to taking input after displaying the results.

The program is perfectly fine if the timer doesn't kick in... But when the timer is on... I think a thread is still stuck at the function where i take the input and the flw the program goes back there when marks have been displayed. I don't want such a behavior to occur. The program should stop taking input as soon as the timer kicks in and never go back to it again. I am unable to figure out how to do so. I am a rookie in this field :P

import java.util.*;

class Quiz {
  private String questions[][];
  private int marks;
  
  public Quiz(){
    marks = 0;
    questions = new String[][]{{ 
      "Name of the screen that recognizes touch input is :",
      "Recog screen",
      "Point Screen",
      "Android Screen",
      "Touch Screen",
      "4",
      "" 
    }};
    //questions as stated above is filled.
  }


  public void displayQues(int x){
      System.out.print("\n Q. "+questions[x][0]);
      System.out.print("\n 1. "+questions[x][1]);
      System.out.print("\n 2. "+questions[x][2]);
      System.out.print("\n 3. "+questions[x][3]);
      System.out.print("\n 4. "+questions[x][4]);
  }
 
  public void getResponse(){
    Timer t = new Timer();
    t.schedule(
      new TimerTask(){
        public void run(){
          System.out.print("\n Time is up!");
          t.cancel();
          return;
        }
      }, 5*1000L);
    
    System.out.print("\n Timer of 5 Minutes started!");
    String temp = "";
    for(int i = 0;i < 10;i++){
      int x = genDiffRndNum(temp);
      displayQues(x);
      System.out.print("\n Enter your answer: ");
      if(validateAnswer(x))
        questions[x][6] = "T";
      else
        questions[x][6] = "F";
      temp = temp+x;
    }
  }

  public int genDiffRndNum(String str){
    while(true){
      int n = (int)(Math.random()*10);
      if(str.indexOf(Integer.toString(n))==-1)
        return n;
    }
  }

  public boolean validateAnswer(int ques){
    Scanner sc = new Scanner(System.in);
    int ans = sc.nextInt();
    sc.close();
    if(Integer.parseInt(questions[ques][5])==ans){
      marks += 3;
      return true;
    }
    marks -= 1;
    return false;
  }

  public void showResults(){
    System.out.print("\n Marks Obtained: "+marks);
    System.exit(0);
  }

  public static void main(String[] args) {
    Quiz q = new Quiz();
    q.getResponse();
    q.showResults();
    System.exit(0);
  }
}

Any suggestions would be appreciated :D

shinjw
  • 3,329
  • 3
  • 21
  • 42
  • Your program probably waits for input, however I doubt your program is perfectly fine as it throws `ArrayIndexOutOfBoundsException` almost immediately. – Ecto Aug 20 '20 at 19:53
  • The problem is that Scanner(System.in) waits for input in a separate thread. I am not even sure this can be done on the command line like this. You could try putting the input in a different thread and then forcefully terminating the input thread, but that is not pretty. – Jaco Van Niekerk Aug 20 '20 at 19:54
  • You may want to consider holding the timer on the main thread. Would help conceptualize this in terms of spinning up threads based on how the program would terminate. 1) the timer 2) upon validation of the correct answer – shinjw Aug 20 '20 at 20:03
  • @JacoVanNiekerk could you please tell me which different input thread can be used and how to terminate it? – hellownaman Aug 21 '20 at 03:51
  • @shinjw could you tell me how to do so... You have understood what I exactly want, but the problem is there can be various questions and I don't want the program to terminate after a single question. – hellownaman Aug 21 '20 at 03:53
  • @Ecto This program contains only 1 question so that you know the format... I have not put in all the questions... Hence there would be no such exception. – hellownaman Aug 21 '20 at 03:56
  • @hellownaman It contains 4 questions and it will throw an exception. Are you satisfied with answer it's stuck at taking input? – Ecto Aug 21 '20 at 07:30
  • @Ecto Its a 2D array... I have only defined 1 row of this array. this first element is the question... The next four are the answers. Next it contains which answer is the correct one... And the last is to denote if the user has entered the input correctly. No I am not satisfied with the answer that it is stuck at taking input. – hellownaman Aug 21 '20 at 09:32

1 Answers1

0

"return" within the TimerTask.run method returns from the TimerTask.run method. It does not make the getResponse() method exit.

To exit from getResponse(), the TimerTask has to set some kind of a flag, which is read by getResponse(). One possibility is to use an AtomicBoolean object. It's initially set to false, and when the timer triggers, it's changed to true:

    AtomicBoolean timeIsUp = new AtomicBoolean(false);
    Timer t = new Timer();
    t.schedule(new TimerTask() {
        public void run() {
            System.out.print("\n Time is up!");
            timeIsUp.set(true);
            t.cancel();
        }
    }, 5 * 1000L);

The loop in getResponse needs to check if the time is up:

    for (int i = 0; i < 10 && !timeIsUp.get(); i++) {
        ...
    }

However, this will only check for timeout between questions. While the program is waiting for the user to type, it cannot be interrupted.

Joni
  • 108,737
  • 14
  • 143
  • 193
  • Thanks.... That would partially solve my problem :) – hellownaman Aug 21 '20 at 03:59
  • What do you mean "partially"? – Joni Aug 23 '20 at 16:18
  • By partially I mean that my problem of interrupting input has not yet been solved. – hellownaman Aug 24 '20 at 07:53
  • Interrupting a read from `System.in` has been asked and answered before see for example https://stackoverflow.com/questions/49520625/how-to-interrupt-reading-on-system-in and this article https://www.javaspecialists.eu/archive/Issue153.html – Joni Aug 24 '20 at 10:44