如何制作一个会提出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();
}
}
答案 0 :(得分:1)
我会亲自使用await
和signal
/ 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;
}
}
正如我所说的......只是另一种方式。