def take_a_walk(win, distance): steps_away = 0 colour = "black" start = Point(distance, distance) current_x = start.getX() current_y = start.getY() while steps_away < distance: random_step = random() if random_step < 0.25: current_y += 1 # step = "north" elif random_step >= 0.25 and random_step < 0.5: current_x += 1 # step = "east" elif random_step >= 0.5 and random_step < 0.75: current_y -= 1 # step = "south" else: current_x -= 1 # step = "west" current_pos = Point(current_x, current_y) steps_away = distance_between_points(start, current_pos) if steps_away >= distance: colour = "red" draw_walk(win, start, current_pos, colour)
def shoot_arrows(win, wind_text, zone_text, score_text, score): """Prompt user to shoot arrows at the target by left-clicking.""" h_wind, v_wind = random.uniform(-WSD, WSD), random.uniform(-WSD, WSD) for _ in range(ARROWS): # determine wind direction wind = "" if v_wind > WTH: wind += "north" elif v_wind < -WTH: wind += "south" if h_wind > WTH: wind += "east" elif h_wind < -WTH: wind += "west" if wind == "": wind = "Calm" # display wind direction wind_text.setText(f"Wind: {wind.title()}") # wait for left-click cursor_pos = win.getMouse() arrow_x = cursor_pos.getX() + h_wind # add horizontal wind to x value arrow_y = cursor_pos.getY() + v_wind # add vertical wind to y value # add wind deviation for next arrow shot h_wind += random.uniform(-WD, WD) v_wind += random.uniform(-WD, WD) # get the distance from the target centre of where the arrow will land arrow_zone = distance_between_points(Point(arrow_x, arrow_y), Point(0.5, 0.5)) # determine what zone the arrow will land in if arrow_zone <= 0.3: draw_arrow(win, arrow_x, arrow_y) if arrow_zone < 0.1: zone_text.setText("YELLOW ZONE (10 POINTS!)") score += 10 elif arrow_zone >= 0.1 and arrow_zone < 0.2: zone_text.setText("RED ZONE (5 POINTS!)") score += 5 else: zone_text.setText("BLUE ZONE (2 POINTS!)") score += 2 else: zone_text.setText("TARGET MISSED (0 POINTS!)") score_text.setText(f"Score: {score}") return score
def archery_game(): """Program entry point.""" win, wind_text, zone_text, score_text, score = draw_gui() score = shoot_arrows(win, wind_text, zone_text, score_text, score) give_grade(wind_text, score_text, score) # wait for user to click on the screen cursor = win.getMouse() cursor_x, cursor_y = cursor.getX(), cursor.getY() win.close() # if the user clicked on the target, reload the window if distance_between_points(Point(cursor_x, cursor_y), Point(0.5, 0.5)) <= 0.3: archery_game()
def clickable_box_of_eyes(cols=None, rows=None): """ 9. [harder] Write a function clickable_box_of_eyes() that takes two parameters columns and rows, and displays a rows x columns grid of blue eyes (all of radius 50) within a box (rectangle). There should be a border of size 50 between the box and the edge of the window. For each click of the mouse inside the box, the function should behave as follows: if the click is on an eye, the row and column of that eye should be displayed in the space below the box, for example as shown below given the click denoted by the dot. Note: row and column numbers should begin at 1. If the user clicks within the box but not on an eye, the displayed message should be 'Between eyes'. The window should close when the user clicks outside the box. """ if cols is None or rows is None: cols = int(input("Enter the number of cols > ")) rows = int(input("Enter the number of rows > ")) b_and_cols = cols + 1 # columns plus border b_and_rows = rows + 1 # rows plus border win = GraphWin("Clickable box of eyes", 100 * b_and_cols, 100 * b_and_rows) win.setCoords(0, b_and_rows, b_and_cols, 0) for i in range(1, b_and_rows): for j in range(1, b_and_cols): draw_blue_eye(win, Point(j, i), 0.5) container = Rectangle(Point(0.5, 0.5), Point(b_and_cols - 0.5, b_and_rows - 0.5)) container.draw(win) message = Text(Point(b_and_cols / 2, b_and_rows - 0.25), "") message.setSize(20) message.draw(win) while True: cursor = win.getMouse() col = int(cursor.getX() + 0.5) row = int(cursor.getY() + 0.5) if col == 0 or row == 0 or col == b_and_cols or row == b_and_rows: win.close() break if distance_between_points(cursor, Point(col, row)) > 0.5: message.setText("Between eye") else: message.setText(f"Eye at row {row}, column {col}")
def take_a_walk(num_steps): horizontal_steps = 0 vertical_steps = 0 for _ in range(num_steps): random_step = random() if random_step < 0.25: vertical_steps += 1 elif 0.25 <= random_step < 0.5: horizontal_steps += 1 elif 0.5 <= random_step < 0.75: vertical_steps -= 1 else: horizontal_steps -= 1 steps = distance_between_points(Point(0, 0), Point(horizontal_steps, vertical_steps)) return abs(steps)
def archery_game(): """ 12. [harder] Write an archery_game() function. This function should draw a target (like that from pract03) using the supplied draw_circle() function. Your function should then allow the user to click on the graphics window five times, representing the firing of five arrows – each click representing the point on the target that is aimed at. Fluctuating atmospheric conditions should be considered – your solution should generate two random values representing the amount an arrow will move horizontally and vertically from the aimed position during its flight, and these values should be adjusted a little (again randomly) after each arrow. Generating random numbers is easily accomplished using the randint function from the random module. This function takes two arguments and returns a random number between these two values. For example, try: import random for i in range(10): print(random.randint(1, 5)) Each time the user clicks, the function should: (i) display a small black circle representing where the arrow hits. (ii) record the number of points scored. The points awarded for each arrow (click) are as follows: 10 for the yellow area, 5 for red and 2 for blue. After the final arrow, the function should display the total score on the graphics window. Hint: calculate distances() by first importing your pract05.py file and using the distance_between_points() function. """ win, wind_text, zone_text, score_text, score = draw_gui() score = shoot_arrows(win, wind_text, zone_text, score_text, score) give_grade(wind_text, score_text, score) # wait for user to click on the screen cursor = win.getMouse() cursor_x, cursor_y = cursor.getX(), cursor.getY() win.close() # if the user clicked on the target, reload the window if distance_between_points(Point(cursor_x, cursor_y), Point(0.5, 0.5)) <= 0.3: archery_game()
def clickable_eye(): """ 5. Write a clickable_eye() function which draws a brown eye of radius 100 within a graphics window of sufficient size. The function should then respond to each user click on the eye by displaying (underneath the eye) the name of the part of the eye clicked on (i.e. one of 'pupil', 'iris', 'sclera'). The user should be able to finish (i.e. close the window) by clicking on any point outside the eye. Hint: use your draw_brown_eye() and distance_between_points() functions from 'pract05.py'. """ win = GraphWin("Clickable eye", 800, 800) win.setCoords(0, 0, 1, 1) centre = Point(0.5, 0.5) radius = 0.35 draw_brown_eye(win, centre, radius) zone_text = Text(Point(0.5, 0.07), "") zone_text.setSize(18) zone_text.setStyle("bold") zone_text.draw(win) while True: choice = win.getMouse() choice_x = choice.getX() choice_y = choice.getY() choice_zone = distance_between_points(Point(choice_x, choice_y), Point(0.5, 0.5)) if choice_zone > radius: win.close() break if choice_zone >= radius / 2 and choice_zone <= radius: zone_text.setText("Sclera") elif choice_zone >= radius / 4 and choice_zone <= radius / 2: zone_text.setText("Iris") else: zone_text.setText("Pupil")
def find_the_circle(): """ 10. [harder] Write a find_the_circle() function to play a simple game. This should start by displaying a graphics window, and creating (but not displaying) a circle of radius 30 at a random position (use the randint function from the random module). The user should then have 10 attempts at locating the circle (by clicking on the graphics window). Each time (except the first) the user misses the circle, a "getting closer" or "getting further away" message should be displayed (depending on the position of the current and previous clicks). If the user manages to find the circle (by clicking within its circumference), then the circle should be displayed and the user given some points: 10 points for finding it with the first click, down to 1 point for finding it with the 10th click. The game then restarts. However, each time the game restarts the circle should be given a new random position and its radius reduced by 10%. The game ends when the user fails to find the circle within 10 clicks. The total number of points scored should then be displayed. Note: game is too hard with radius 30 circle so I've upped it to 60. """ win = GraphWin("Find the circle", 300, 440) score, radius, loss = 0, 60, False divider = Rectangle(Point(-1, 300), Point(300, 360)) divider.setFill("gray") divider.draw(win) warning_text = Text(Point(150, 330), "Click in the space\nabove this grey " "rectangle") warning_text.setSize(12) warning_text.setStyle("bold") warning_text.draw(win) status_text = Text(Point(150, 385), "") status_text.setSize(12) status_text.setStyle("bold") status_text.draw(win) score_text = Text(Point(150, 415), "Score: 0") score_text.setSize(12) score_text.setStyle("bold") score_text.draw(win) points_text = Text(Point(150, 25), "") points_text.setSize(14) points_text.setStyle("bold") points_text.draw(win) while True: centre_x, centre_y = random.randint(0, 300), random.randint(0, 300) centre = Point(centre_x, centre_y) hidden_circle = Circle(centre, radius) hidden_circle.setFill("red") status_text.setText("Find the circle!") distances = [] for i in range(1, 11): while True: cursor = win.getMouse() cursor_y = cursor.getY() if cursor_y <= 300: break distance = distance_between_points(centre, cursor) distances.append(distance) if distance <= radius: hidden_circle.draw(win) divider.undraw() divider.draw(win) points_text.undraw() points_text.draw(win) if i == 1: points_text.setText("You get 10 points!") status_text.setText("Click 1: you got it first try") else: status_text.setText(f"Click {i}: you got it") if i == 10: points_text.setText("You get 1 point!") else: points_text.setText(f"You get {11-i} points!") radius *= 0.9 score += 11 - i time.sleep(4) hidden_circle.undraw() status_text.setText("") points_text.setText("") score_text.setText(("Score:", score)) break if i == 1: status_text.setText("Click 1: missed") elif distances[i - 1] > distances[i - 2]: status_text.setText(f"Click {i}: further away") elif distances[i - 1] == distances[i - 2]: status_text.setText(f"Click {i}: same distance") else: status_text.setText(f"Click {i}: closer") if i == 10: loss = True break if loss: score_text.setText("Game over") hidden_circle.draw(win) divider.undraw() divider.draw(win) points_text.undraw() points_text.draw(win) break points_text.setText(f"Your score is {score}") time.sleep(4) win.close()