I am making a timed quiz where there should be a timer on each question.
I want my code to output a question for 20 seconds and ask for an input for the answer and when the time is up, question number 2 should show up. I am stuck on what should I do to have that, a reference is enough, I just don't know what to read on about, I am using java.util.Timer and TimerTask.
I also tried
ExecutorService but i only see examples that it shutsdown after the timer, i need to post another question after the timer ends, not shotdown the program since i need a time limit for each question and not a timer for the whole quiz.
I tried this
if(seconds<=20)
{
question1();
}
else if (seconds<=40||seconds>=21)
{
new ProcessBuilder("cmd","/c","cls").inheritIO().start().waitFor();
question2();
}
I also tried using while
while(seconds<=20){
question1();
}
while(seconds<=40||seconds>=21){
new ProcessBuilder("cmd","/c","cls").inheritIO().start().waitFor();
question2();
}
This is what my question method looks like.
public static void question2(String... args) throws
IOException, InterruptedException
{
System.out.println("");
System.out.printf("%72s\n","QUIZ FOR PHILIPPINE HISTORY");
System.out.println("");
System.out.printf("%64s\n","Question #2");
System.out.println("");
System.out.println("\t\t\t\t\t WHO DISCOVERED PHILIPPINES?");
System.out.println("\n\t\t\t\t\t\tA. Fernando Magellan");
System.out.println("\t\t\t\t\t\tB. Ferdinand Megallan");
System.out.println("\t\t\t\t\t\tC. Ferdinand Magellan");
System.out.println("\t\t\t\t\t\tD. Fernando Poe");
System.out.println("\n\t\t\t\t\t\tTYPE YOU ANSWER HERE: ");
char answer2 = a.nextLine().charAt(0);
switch (sagot2)
{
case 'B':
case 'b':
score++;
seconds = 21;
System.out.print("You are CORRECT!");
break;
default:
System.out.print("You are WRONG");
seconds = 21;
break;
}
}
This is the beginning of my code plus the timer and timertask.
import java.util.Timer;
import java.util.TimerTask;
import java.util.Scanner;
import java.io.IOException;
public class q2 {
static int seconds = 0;
static Scanner a=new Scanner(System.in);
static Timer timer = new Timer();
static int number = 1;
static int score = 0;
public static void mema(){
TimerTask task = new TimerTask ()
{
public void run()
{
seconds++;
System.out.print(seconds);
}
};
timer.schedule(task,1000,1000);
}
I also tried using this but it doesnt do the other method after 5 seconds.
long start = System.currentTimeMillis();
long wait = 5000;
long end = start + wait;
long end1 = end + wait;
while (System.currentTimeMillis() < end)
{
question1();
}
while (System.currentTimeMillis() < end1 || System.currentTimeMillis() > end)
{
question2();
}
Various things that you did make your code more complicated then it ought to.
First of all, avoid fixing details such as "this is the first question" versus "this is the second question".
Instead: focus on basic elements that you need. In your case: you want to display a question for a certain amount of time. Afterwards, the program should either display another question - or probably give a summary and end.
Thus: write a class/method that simply puts up a question and then waits. And then think how you could re-use that code to put up any number of questions in sequence.
For the "timing": given the fact that you are a beginner, I would recommend you to not go "fully multi-threaded" (meaning: tasks, and schedulers) at this point. Instead, "waiting for some time" can easily be achieved via
getting the currentTime
endTime = currentTime + 20 sec
looping until that endTime is reached
Thing is: you learn programming by exploring your options and trying many things. Thus I gave you hints - not code.
Related
I managed to get the customers showing up at random times, the only problem I have now is wrapping the whole thing in a 2-minute timer without conflicting with the customer arrivals.
static Timer timer = new Timer();
static class Task extends TimerTask {
#Override
public void run() {
int delay = (new Random().nextInt(5)+2) * 1000;
timer.schedule(new Task(), delay);
System.out.println("Hi " + delay);
}
}
public static void main(String args[]) {
new Task().run();
}
This is what I have that works so far. I've tried wrapping it in another TimerTask, and using System.nanoTime() and a while loop. They both just end up conflicting with the customer arrivals. I usually like to figure things out on my own, but I've been working on this one part for hours and I can't figure it out.
Why not to use a sleep with a do-while loop like:
long durationMillis = TimeUnit.MINUTES.toMillis(2);
long endTime = System.currentTimeMillis() + durationMillis;
do {
int delaySec = ThreadLocalRandom.current().nextInt(2, 7);
TimeUnit.SECONDS.sleep(delaySec);
System.out.println("Hi " + delaySec);
} while (System.currentTimeMillis() < endTime);
Change delaySec semantics if you don't need to wait for whole seconds or 6 second wait is not inclusive.
I've been practicing with threads, so I wrote up this timed game where the user needs to guess the correct number (ranges from 1-10). If the user guesses the correct answer in the time limit, the thread stops and the program terminates. It fails to work when the user fails to guess within the time limit. Even though it enters the if-statement after the time limit, it still fails to interrupt the thread completely unless I guess the correct number. I have read other threads but they seem to use ask about the "traditional" guessing game or utilizing Timer. Explanation and/or tips for a suggested solution is also appreciated.
import java.util.*;
import static java.lang.System.out;
import java.io.*;
public class Threading implements Runnable {
private static int num;
private static int k;
public void run() {
try {
Scanner line = new Scanner(System.in);
k = -1;
out.println("Guess!");
while (k != num) {
k = line.nextInt();
if (k != num) {
out.println("Nope");
}
}
}
catch (Exception e) {
out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
out.println(num);
Thread t = new Thread(new Threading());
t.start();
long patience = 1000 * 5;
long startTime = System.currentTimeMillis();
while (t.isAlive()) {
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience) && t.isAlive()) {
out.println("I'm in here!");
t.interrupt();
t.join();
out.println("Times up!");
}
}
}
}
Since one of the comments already points out that the call to nextInt will block I don't think there is a need to go into the details of that.
So for now I'm going to assume you're fine with allowing the user 1 final guess after the timer expires.
The following is the modified code including my comments. I refer to the thread you named t as the "guessing thread".
private static int num;
private static int k;
//Changed variable "line" to "scanner" and made it static so that the
// main method can close it once everything is done.
private static Scanner scanner = new Scanner(System.in);
public void run() {
try {
k = -1;
System.out.println("Guess!");
while (k!=num) {
//Added a check for interrupt, otherwise this thread will never
// end unless the user enters the correct answer.
if(Thread.currentThread().isInterrupted())
return;
k = scanner.nextInt();
if(k != num){
System.out.println("Nope");
}
}
System.out.println("Correct!");
} catch (Exception e) {
System.out.println("I'm not done!");
}
}
public static void main(String args[]) throws InterruptedException {
num = (int) (Math.random() * 9 + 1);
System.out.println(num);
//Declared the guessing thread as final so it can be used inside of
// the TimerTask that is created later.
final Thread t = new Thread(new GuessUntilTimeLimit());
t.start();
long patience = 1000 * 5;
//Use a Timer to enforce your time limit, the TimerTask will execute
// an interrupt of your guessing thread if the thread is still alive
// (it may have died already if user got right answer)
Timer timer = new Timer();
TimerTask task = new TimerTask(){
#Override
public void run() {
if(t.isAlive()){
t.interrupt();
System.out.println("Times up! Enter your final guess now.");
}
}
};
timer.schedule(task, patience);
//Wait for the guessing thread to finish before canceling the timer
t.join();
//By now either the user got the answer or time has run out. Either way
// we need to clean up by canceling the timer.
timer.cancel();
//Added a call to close the scanner, it's always important to release
// resources
scanner.close();
}
Now your main thread schedules a task to execute after patience milliseconds. This task is then responsible for interrupting the "guessing thread". The "guessing thread" will check for interrupt and stop itself when appropriate.
Again, depending on your requirements, you may need to alter the way you accept user input since nextInt will block the thread. For completeness I'm including a link to the question regarding interrupting Scanner.nextLine mentioned in the comments.
I have started a Java coding short course at a university about 5 months ago. I have learnt quite the amount of things with regards to Java coding, but am still lacking in other things such as threads, handling exceptions, or even making JFrame games. I decided to embark on a text based game to just learn and figure out how a game loop should work (kind of), and how the logic should work (still, very "kind of"). The game I wrote runs with if-else commands, thus you get displayed a screen, type in the command of the option you want to pick, and it bumps you to the next menu, very standard of course. I run these if-else statements within nested for loops.
My nested for loops looks like the following:
// This is just an example, they're actually a lot more cluttered
// in my actual source code.
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
for (int i = 0; i <= 10; i--)
{
for (int ii = 0; i <= 10; i--)
{
if (reply.equalsIgnoreCase("/help")
{
System.out.println("Here I have a separate call to a class
file (excuse me, forgot the exact wording), thus it
call something like help.writeOutput(); to display
the help menu");
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/makegameeasy")
{
// Just an example.
gamedifficultyEasy.writeOutput();
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else if (reply.equalsIgnoreCase("/makegamedifficult")
{
// Another example.
gamedifficultHard.writeOutput();
reply = keyboardInput.nextLine();
if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else if (reply.equalsIgnoreCase("/back")
{
mainMenu.writeOutput();
reply = keyboardInput.nextLine();
break;
}
}
else
{
System.out.println("Here I print out an error for incorrect
input received, standard fare.");
mainMenu.writeOutput();
reply = keyboard.nextLine();
break;
}
}
}
As mentioned, the above is just an example, it's not very elegant, and I can probably use Exceptions for any incorrect info submitted by the user, however I do not know too much of Exceptions to comfortably add them, so I'll do that at a later time, however my main issue at the moment is a part of my game where "resource mining" has to be done on regular intervals. I have been all over Google, but still can't quite catch how to set a Thread or Timer up for my game so it does the mining automatically, and the player can go on with their game.
The game is essentially one of those games where you build up a base, upgrade your mining tools, and generate more "stuff". I have pasted a few blocks of code from my "mining" class file below that will basically run how much of one thing should be mined. In the game you will be able to buy upgrades of course, so it will get factored into your mining speed.
// I initiate my variables a lot earlier, but just for some
// clarity, I have initiated the variables in the below methods,
// they will not work correctly anyway, I am aware of that, however
// I didn't want to add the other "get, set and initiate"
// variables and methods everywhere, as to not spam this block of code.
// upgradeOS, upgradeHF, and upgradeLM all have their own respective
// set and get methods. They are also all int variables.
public void handleOS()
{
// OS = short for Oxygen Silo
int mineOS = os.getStoredO2() + (1 * upgradeOS);
os.setStoredO2(mineOS);
}
public void handleHF()
{
// HF = short for Hydrogen Fuel
int mineHF = hf.getStoredO2() + (1 * upgradeHF);
hf.setStoredO2(mineHF);
}
public void handleLM()
{
// LM = short for Liquid Minerals
int mineLM = lm.getStoredMinerals() + (1 * upgradeLM);
lm.setStoredMinerals(mineLM);
}
// This is what's going to run the whole time on the set intervals.
public void mine()
{
mineOS = os.getStoredO2() + (1 * upgradeOS);
mineHF = hf.getStoredO2() + (1 * upgradeHF);
mineLM = lm.getStoredMinerals() + (1 * upgradeLM);
os.setStoredO2(mineOS);
hf.setStoredO2(mineHF);
lm.setStoredMinerals(mineLM);
}
// Using 10 seconds here to have it update as quickly as possible so I can
// see any changes. This is just here to write an output.
public void getUpgradeInfo()
{
System.out.println("Oxygen: " + (1 * upgradeOS) + " / per 10 seconds.");
System.out.println("Hydrogen: " + (1 * upgradeHF) + " / per 10 seconds.");
System.out.println("Liquid Mineral: " + (1 * upgradeLM) + " / per 10 seconds.");
}
I'm not the best naming schemes for my materials...
TL;DR: I can't figure out how to implement a thread or timer just for the above mentioned mine() method since I do not have the appropriate amount of knowledge. My if-else rules aren't too elegant, but I'll work on those of course. Basically the if-else rules should run separately from the mine() method, and you can do some AFKing without the game updating the System.out output, thus you can be floating in, for example, the Oxygen Silo upgrade menu, and you won't be bounced back to a different menu due to a thread "waking up", such as being bounced to the main menu, but the mine() method will still generate resources in the background as it should.
Any help on this, or just even a nudge in the right direction will be greatly appreciated.
To answer the question you asked, you can do something like this:
import java.util.*;
TimerTask tt = new TimerTask() {
public void run() {
mine();
}
}
Timer t = new Timer();
t.scheduleAtFixedRate(tt, 0, 1000);
Alternatively, you can use an ActionListener and the swing timer in a similar way. This has the advantage of being Thread-safe in case you build a swing gui on top
Lastly, you should check out the usage of synchronized and volatile to make sure that the variable(s) that are updated in mine() are done so in a thread-safe way
Thanks to #ControlAltDel, definite shove in the right direction. I have taken a bit of code and set it up like this:
import java.util.*;
// extends TimerTask needed
public class TimerTestOne extends TimerTask
{
// Needed
#Override
public void run()
{
TimerTestTwo ttt = new TimerTestTwo();
mine();
}
// Needed, method doesn't need the same name though.
private void completeTask()
{
try
{
//assuming it takes 10 secs to complete the task
Thread.sleep(10000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
// You will need to define the following line of code:
TimerTask tt = new TimerTestOne();
Scanner keyboard = new Scanner(System.in);
String reply;
// Following 2 lines of code, yup, need them.
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(tt, 0, 10*1000);
previousMenu();
for (int i = 0; i <= 10000; i++)
{
for (int ii = 0; ii <= 10000; i++)
{
System.out.println("Go to another menu?");
reply = keyboard.nextLine();
if (reply.equalsIgnoreCase("/yes"))
{
yes();
reply = keyboard.nextLine();
}
}
}
}
// I added the following methods, just so I didn't have to work
// off 2 class files.
public void mine()
{
System.out.println("Mined");
}
public static void yes()
{
System.out.println("Next menu");
}
public static void previousMenu()
{
System.out.println("Previous menu");
}
}
So there, if anyone ever needs to have a look at setting a timer up that won't break your text based game.
I'm trying to develop a timer for chess game.
There should be a function like
wait for user input there move from Console
if wait time > 60
stop waiting and keep going.
What I can think of to solve this is using Thread like:
public class Game {
Thread t1 = new PlayDisc(this);
Thread t2 = new Timer(this);
public static void main(String[] args) {
t1.start();
t2.start();
}
}
public class Timer extends Thread{
Game g;
public Timer(Game g) {
this.g = g;
}
#Override
public void run() {
int i = 0;
while(true){
if(i > 6000) {
g.t1.interrupt();
break;
}
}
}
}
public class PlayDisc extends Thread{
private Game g;
public PlayDisc(Game g) {
this.g = g;
}
#Override
public void run() {
Scanner s = new Scanner(System.in);
int x = s.nextInt();
int y = s.nextInt();
Point p = new Point(x, y);
cm.nextPoint = p;
s.close();
}
}
I know this will not work as Scanner.nextInt() is a blocking method. But I'm required to read input from cmd line.
Is there any way to solve this?
There is already a Timer class (in fact two of them, java.util.Timer and javax.swing.Timer). But as you've realized, the blocking nature of nextInt() prevents you from doing anything after the timeout. You would need an additional library that would give you better console control than Java does by default. That, or use Swing.
Edit: It might be possible to perform a hack of some sorts, by using a polling loop with hasNextInt(). That way you wouldn't let the scanning thread block.
Re-Edit: Nah, it's not possible, since hasNext() will block. You'll have to test whether the interrupt will get you out of the trouble here (it might not).
The problem with Scanner is that you don’t have control over the method’s reading more bytes which can always cause blocking. The safe way is to read from System.in manually and create a Scanner which can only read the bytes you already got from the console. Then you can do polling (with sleeping) for implementing a time-out. By choosing the right amount of time for sleeping you get the right balance between responsiveness and CPU usage.
The example program below uses a check interval of 200ms which is good enough to be perceived as “immediate response” by a human user. This value is independent from the wait time which you can configure freely (as long as it is significantly higher than the check interval).
Other things to be aware of is that we calculate a deadline at the beginning rather than aggregating waiting times to be independent of CPU usage within the loop. And we use System.nanoTime() to be independent from changes that might happen to the system’s clock.
long timeOutNS=TimeUnit.MINUTES.toNanos(1); // 1 min timeout
long checkNS=TimeUnit.MILLISECONDS.toNanos(200); // check input every 200ms
int input=0;
boolean hasInput=false;
readWithTimeOut: {
System.out.println("Enter int: ");
long deadLine=System.nanoTime() + timeOutNS;
for(;;) {
int a = System.in.available();
if(a>0) {
byte[] b=new byte[a];
a=System.in.read(b);
if(a<=0) break readWithTimeOut;
Scanner scanner=new Scanner(new ByteArrayInputStream(b, 0, a));
if(scanner.hasNextInt()) {
input=scanner.nextInt();
hasInput=true;
break;
}
else if(scanner.hasNext())
System.err.println("not an int: "+scanner.next()); // consumes token
continue;
}
long remaining=deadLine-System.nanoTime();
if(remaining<=0) {
System.err.println("timeout");
break readWithTimeOut;
}
LockSupport.parkNanos(Math.min(remaining, checkNS));
}
}
System.out.println( hasInput? "entered "+input: "no valid input" );
InputStream.available() is a non-blocking method that you can use to check if there's something in the stream.
If you don't care about spinning (and thus wasting a processor core) that's as simple as it can get:
import java.io.IOException;
import java.util.Scanner;
public class ConsoleReadWithTimeout {
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws Exception {
int i = readIntWithTimeout(5 * 1000);
scanner.close();
}
// returns -1 in case of timeout
static private int readIntWithTimeout(long timeoutInMs) throws IOException {
long startTime = System.currentTimeMillis();
while (System.in.available() == 0) {
if (timeoutInMs < System.currentTimeMillis() - startTime) {
return -1; // or maybe throw a TimeoutException ?
}
}
return scanner.nextInt();
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
I'm working on a IRC Twitch.tv BOT (PircBot) and i want to implement a !uptime chatcommand which will display how long the Stream is online.
I searched in google a Bit and i only found solutions which requires a GUI.
Can Some1 tell me what libraries are good to use or give me some exampel code?
I need to display seconds, minutes, hours, days.
First i thought about doing a normal timer which counts +1 all seconds but i think its easier and there are some proper functions to handle such "count"-timers, right?
Im fine with any hints!
thanks :)
Thats what i came up with now:
In my Main class, i got a timer which i call with:
utimecounttimer();
My Timer looks like this:
public void utimecounttimer() {
uptimetimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (isstreamlive == true){
UptimeCount.Uptimestart();
}else{
UptimeCount.Uptimestop();
}
}
}, 1000, 1000);
}
and then my UptimeCount Class is here:
public class UptimeCount {
public static long startTime = 0;
public static long OnlineTimeMillis = 0;
public static float OnlineTimeSec = 0;
public static float OnlineTimeMin = 0;
public static float OnlineTimeHour = 0;
public static float OnlineTimeDay = 0;
public static void Uptimestart(){
if(startTime == 0){
startTime = System.currentTimeMillis();
}else
if(startTime != 0){
OnlineTimeMillis = System.currentTimeMillis()-startTime;
OnlineTimeSec = OnlineTimeMillis /1000F;
OnlineTimeMin = OnlineTimeMillis /(60*1000F);
OnlineTimeHour = OnlineTimeMillis /(60*60*1000F);
OnlineTimeDay = OnlineTimeMillis /(24*60*60*1000F);
}
System.out.println("Seconds"+OnlineTimeSec);
System.out.println("Minutes"+OnlineTimeMin);
System.out.println("Hours"+OnlineTimeHour);
System.out.println("Days"+OnlineTimeDay);
}
public static void Uptimestop(){
startTime = 0;
OnlineTimeMillis = 0;
OnlineTimeSec = 0;
OnlineTimeMin = 0;
OnlineTimeHour = 0;
OnlineTimeDay = 0;
}
}
And then, last but not least il get the Infos in chat with the following line in my Main class:
if (message.equalsIgnoreCase("!uptime")) {
sendMessage(channel," Stream is running for: "+UptimeCount.OnlineTimeDay +" Days, "+UptimeCount.OnlineTimeHour +" Hours. "+UptimeCount.OnlineTimeMin +" Minutes and " +UptimeCount.OnlineTimeSec +" Seconds.");
}
I didnt test it yet but i think i have to format the ms output of the floats and then it should be working, right?
You can use Joda Time to represent durations and times:
// at startup of the stream
DateTime startedAt = DateTime.now();
// later
Duration elapsed = new Duration(startedAt, DateTime.now());
And could use the solution described in this answer to format your output, to get a human readable output (ie. "1 hours 2 minutes").
Please also check Duration since it has methods like toStandardHours, toStandardMinutes which can be used to display the total number of hours/minutes/etc. elapsed (ie. "1 hours | 62 minutes").
// it will give you current time in mille seconds
long startTime = System.currentTimeMillis();
// Mill second diffrence
long OnlineTimeMillis = System.currentTimeMillis()-startTime;
// time diff in mille seconds since you are online
float OnlineTimeSec = OnlineTimeMillis /1000F;
// time diff in Minutes since you are online
float OnlineTimeMin = OnlineTimeMillis /(60*1000F);
// time diff in Hours since you are online
float OnlineTimeHour = OnlineTimeMillis /(60*60*1000F);
// time diff in days since you are online
float OnlineTimeDay = OnlineTimeMillis /(24*60*60*1000F);