CMU Coding Bootcamp
1from cmu_graphics.cmu_graphics import AppWrapper, app, runApp
2from cmu_graphics import *
3from types import SimpleNamespace
4from random import randint, choice
5from time import sleep
6from sys import exit
7
8
9def onAppStart(app_inst: AppWrapper):
10 app_inst.difficulty = 1
11 pairs = 5 * app_inst.difficulty
12 app_inst.dots = []
13 for i in range(10 * app_inst.difficulty):
14 app_inst.dots.append(makeDot(app_inst, i % pairs))
15 app_inst.counter = 0
16 app_inst.showing = []
17 app_inst.end_game = False
18 app_inst.hint = False
19 app_inst.hints = 0
20 app_inst.warning = 0
21
22
23def checkOverlap(dot1, dots):
24 for dot2 in dots:
25 if (dot1.cx - dot2.cx) ** 2 + (dot1.cy - dot2.cy) ** 2 <= (
26 dot1.r + dot2.r
27 ) ** 2:
28 return True
29 return False
30
31
32def makeDot(app_inst: AppWrapper, num: int):
33 dot = SimpleNamespace()
34 dot.num = num
35 dot.r = randint(10, 30)
36 dot.cx = 0
37 dot.cy = 0
38 while dot.cx == 0 or dot.cy == 0 or checkOverlap(dot, app_inst.dots):
39 dot.cx = randint(20, app_inst.width - 20)
40 dot.cy = randint(20, app_inst.height - 20)
41
42 dot.color = choice(["aqua", "lime", "yellow"])
43 return dot
44
45
46def drawDot(dot: SimpleNamespace):
47 drawCircle(dot.cx, dot.cy, dot.r, fill=dot.color)
48
49
50def collision(pointer, dot2):
51 if (pointer.cx - dot2.cx) ** 2 + (pointer.cy - dot2.cy) ** 2 <= dot2.r**2:
52 return True
53 return False
54
55
56def onMousePress(app_inst: AppWrapper, mouseX, mouseY):
57 pointer = SimpleNamespace()
58 pointer.cx = mouseX
59 pointer.cy = mouseY
60 for dot in app_inst.dots:
61 if collision(pointer, dot):
62 app_inst.showing.append(dot)
63
64
65def onStep(app_inst: AppWrapper):
66 if app_inst.warning != 0:
67 sleep(2)
68 app_inst.warning = 0
69 if app_inst.hint:
70 sleep(2)
71 app_inst.hint = False
72 if len(app_inst.showing) == 2:
73 if app_inst.showing[0].num == app_inst.showing[1].num:
74 app_inst.dots.remove(app_inst.showing[0])
75 app_inst.dots.remove(app_inst.showing[1])
76 sleep(0.5)
77 app_inst.counter += 1
78 app_inst.showing = []
79 if len(app_inst.dots) == 0:
80 app_inst.end_game = True
81
82
83def onKeyPress(app_inst: AppWrapper, key):
84 if key == "r":
85 app_inst.dots = []
86 for i in range(10):
87 app_inst.dots.append(makeDot(app_inst, i))
88 app_inst.showing = []
89 app_inst.counter = 0
90 app_inst.end_game = False
91 elif key == "q":
92 exit()
93 elif key == "h":
94 app_inst.hint = True
95 app_inst.hints += 1
96 elif key.isdigit():
97 if int(key) < 1 or int(key) > 4:
98 app_inst.warning = int(key)
99 app_inst.difficulty = max(1, min(int(key), 4))
100 pairs = 5 * app_inst.difficulty
101 app_inst.dots = []
102 for i in range(10 * app_inst.difficulty):
103 app_inst.dots.append(makeDot(app_inst, i % pairs))
104 app_inst.counter = 0
105 app_inst.showing = []
106 app_inst.end_game = False
107
108
109def redrawAll(app_inst: AppWrapper):
110 if app_inst.warning:
111 drawLabel(
112 f"Invalid difficulty: {app_inst.warning}",
113 app_inst.width // 2,
114 app_inst.height // 2 - 50,
115 size=20,
116 )
117 drawLabel(
118 "difficulty must be between 1 and 4",
119 app_inst.width // 2,
120 app_inst.height // 2 - 25,
121 size=20,
122 )
123 drawLabel(
124 f"picking difficulty {app_inst.difficulty}",
125 app_inst.width // 2,
126 app_inst.height // 2,
127 size=20,
128 )
129 return
130 for dot in app_inst.dots:
131 drawDot(dot)
132 if dot in app_inst.showing:
133 drawLabel(str(dot.num), dot.cx, dot.cy, size=24)
134 elif app_inst.hint:
135 drawLabel(str(dot.num), dot.cx, dot.cy, size=24)
136 if app_inst.end_game:
137 drawLabel("You win!", app_inst.width // 2, app_inst.height // 2 - 50, size=36)
138 drawLabel(
139 f"Final score: {app_inst.counter}",
140 app_inst.width // 2,
141 app_inst.height // 2,
142 size=24,
143 )
144 drawLabel(
145 f"Hints used: {app_inst.hints}",
146 app_inst.width // 2,
147 app_inst.height // 2 + 25,
148 size=24,
149 )
150 drawLabel(
151 "Press 'r' to restart",
152 app_inst.width // 2,
153 app_inst.height // 2 + 75,
154 size=24,
155 )
156 drawLabel(
157 "Press 'q' to quit",
158 app_inst.width // 2,
159 app_inst.height // 2 + 100,
160 size=24,
161 )
162 else:
163 drawLabel(f"{app_inst.counter}", 20, 20, size=24, fill="blue")
164 drawLabel(f"{app_inst.hints}", app_inst.width - 20, 20, size=24, fill="red")
165
166
167runApp()