import random from turtle import * # ---------------- Globals ---------------- racers = [] write = None obstacles = [] pushback_obstacles = [] winning_t = None instruction_turtles = [] start_button = None start_clicked = False screen = Screen() screen.tracer(0) play_again_button = None play_again_bounds = None coins = 0 coin_writer = None # ---------------- Instructions & Start Button ---------------- # Shows the instruction screen and draws the start button def showInstructionsPage(): global start_button, instruction_turtles, start_clicked start_clicked = False screen.clear() instruction_turtles.clear() instructions = Turtle() instructions.hideturtle() instructions.penup() instructions.goto(0, 100) instructions.write( "WELCOME TO THE TURTLE RACE!\n\n" "• Predict which turtle will win.\n" "• Small BLACK squares = slow you down.\n" "• RED squares = push you backwards.\n" "• Click the LIGHTBLUE box to begin!", align="center", font=("Arial", 18, "bold") ) instruction_turtles.append(instructions) start_button = Turtle() start_button.penup() start_button.goto(0, -40) start_button.shape("square") start_button.shapesize(stretch_wid=2, stretch_len=6) start_button.color("lightblue") start_button.showturtle() btn_text = Turtle() btn_text.hideturtle() btn_text.penup() btn_text.goto(0, -48) btn_text.write("START", align="center", font=("Arial", 20, "bold")) instruction_turtles.append(btn_text) screen.update() # Detects clicks on the start button and sets the start flag def onStartClick(x, y): global start_clicked if -60 < x < 60 and -70 < y < -10: start_clicked = True # Waits until the player clicks the start button def waitForStartButton(): screen.onclick(onStartClick) while not start_clicked: screen.update() screen.onclick(None) # Clears the instruction page and loads the game def loadGamePage(): screen.clear() screen.tracer(1) setup() # ---------------- Setup & Track ---------------- # Sets up the race by drawing the track, obstacles, and turtles def setup(): global racers, write drawTrack() drawObstacles() showCoins() names = ["Fred", "Jeff", "Alice", "Joe", "Max"] racers = [] write = Turtle() write.hideturtle() write.penup() write.goto(-20, -250) write.color("red") for i in range(5): t = Turtle() t.nickname = names[i] t.shape("turtle") t.penup() t.goto(-300, i*80 - 120) racers.append(t) # ---------------- Track drawing ---------------- # Draws the race track, grass, crowd, and finish/start lines (it hides the turtle) def drawTrack(): t = Turtle() t.hideturtle() t.speed(0) #top grass t.penup() t.goto(-400, 240) t.color("forest green") t.begin_fill() t.pendown() for _ in range(2): t.forward(800) t.left(90) t.forward(150) t.left(90) t.end_fill() #bottom grass t.penup() t.goto(-400, -310) t.color("forest green") t.begin_fill() t.pendown() for _ in range(2): t.forward(800) t.left(90) t.forward(150) t.left(90) t.end_fill() # the crowd t.penup() t.goto(-380, 260) t.color("gray20") t.begin_fill() t.pendown() for _ in range(2): t.forward(760) t.left(90) t.forward(60) t.left(90) t.end_fill() #The rainbow people colors = ["yellow", "white", "red", "blue", "orange", "purple"] for x in range(-360, 361, 20): t.penup() t.goto(x, 285) t.dot(10, random.choice(colors)) #track border t.penup() t.goto(-350, -160) t.color("black") t.pensize(3) t.pendown() for _ in range(2): t.forward(700) t.left(90) t.forward(400) t.left(90) # START LINE (x = -300) t.penup() t.goto(-300, -160) t.setheading(90) t.color("green") t.pensize(4) t.pendown() t.forward(400) #finish line t.penup() t.goto(300, -160) t.setheading(90) t.color("red") t.pendown() t.forward(400) #lines (at y = 0, 50, 100, 150, 200) t.color("black") t.pensize(2) for y in range(-160, 241, 80): t.penup() t.goto(-350, y) t.setheading(0) for _ in range(35): # dashed t.pendown() t.forward(10) t.penup() t.forward(10) #labels t.penup() t.color("green") t.goto(-335, 260) t.write("START", font=("Arial", 16, "bold")) t.color("red") t.goto(270, 260) t.write("FINISH", font=("Arial", 16, "bold")) # ---------------- Obstacles ---------------- # Randomly places slow-down and pushback obstacles on each lane def drawObstacles(): global obstacles, pushback_obstacles obstacles = [] pushback_obstacles = [] lane_y_positions = [-120, -40, 40, 120, 200] for y in lane_y_positions: count = random.randint(2, 3) for _ in range(count): x = random.randint(-150, 200) o = Turtle() o.hideturtle() o.penup() o.shape("square") o.shapesize(stretch_wid=0.6, stretch_len=0.6) o.color("black") o.goto(x, y) o.showturtle() obstacles.append(o) for y in lane_y_positions: x = random.randint(-120, 220) p = Turtle() p.hideturtle() p.penup() p.shape("square") p.shapesize(stretch_wid=0.9, stretch_len=0.9) p.color("red") p.goto(x, y) p.showturtle() pushback_obstacles.append(p) # ---------------- Win check ---------------- # Checks whether any turtle has reached the finish line def checkWin(): global winning_t for i in range(len(racers)): if racers[i].xcor() >= 300: winning_t = i return True return False # ---------------- Race loop ---------------- # Runs the race loop and moves turtles forward with obstacle effects def race(): win = checkWin() while not win: for t in racers: step = random.randint(10, 30) for o in obstacles: if t.distance(o) < 18: step = random.randint(1, 6) break for p in pushback_obstacles[:]: if t.distance(p) < 18: back = random.randint(20, 40) t.backward(back) try: p.hideturtle() pushback_obstacles.remove(p) except ValueError: pass t.forward(step) win = checkWin() # ---------------- Display & Prediction ---------------- # Displays the race result and tells the player if they won, it also adds to the coin function. If you guess correct, you gain 50 coins, if you dont you lose -10. # These coin numbers will be carried on even if you click play again def displayResult(predict): global coins bold_font = ("Times New Roman", 20, "bold") if checkWin(): winner_name = racers[winning_t].nickname racers[winning_t].write(winner_name, align="right", font=bold_font) write.write(f"{winner_name} won!", font=bold_font) # --- COIN LOGIC --- if predict and predict.lower() == winner_name.lower(): coins += 50 write.goto(-20, -280) write.write("+50 coins!", font=("Arial", 16, "bold")) else: coins -= 10 write.goto(-20, -280) write.write("-10 coins!", font=("Arial", 16, "bold")) showCoins() showPlayAgain() screen.onclick(onPlayAgainClick) # Asks the user to predict which turtle will win def getPrediction(): displayRacers() p = textinput("racers prediction", "which racer will win?") return p # Displays all racer names on the screen def displayRacers(): pen = Turtle() pen.hideturtle() for i in range(len(racers)): pen.penup() pen.goto(-280, i*80 - 160) pen.write(f"{racers[i].nickname}", font=("Times New Roman", 18)) # ---------------- Play Again ---------------- # Draws the play again button after the race finishes def showPlayAgain(): global play_again_button, play_again_bounds play_again_button = Turtle() play_again_button.hideturtle() play_again_button.penup() play_again_button.goto(-100, -200) play_again_button.color("white", "blue") play_again_button.begin_fill() for _ in range(2): play_again_button.forward(200) play_again_button.left(90) play_again_button.forward(60) play_again_button.left(90) play_again_button.end_fill() play_again_button.goto(0, -190) play_again_button.color("white") play_again_button.write("PLAY AGAIN", align="center", font=("Arial", 18, "bold")) play_again_bounds = (-100, 100, -200, -140) # Detects clicks on the play again button def onPlayAgainClick(x, y): if play_again_bounds: x1, x2, y1, y2 = play_again_bounds if x1 <= x <= x2 and y1 <= y <= y2: restartGame() # Resets the game and starts over def restartGame(): global racers, obstacles, pushback_obstacles, winning_t, start_clicked screen.clear() racers.clear() obstacles.clear() pushback_obstacles.clear() winning_t = None start_clicked = False main() #---------------- Coins -------------------- # Adds a coin meter at the bottom def showCoins(): global coin_writer if coin_writer is None: coin_writer = Turtle() coin_writer.hideturtle() coin_writer.color("yellow") coin_writer.penup() coin_writer.goto(-350, -260) coin_writer.clear() coin_writer.write(f"Coins: {coins}", font=("Arial", 16, "bold")) # ---------------- Main ---------------- def main(): showInstructionsPage() waitForStartButton() loadGamePage() prediction = getPrediction() race() displayResult(prediction) main()