Implementing a countdown in a Quiz game that resets upon answer, and starts over from scratch on new question given

Hi there

As a part of out course at university in basic coding, we’re making a Quiz-like game of the Periodic Table. The quiz is in Norwegian, but hopefully you’re able to understand the code itself and hopefully help me a little on my way to solve this problem.

I want to add a feature to this game that starts a timer each time a question is asked, where the score is determined how fast you answer the question. For example a 60 second countdown in the background. I do not want to exit the game if it reaches zero, but rather let the user answer and if they are correct they get 0 points (because time is up), and if incorrect also 0 points.
I want the timer to stop if the user answers correct within the timeframe and determine their score depending of time left, and then move on to the next one, and start from 60 again when the next question is asked etc.

For example: if user answers correct at 45 seconds left, reward 30 points – if user answers correct at 15 seconds left, reward 10 points.
I hope you understand what I am trying to do.

We have not yet implemented a score feature as we work on different parts of this program separately.

So far I’ve figured out I need to import the threading to be able to run this in the background of the main program. And below you can see my progress on the countdown part.

def countdown():
  global my_timer
  my_timer = 60
  for x in range(60):
    my_timer = my_timer -1
    sleep(1)
    print("Time is up")

countdown_thread = threading.Thread(target = countdown)
countdown_thread.start()

while my_timer > 0:

I am not sure how to implement this into the main code and hope someone is able to help me out with that! I will post the main code below:

from hint import * #Our own made module to grab hints for the questions.
from random import randrange
import replit
from colorama import Fore #Color coded replies from program
from colorama import Style #To reset color on replies from program
from time import *
import threading

liste = []
trekning = []
poeng = 0 

##################################

class Grunnstoff:
  
  def __init__(self, grunnStoff, periode, gruppe, stoffKategori, atomNummer):
    self.grunnStoff = grunnStoff
    self.periode = periode
    self.gruppe = gruppe
    self.stoffKategori = stoffKategori
    self.atomNummer = atomNummer

  def __str__(self):
    return self.grunnStoff
    return self.periode
    return self.gruppe
    return self.stoff.Kategori
    return self.atomNummer

###########################################

def fyllKlasse():
  for i in range(len(atomSymbol)):
    nytthint = Grunnstoff(atomSymbol[i], periode[i], gruppe[i], stoffKategori[i], atomNummer[i])
    liste.append(nytthint)

##########################################

def spillds():
  global poeng
  for x in range(len(trekning)):
    i = trekning[x]
    print("\nOppgave " + str(x + 1) + ") \nGrunnstoffet tilhører \nPeriode: ",liste[i].periode,"\nGruppe: ", liste[i].gruppe, "\nKategori:",liste[i].stoffKategori)
    svar = input("\nHvilket grunnstoff kan dette være? ")
    if svar == liste[i].grunnStoff:
      print(f"{Fore.GREEN}\nJammen, det er jo helt rett!{Style.RESET_ALL} \nDa går vi videre til neste oppgave.")
      print("\n------------------------------")
    else:
      print(f"{Fore.YELLOW}\nNeinei, der bommet du litt.{Style.RESET_ALL}")
      print("\n------------------------------")
      print("\nHer skal du få litt mer hjelp: \nGrunnstoffet har atomnummer:", liste[i].atomNummer)
      svar = input("\nHvilket grunnstoff tror du dette kan være? ")
      if svar == liste[i].grunnStoff:
        print(f"{Fore.GREEN}Himla bra, altså! Du er klar for en ny utfordring.{Style.RESET_ALL}")
        print("\n------------------------------")

      else:
        print(f"{Fore.RED}\nBæsj... Vi prøver neste grunnstoff{Style.RESET_ALL}")
        print("Vi var ute etter: ", liste[i].grunnStoff)
        print("\n------------------------------")

def pick():
  while len(trekning) < len(atomSymbol): #Funksjonen trekker tilfeldig fra lista av atomsymboler, og lagrer trekningen i en liste for å unngå å trekke samme to ganger
    ny = randrange(len(liste))
    if ny not in trekning:
        trekning.append(ny)

while True:

  print("Velkommen til det middels store spillet om periodesystemet!\n")
  valg = input("Tast 1 for å spille uten tid. \nTast 2 for å se en oversikt over de 20 første grunnstoffene.\nTast 3 for å spille med tid.")

  if valg == "1":
    fyllKlasse()
    pick()
    print("------------------------------")
    print("\nI dette spillet får du testet din forståelse av periodesystemet og dets oppbygning. \nBasert på opplysningene du får, skal du komme frem til riktig grunnstoff. \nSvar ved å skrive atomsymbol. \nLykke til!\n")
    print("------------------------------")
    #print(trekning)
    spillds()
  elif valg == "2":
    fyllKlasse()
    pick()
    for i in range(len(liste)):
      print(liste[i].grunnStoff, " ", liste[i].periode, " ", liste[i].gruppe, " ", liste[i].stoffKategori, " ", liste[i].atomNummer)
    print("------------------------------")
  elif valg == "3":
    print("lol")
  else:
    print ("Ikke gyldig valg. Prøv igjen!")
    print("\n------------------------------\n")

In keywords:

  • I want to make a countdown for each question, 60s
  • If answer is correct, stop timer, give score depending on time left (if time is out, 0 score) and go to next question.
  • If answered incorrectly, user gets a hint from our premade “hint” module, but countdown still goes.
  • If time is up, user can still answer but gets 0 points.

I feel like this is very complex, but I hope it is not. If someone is able to give me an explanation in text on the principles and how to do it, I may be able to pull it off myself. If you want to post code with an answer, I’d really really appreciate it. Or just a link or a video with exactly this. Everything helps!

I’m not too sure that you need to be so complex (in terms of ‘threading’, that is); could you not use a simple timing method, like this?

from time import sleep
from datetime import datetime


def timer():
    h, m, s = datetime.now().hour, datetime.now().minute, datetime.now().second
    print(f"{h:02d}:{m:02d}:{s:02d}")
    return h, m, s


print(f"Timer started:", end=' ')
start = datetime.now()
timer()

sleep(15)  # this represents the delay of the user input

print(f"Timer stopped:", end=' ')
stop = datetime.now()
timer()

timedelta = stop - start

s = timedelta.seconds

print(f"Seconds elapsed: {s}")

It’s not going to be accurate to the n’th degree, but it may be fit for your purpose.

I’ve not taken this to a full solution, as I’m sure you can do that, if you see fit.

(Edit done for a code update)