Java - 如何进行简单的检查?

时间:2016-10-31 02:48:44

标签: java multithreading

如何制作一个会提出5个问题的程序(多项选择a到d)?
使用线程睡眠(返回倒计时)每个问题都有30秒的时间 当倒计时到0时,它将进入下一个问题
以及如何使用公式添加分数?

import java.util.Scanner;
import java.io.IOException;

class timer{
    public static void main(String[]args) throws IOException{
         Scanner scan = new Scanner(System.in);
         Thread thread1 = Thread.currentThread();
         Thread thread2 = new Thread(() -> {
              try{
                   for(int seconds = 30; seconds >= 0; seconds--){
                        System.out.println("\rYou have "+seconds+"second's left!");
                        Thread.sleep(1000);
                   }
              }catch(InterruptedException e){}
          });
          System.out.println("What is 1+1? ");
          System.out.println("a. 1\t b.2\t c.3\t d.4");
          thread2.start();
          String answer = scan.next();
          thread2.stop();
    }
}

2 个答案:

答案 0 :(得分:1)

我会亲自使用awaitsignal / signalAll同步我的主题,并依赖方法Condition#await(long time, TimeUnit unit)来了解在等待时是否给出了答案,所以我的代码就是这样的:

Scanner scan = new Scanner(System.in);
// The lock used to used to synchronize my threads
Lock lock = new ReentrantLock();
// The target condition
Condition answered = lock.newCondition();
Thread thread2 = new Thread(() -> {
    try {
        // Indicates whether the question has been answered
        boolean hasAnswered = false;
        lock.lock();
        try {
            // Loop until the question has been answered or 10 seconds
            for (int seconds = 10; !hasAnswered && seconds >= 0; seconds--){
                System.out.printf("You have %d sec's left!%n", seconds);
                // Wait 1 second and if await returns true it means that
                // I had an answer in time otherwise it means that we
                // reached the timeout without getting answer
                hasAnswered = answered.await(1L, TimeUnit.SECONDS);
            }
        } finally {
            lock.unlock();
        }
        // Print the message indication whether we get the answer in time or not
        if (hasAnswered) {
            System.out.println("Good Job !!");
        } else {
            System.out.println("Too late !!");
        }
    } catch(InterruptedException e){
        Thread.currentThread().interrupt();
    }
});
System.out.println("What is 1+1? ");
System.out.println("a. 1\t b.2\t c.3\t d.4");
thread2.start();
String answer = scan.next();
lock.lock();
try {
    // Notify the other thread that we have an answer
    answered.signalAll(); // could be answered.signal() as we have only 
                          // thread waiting to be notified but it is a 
                          // better practice to use signalAll
} finally {
    lock.unlock();
}

成功时的输出:

What is 1+1? 
a. 1     b.2     c.3     d.4
You have 10 sec's left!
You have 9 sec's left!
You have 8 sec's left!
You have 7 sec's left!
2
Good Job !!

输出以防止为时已晚:

What is 1+1? 
a. 1     b.2     c.3     d.4
You have 10 sec's left!
You have 9 sec's left!
You have 8 sec's left!
You have 7 sec's left!
You have 6 sec's left!
You have 5 sec's left!
You have 4 sec's left!
You have 3 sec's left!
You have 2 sec's left!
You have 1 sec's left!
You have 0 sec's left!
Too late !!

答案 1 :(得分:1)

我知道这个帖子已经有了一个公认的答案,我真的很喜欢Nicolas Filotto的答案,但我想我只想分享另外一种方法来完成这个任务(就像Java中的任何东西一样),那就是使用 BufferReader()/ InputStreamReader(System.in),它允许您从控制台收集输入,如果操作正确,则不会阻止代码操作。当然,另一个线程用于问题时间限制机制。

但是,使用此代码有点麻烦,从Text文件中检索用户提出的问题,以便任何测试都可以与代码一起使用。这消除了对测试进行硬编码的需要。测试文本文件中的每一行都是一个由三部分组成的问题(用管道(|)字符分隔。第一部分是问题本身,第二部分是实际答案,可选第三部分是秒数允许回答问题。如果第3部分未提供问题,则使用默认值10秒。如果第3部分提供0,则问题不包含时间限制。测试文件内容应如下所示:

1: What is:  1 + 1 = ?\n   a: 1   b: 2   c: 3   d: 4\n|b|10
2: What is:  5 + 5 = ?\n   a: 1   b: 12  c: 10  d: 15\n|c|20
3: What is:  6 + 4 = ?\n   a: 10  b: 11  c: 12  d: 13\n|a
4: What is:  2 + 3 = ?\n   a: 3  b: 4  c: 5  d: 6\n|c|10
5: What is:  4 + 3 = ?\n   a: 7  b: 6  c: 5  d: 8\n|a|10

正如您在文件内容中所看到的,问题3使用默认时间限制。 \ n \ t 标记在文件文本中是允许的,并在处理代码中进行相应处理。

我不会深入研究代码操作,因为我已经很好地评论了它的作用。这是一个完整的可运行的:

package timedquestions;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import javax.swing.JDialog;
import javax.swing.JOptionPane;

public class TimedQuestions {
    private static String redColor = "\u001B[31m";      // for setting output text color red
    private static String blueColor = "\u001B[34m";     // for setting output text color blue
    private static String purpleColor = "\u001B[35m";   // for setting output text color purple
    private static String resetColor = "\u001B[39;49m"; // for resetting output text color to default
    private static boolean questionAnswered = false;    // Keeps track of whether a question was answered
    private static int questionCount = 0;               // Keeps count of number of questions asked to User
    private static int rightAnswers = 0;                // Keeps count of questions answered Correctly
    private static int wrongAnswers = 0;                // Keeps count of questions answered Incorrectly
    private static int defaultSecondsForTimout = 10;    // The default question time limit
    private static int secondsForTimout = 10;           //Current set time limit for question (can change by question)
    private static boolean timeOut = false;             // Keeps track of whether or not the question has timed out.


    public static void main(String[] args) {
        // Start the test...
        startTest("Test001.txt");  // Your test file path & name goes here.

        // Calculate and display score for test...
        double scr = (double) ((rightAnswers/questionCount)*100);
        int score =  (int) Math.ceil((double)rightAnswers/(double)questionCount*100.0);

        System.out.println("\n======================================================");
        System.out.println("Out of a total of " + questionCount + " questions\n"
                         + "you got " + rightAnswers + " questions Correct and\n"
                         + "you got " + wrongAnswers + " questions Wrong.\n"
                         + "Your score is " + + score + "% "
                         + "which gives you a grade of '" + getLetterGrade(score) + "'.");
        System.out.println("======================================================");

        // Done.
    }

    private static void startTest(String testFilePath) {
        // Get the number of lines (questions) within the supplied Test file...
        int fileLinesCount = 0;
        LineNumberReader  lnr;
        try {
            lnr = new LineNumberReader(new FileReader(new File(testFilePath)));
            lnr.skip(Long.MAX_VALUE);
            fileLinesCount = (lnr.getLineNumber() + 1);
            //System.out.println("Within this Test there are " + fileLinesCount + " questions.");
            lnr.close();
        } 
        catch (FileNotFoundException ex) { System.out.println(ex.getMessage()); return; }
        catch (IOException ex) { System.out.println(ex.getMessage()); return; }

        // Display test information to the User via a Message Box
        // and allow User to start the test.
        String msg = "Within this Test there are " + fileLinesCount + " questions.\n" +
                     "You will have " + secondsForTimout + " seconds to answer each test question.\n" +
                     "If a question runs out of time then you will get that question WRONG.\n\n" +
                     "Press the OK button to start the Test:";
        JDialog dialog = new JDialog();
        dialog.setAlwaysOnTop(true);    
        JOptionPane.showMessageDialog (dialog, msg, "Test Inforamtion...", JOptionPane.PLAIN_MESSAGE);  
        dialog.dispose();

        // Open a Bufferreader to read in questions from the Test file.
        try (BufferedReader fileReader = new BufferedReader(new FileReader(testFilePath))) {
            // Iterate through the Test file and process one question at a time....
            String testFileLine = "";
            while ((testFileLine = fileReader.readLine()) != null) {
                // Split the file line question into specific parts.
                // 1st part will be the question itself, 2nd part will be 
                // the answer and the 3rd part will be the number of seconds
                // allowed to answer question. If the 3rd part is not supplied
                // within the file line question then a default of 10 seconds 
                // is used as set by the defaultSecondsForTimout class global 
                // variable.
                String[] fileQuestionParts = testFileLine.split("\\|");
                String question = fileQuestionParts[0];
                // Allow for newline and tab tags within text string.
                question = "\n" + question.replaceAll("\\\\n", "\n").replaceAll("\\\\t", "\t");
                //Get the question answer from file line
                String questionAnswer = fileQuestionParts[1];
                // If the seconds time out is provided within the question file
                // line then grab it for use. If 0 is supplied then there is no 
                // time limit on that particular question.
                if (fileQuestionParts.length > 2) { secondsForTimout = Integer.parseInt(fileQuestionParts[2]); }
                // otherwise use the default of 10 seconds.
                else { secondsForTimout = defaultSecondsForTimout; }


                String answerResult = "";
                questionCount++;    // Increment the questionCount variable
                questionAnswered = false;   // Set the qustionAnswered variable

                // Ask the retrived question to User....
                answerResult = askTimedQuestion(question, secondsForTimout);
                questionAnswered = true;

                // If the User entered quit then quit the test.
                if (answerResult.equalsIgnoreCase("quit")) { break; }

                // If the User supplied input is the right answer then...
                if (answerResult.equalsIgnoreCase(questionAnswer)) { 
                    System.out.print(blueColor + "  CORRECT\n " + resetColor);
                    rightAnswers++;     // Increment the rightAnswers variable.
                }
                // If the User supplied input is the wrong answer then...        
                else { 
                    wrongAnswers++;     // Increment the wrongAnswers variable.
                    System.out.print(redColor + "  WRONG\n " + resetColor); }
            }
            // Close the file reader.
            fileReader.close();
    }
        catch (IOException e) { 
            // Display file errors
            System.out.println("\nERROR! - " + redColor + e.getMessage() + resetColor); 
        }
    }

    // Method for asking the questions retrieved from the supplied Test file
    private static String askTimedQuestion(String question, int secondsPerQuestion) {
        // The secondsPerQuestion parameter allows you to change
        // the number of seconds for each question if seconds are
        // applied to a particular question within the Test file.
        secondsForTimout = secondsPerQuestion;

        // Establish a new Thread for perform our question timing...
        Thread timerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // See if this thread has been interrupted. If it has then
                    // we stop our timer While/Loop (a gracefull Thread Stop).
                    while (!Thread.currentThread().isInterrupted()) {
                        for (int seconds = secondsForTimout; seconds >= 1; seconds--){
                            // Break out of this timer FOR loop if the question
                            // was answered by using Thread.interrupt().
                            if (questionAnswered) { Thread.currentThread().interrupt(); break;}
                            // Show that timer is ticking away...
                            System.out.print(purpleColor + "*" + resetColor);

                            // ==========================================================
                            // Or you can use this...
                            //if (seconds < secondsForTimout) { System.out.print("-"); }
                            //System.out.print(seconds);
                            // ==========================================================
                            Thread.sleep(1000);
                        }

                        // If the question wasn't answered and our timer loop has 
                        // expired then inform User that time is up and set the
                        // timeOut variable to true.
                        if (!questionAnswered) { 
                            System.out.print("\b\b\b\u001B[31mYour time is up for this question!\u001B[39;49m");
                            timeOut = true; 
                        } 
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        // Catch Exceptions for BufferReader()/InputStreamReader()...
        try {
            // Declare a BufferReader object so as to get input from User.
            // We use BufferReader along with InputStreamReader(System.in) 
            // for this.
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

            // Display the supplied Question from file to User...
            if (questionCount > 1) {
                System.out.println("\n------------------------------------------------------");
            }
            System.out.print(blueColor + "[" + secondsForTimout + " seconds]" + resetColor);
            System.out.println(question);

            // Declare User input variable & initialize to a Null String
            String input = "";      

            // Reset the timeOut variable
            timeOut = false;    

            // Make sure our timer thread is dead before restarting it.
            //while (timerThread.isAlive()){}
            // Start the Timer Thread
            if (secondsPerQuestion > 0) { timerThread.start(); }

            // Loop through input from the User
            do {
                // Wait until we have User input data to complete a readLine()
                // or until our timer thread has set the timeOut variable to
                // true.
                while (!br.ready()) {
                    // If our timer thread has set the timeOut variable to
                    // true then let's get outta this question altogether.
                    // First we get out of our 'wait for input' loop...
                    if (secondsPerQuestion > 0 && timeOut) { break; }
                }
                // Then we get out of our Do/While Loop.
                if (secondsPerQuestion > 0 && timeOut) { break; }

                // No time-out so let's move on...
                // Let's see what the User supplied for an answer.
                // If just ENTER was supplied then input will contain
                // a Null String and the User can still enter an answer
                // until the question is timed out.
                input = br.readLine(); 

                // remove any unwanted text from System.out.print() 
                // that had made its way through the timer thread.
                System.out.print("\b\b\b\b\b");

            } while ("".equals(input));

            // Stop the timer thread.
            timerThread.interrupt();

            return input;
        }
        catch (IOException ex) { return ""; }
    }

    // Determine & return the Letter Grade for the 
    // supplied integer test percentage score. This
    // is a typical North American Standard (I think?).
    private static String getLetterGrade(int score) {
        String grade = "";
        if (score >= 90) { grade = "A"; }
        if (score >= 80 && score <= 89) { grade = "B"; }
        if (score >= 70 && score <= 79) { grade = "C"; }
        if (score >= 60 && score <= 69) { grade = "D"; }
        if (score >= 0 && score <= 59) { grade = "F"; }
        return grade;
    }
}

正如我所说的......只是另一种方式。