Java countdown time doesnt display correct time - java

Im currently working on a project that has a simple countdown where the user enters a time and it starts counting down from that time. it is GUI based and displays the countdown to the user. ive managed to make it count down but its not displaying correctly.
For example, if i enter 1min 30secs, it counts down from 1:30, to 1:01 then incorrectly displays 0:00 then it counts down from 0:59. it is correct until i get to a point where the minutes change to seconds and it doesnt display correctly for 1 second.
Countdown class:
class countdownClass implements ActionListener { //counts down then beeps
int counter;
public countdownClass(int counter) {
this.counter = counter;
}
public void actionPerformed(ActionEvent sc) { //counts down every second
counter--;
if(counter >= 1) { //a simple countdown
if(counter > 9){ //this statement is for aestetic purpose as before
seconds.setText("" + counter);
}else{
seconds.setText("0" + counter);
}
}
else if(minutesNum >= 1 && counter <= 0){ //if minute exists carry on the countdown
// 1:01 - > 1:00 - > 0:59
int minuteUpdate = minutesNum - 1;
if (minutesNum < 9){
minutes.setText("0" + Integer.toString(minutesNum));
seconds.setText("00");
if(counter <= 0){
minutes.setText("0" + Integer.toString(minuteUpdate));
}
}else{
minutes.setText("0" + Integer.toString(minutesNum));
seconds.setText("0" + Integer.toString(00));
minutes.setText("0" + Integer.toString(minuteUpdate));
}
counter = 60;
}
else if(minutesNum == 0 && counter == 0) { //once the countdown ends plays a beep
timer.stop();
seconds.setText("00");
finish.setText("Time is up!");
start.setEnabled(true);
try{
clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("ring.wav")));
clip.start();
soundPlay = true;
}
catch (Exception e){
e.printStackTrace(System.out);
}
}
}
}
could you please help me identify where the code is going wrong and provide me with a fix for it.
Thanks for your time.

Your code looks a little over-engineered. Just convert the user-entered time into seconds and decrement that value every second. Then print the result with something like:
private static String secondsToMinutesAndSeconds(int time) {
int minutes = time / 60;
int seconds = time % 60;
return String.format("%02d:%02d", minutes, seconds);
}
E.g. 1 minute 30 seconds is just 90 seconds. Pass 90 into the above method and you get 01:30. If you need the minute and second values individually, it should be easy enough to edit that code example.

It appears that the minutes digit displayed is minuteUdpate which is set to one less than MinutesNum.
else if(minutesNum >= 1 && counter <= 0){ //if minute exists carry on the countdown
// 1:01 - > 1:00 - > 0:59
int minuteUpdate = minutesNum - 1;
if (minutesNum < 9){
minutes.setText("0" + Integer.toString(minutesNum));
seconds.setText("00");
if(counter <= 0){
minutes.setText("0" + Integer.toString(minuteUpdate));
}
}else{
minutes.setText("0" + Integer.toString(minutesNum));
seconds.setText("0" + Integer.toString(00));
minutes.setText("0" + Integer.toString(minuteUpdate));
}
counter = 60;
minutesNum is less than 9, and counter = 0 for 1:00, so this line should be done:
minutes.setText("0" + Integer.toString(minuteUpdate));
I'd remove that if block. The minutes number should not be decremented before the seconds number is changed to 60.

For me, your code is useless complex.
What you should do:
Use two variables to save minutes and seconds.
The start value of there two variables will be what the users put (Examples if its 3:50, minutes will be 3, second will be 50)
Start a timer every second, scale 1 second from counter and if seconds is <= 0, scale minutes and put seconds to 59. If minutes is 0 and seconds.
It's just a concept to show my idea:
private static int minutes = 0;
private static int seconds = 5;
private static Timer timer;
private static TimerTask task = new TimerTask()
{
#Override
public void run()
{
if (countdown())
System.out.println(minutes + ":" + seconds);
else
{
System.out.println("Finish!");
timer.cancel();
}
}
};
private static boolean countdown()
{
seconds --;
if (seconds < 0)
{
minutes--;
seconds = 59;
if (minutes == -1)
{
return false;
}
}
return true;
}
public static void main(String[] args)
{
timer = new Timer();
timer.schedule(task, 0, 1000);
}
You could work with seconds only and avoid the minutes variable.
(Example: 1 min => 60 seconds; and then use a method to fix it using division)
It's my first time i use ScheduledThreadPoolExecutor so it could not be perfect.
private static int minutes = 0;
private static int seconds = 5;
private static ScheduledThreadPoolExecutor executorService;
private static boolean countdown()
{
seconds --;
if (seconds < 0)
{
minutes--;
seconds = 59;
if (minutes == -1)
{
return false;
}
}
return true;
}
private static Runnable task = new Runnable()
{
#Override
public void run()
{
if (countdown())
System.out.println(minutes + ":" + seconds);
else
{
System.out.println("Finish!");
// by throwing an exception we will stop the countdown
throw new RuntimeException();
}
}
};
public static void main(String[] args)
{
executorService = new ScheduledThreadPoolExecutor(1);
executorService.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
try
{
// schedulate again the countdown
System.out.println("Wait 7 seconds");
Thread.sleep(7000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Schedulate again");
// since we work with the original values
// we must reset it
minutes = 0;
seconds = 5;
executorService.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
}
Remember: this code don't work if multi threads calls countdown method!
Anyway, you can use executorService.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS); to restore the countdown.

Related

How do I stop the timer from counting down when I switch to pause state?

I have a java game wherein there is a countdown timer from 60 secs. It works fine, but when I pause the game and return back to play state. the original time is now reduced because I found out that the timer still keeps running from the system no matter what gameState I'm in. How do I fix this?
I tried storing the remainingTime to a pauseTime variable whenever I switch states, and just subtract it and stuff. But my efforts seem to failed.
// GET ELAPSED TIME
if(gp.gameState == gp.playState && remainingTime >= 0) {
soundCounter--;
elapsedTime = System.currentTimeMillis() - startTime;
remainingTime = totalTime - elapsedTime;
if(remainingTime <= 0) {
remainingMilliseconds = 0;
remainingSeconds = 0;
remainingMinutes = 0;
// GAME OVER
gp.gameOver();
} else {
remainingMilliseconds = remainingTime % 1000;
remainingSeconds = (remainingTime / 1000) % 60;
remainingMinutes = (remainingTime / 1000) / 60;
}
}
// DRAW TIMER
timeString = String.format("%02d:%02d:%03d", remainingMinutes, remainingSeconds, remainingMilliseconds);
Your problem is that you are calculating your elapsed time forever since the first startTime.
One of the solution would be to calculate a delta (difference) time between loop iterations.
Here some very primitive code that should get you started:
public static void main(String[] args) {
boolean paused = false;
long lastRun = System.currentTimeMillis();
long elapsed = 0;
System.out.println("Game start");
while (true) {
long now = System.currentTimeMillis();
long delta = now - lastRun;
if (!paused && delta > 0) {
elapsed += delta;
// Do game stuff
System.out.println("Elapsed: " + elapsed);
if (elapsed >= 5000) return;
lastRun = now;
}
}
}

How do I make a countdown from 10 for a Bukkit Plugin?

I am trying to make a Championships kind of plugin where there is a start-game command that starts the game after counting down from 10. However, I cannot find a way to wait 1 second as an interval in the countdown. I have tried Object.wait(long) and BukkitScheduler.setRepeatingDelayedTask() but neither of them are working out for me (object.wait() returns java.lang.IllegalMonitorStateException: current thread is not owner and BukkitScheduler.setRepeatingDelayedTask() errors in my editor). Anyone know a workaround to this?
// See how many seconds have been counted
private int count;
private BukkitTask task;
public void doStuff() {
// Reset count
count = 0;
task = new BukkitRunnable() {
#Override
public void run() {
// If count is less than or equal to ten, increment count, otherwise set count to -1.
count = count <= 10 ? count + 1 : -1;
if (count >= 10 || count == -1) {
// Cancel task if count is over 10s
task.cancel();
return;
}
Bukkit.getLogger().log(Level.INFO, "Seconds passed: " + count + "!";
}
}.runTaskTimer(YourPlugin.getPlugin(), 0, 20);
}
Use BukkitScheduler is the solution. But, it count in tick where 20 ticks = 1 seconds.
So, you have to do something like this:
private BukkitTask task;
private int count;
public void startTimer() {
count = 10; // restart count down at 10 seconds
task = Bukkit.getScheduler().runTaskTimer(MyPlugin.getInstance(), ()-> {
// here what you want
if(count == 0)
task.cancel(); // cancel the task if the counter is finished
count--; // reduce the counter
}, 20, 20);
}
The first "20" is the time before starting scheduler. The second is the time between each call (both in ticks).
Also, don't use Thread.sleep() or Object.wait() because they could freeze the full server, and maybe timed out everyone...

Adding functions to Thread class in Java

I have written a simple clock class to simulate time I need it to run at the same time as other threads so I made it threaded I have a few extra methods that get units of time used in my system but now I have changed it to a threaded system I can't seem to get hold of them.
Here is the code for the clock class
public class Clock extends Thread {
private Integer seconds;
private Integer minute;
private Integer hour;
public Clock()
{
setClock(0,0,0);
}
public void setClock(int hr, int min, int sec)
{
if(0 <= hr && hr < 24)
{
hour = hr;
}
else
{
hour = 0;
}
if(0 <= min && min < 60)
{
minute = min;
}
else
{
minute = 0;
}
if(0 <= sec && sec < 60)
{
seconds = sec;
}
else
{
seconds = 0;
}
}
public void tick()
{
this.seconds += 5;
this.minute += (int)(this.seconds/60);
this.seconds = this.seconds % 60;
this.hour += (int)(this.minute/60);
this.minute = this.minute % 60;
this.hour = this.hour % 24;
}
public int getMin()
{
return this.minute;
}
public int getHour()
{
return this.hour;
}
public String getTime()
{
return minute.toString() + "m" + seconds.toString() + "s";
}
public void run()
{
tick();
}
}
The three functions above the run are the ones causing the problem I have looked for a solution but can't find one I thought that ´extends´ was like inheritance and it would add those methods to the Thread.
Here is the thread declaration
Thread clock1 = new Clock();
I start it in the normal way of doing start then join as I am running multiple threads.
Thread TestJunc4 = new CarPark(100,TestTemp4,clock1);
I pass the thread into the other threads that need it then try and make a call like this , I am just giving the top part of the statement as the rest doesn't seem important.
while(clock.getHour() != 1)
The problem is I can't call the get methods like the ´getHour´ I am using net beans and when I get the list of functions they don't show up in it and if I add them manual I get the error that it can't find them.
Your Clock class is extending Thread. So and instance of Clock is a Thread too.
This means everywhere, where the java api expects an thread you can pass your clock object. But when you need special methods of your impl. your have to pass it as clock.
Clock clock1 = new Clock();

Creating a java Clock. increasing time

I am creating a clock in Java. I have managed to do some very basic stuff and now i want to implement a function.
If i set the time to i.e. 12:04:59 and use my timeTick Method it will increase the time with 1 second but the problem is it will say the time is 12:04:60 and it doesn't change to 12:05:00.
I've been struggling a while now and i can't really find a solution to it.
My code is below, i hope you can help me,
public class Clock{
public int seconds;
public int minutes;
public int hours;
public Clock ( int InsertSeconds, int InsertMinutes, int InsertHours){
seconds = InsertSeconds;
minutes = InsertMinutes;
hours = InsertHours;
}
public void timeTick(){
seconds = seconds + 1;
}
public String toString(){
return hours + ":" + minutes + ":" + seconds;
}
}
I am not planning to use Imports because i am a beginner it would be great if we can keep it simple.
The problem here lays in the timeTick() function. In a real clock example we have some extra rules for counting. Every time we count to 60 seconds, we add a minute. Every time we count to 60 minutes, we add an hour. So you have to implement these rules.
// lets make some simple code
public void timeTick(){
seconds = seconds + 1; // you can also use seconds++; it means exactly the same thing
if(seconds == 60){
minutes++; // we reached a minute, we need to add a minute
seconds = 0; // we restart our seconds counter
if(minutes == 60){
hours++; // we reached an hour, we need to add an hour
minutes = 0; // we restart our minutes counter
// and so on, if you want to use days (24 h a day) , months ( a bit more difficult ), ...
}
}
}
I hope this will help you, for a starter it might be a good idea to split the second part of code into a function, which deals with this situation. Good luck!
How about this:
public void timeTick () {
seconds++;
while (seconds >= 60) {
minutes++;
seconds-=60;
}
while (minutes >= 60) {
hours++;
minutes-=60;
}
}
Try this :
public void timeTick () {
seconds++;
if (seconds == 60)
{
seconds = 0;
minutes++;
if (minutes == 60)
{
minutes = 0;
hours++;
}
}
}
try this:
public class Clock{
public int seconds;
public int minutes;
public int hours;
public Clock ( int InsertSeconds, int InsertMinutes, int InsertHours){
seconds = InsertSeconds;
minutes = InsertMinutes;
hours = InsertHours;
}
public void timeTick(){
seconds = seconds + 1;
if(seconds==60){
minutes++;
seconds=0;
if(minutes==60){
hours++;
minutes=0;
}
}
}
public String toString(){
return hours + ":" + minutes + ":" + seconds;
}
}
You could check for when you have 60 seconds, then reset seconds to zero, and increase minutes by 1. e.g.
if (the condition you want to check) {
//increase the number of minutes.
//reset number of seconds.
}
If you're entering seconds values of more than 60, you'll need to work out how many minutes that equals using division, and the remaining number of seconds using the modulus operator: % e.g.
seconds = 125;
minutes = seconds / 60; // 2 minutes
remaining_seconds = seconds % 60; // 5 seconds

Format Stopwatch to display 00:00

I am experimenting with using a stopwatch in one of my apps and I have got it to where it will start counting seconds on start and stop counting on stop. My problem is that it will keep going on after 60 seconds. For example I get 120 seconds if I waited for two minutes.
So my question is how can I make it so once the seconds reached 60 the minutes would be increased by one and the seconds would start over?
So instead of :120 I would get 2:00. Here is the code I have:
final int MSG_START_TIMER = 0;
final int MSG_STOP_TIMER = 1;
final int MSG_UPDATE_TIMER = 2;
Stopwatch timer = new Stopwatch();
final int REFRESH_RATE = 100;
Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_START_TIMER:
timer.start();
mHandler.sendEmptyMessage(MSG_UPDATE_TIMER);
break;
case MSG_UPDATE_TIMER:
tvTextView.setText(":"+ timer.getElapsedTimeSecs());
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE);
break;
case MSG_STOP_TIMER:
mHandler.removeMessages(MSG_UPDATE_TIMER);
timer.stop();
tvTextView.setText("");
break;
default:
break;
}
}
};
Also are:
public void start(View v) {
mHandler.sendEmptyMessage(MSG_START_TIMER);
}
public void stop(View v) {
mHandler.sendEmptyMessage(MSG_STOP_TIMER);
}
By the way I looked at this question but his issue was with TimeSpan and if I understand correctly that is different from Stopwatch(correct me if I am wrong). Thanks for your time and effort.
If you start with the time in seconds:
display = String.format("%d:%02d", seconds / 60, seconds % 60);
If you don't want the minutes if they are 0:
if (seconds < 60)
display = String.format("%02d", seconds);
else
display = String.format("%d:%02d", seconds / 60, seconds % 60);
You are just going to have to make a function that creates a string for you. Stash this somewhere reachable.
public String NumToStr(long i){
if (i < 10 ) {
return ("0" + Long.toString(i));
}
return Long.toString(i);
}
this will take any number that is less than 10 and give you a string with a "0" infront of the number.
i.e. send it a 7 and get "07" then send it a 55 and get "55" because it was not less than 10. Finaly send it the seconds 5 and get "05". Now add the strings together,
Hour + ":" + Minute + ":" + Seconds;
and you will get "07:55:05"
next just put in a
if (seconds > 60) {
seconds = 0
minutes++;
}
if (minutes > 60) {
minutes = 0
hours++;
}
if (hours > 12) {
hours = 0
}
With all respect this is basic stuff.
In response to where should you put all of this? Where ever you like. But you need to redo some of your code.
case MSG_UPDATE_TIMER:
long TimePassed;
TimePassed = Seconds;
if (Minutes > 0) {
TimePassed = TimePassed + (60 * Minutes);
}
if (Hours > 0) {
TimePassed = TimePassed + (60 * 60 * Hours);
}
Seconds = (timer.getElapsedTimeSecs()- TimePassed );
if (Seconds > 60) {
Seconds = 0
Minutes++;
}
if (Minutes > 60) {
Minutes = 0
hours++;
}
String timeSecs = NumToStr(Seconds);
String timeMins = NumToStr(Minutes);
String timeHours = NumToStr(Hours);
String Time = timeHours + ":" + timeMins + ":" + timeSecs;
tvTextView.setText(Time);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE);
break;

Categories