CMU Coding Bootcamp

feat: oct 6 add cmu_graphics, and mem game

thecoded.prof 8337c5f1 89ac97c0

verified
Changed files
+236 -2
python
oct6
memorygame
+69 -2
nilla.nix
··· 14 14 inputs = { 15 15 nixpkgs = { 16 16 src = pins.nixpkgs; 17 - }; 17 + }; 18 + }; 19 + packages.cmu-graphics = { 20 + systems = [ "x86_64-linux" ]; 21 + package = 22 + { 23 + pkgs, 24 + python313, 25 + fetchPypi 26 + }: 27 + let 28 + pname = "cmu_graphics"; 29 + version = "1.1.43"; 30 + in 31 + python313.pkgs.buildPythonPackage { 32 + inherit pname version; 33 + 34 + src = fetchPypi { 35 + inherit pname version; 36 + hash = "sha256-IU6z+4xB7Uz/SsIrFkFRfLL10ZmpQTPyK+yDWDq89Xs="; 37 + }; 38 + 39 + doCheck = false; 40 + checkPhase = '' 41 + true 42 + ''; 43 + dontCheckPythonPackages = true; 44 + pyproject = true; 45 + 46 + dependencies = [ 47 + python313.pkgs.pycairo 48 + python313.pkgs.pygame 49 + ]; 50 + 51 + build-system = [ 52 + python313.pkgs.setuptools 53 + python313.pkgs.wheel 54 + pkgs.pre-commit 55 + ]; 56 + 57 + }; 18 58 }; 19 59 shells.default = config.shells.python; 20 60 shells.python = { 21 61 # Declare what systems the shell can be used on. 22 62 systems = [ "x86_64-linux" ]; 23 - 63 + 24 64 # Define our shell environment. 25 65 shell = 26 66 { ··· 34 74 pkgs.black 35 75 ]; 36 76 }; 77 + }; 78 + shells.cmu-graphics = { 79 + systems = [ "x86_64-linux" ]; 80 + shell = 81 + { 82 + pkgs, 83 + mkShell, 84 + ... 85 + }: 86 + let 87 + python3 = pkgs.python313.override { 88 + packageOverrides = pyfinal: pyprev: { 89 + cmu_graphics = config.packages.cmu-graphics.result.x86_64-linux; 90 + }; 91 + }; 92 + in 93 + mkShell { 94 + packages = [ 95 + (python3.withPackages (ppkgs: [ 96 + ppkgs.cmu_graphics 97 + ppkgs.pycairo 98 + ppkgs.pygame 99 + ppkgs.pillow 100 + ppkgs.numpy 101 + ])) 102 + ]; 103 + }; 37 104 }; 38 105 }; 39 106 }
+167
python/oct6/memorygame/main.py
··· 1 + from cmu_graphics.cmu_graphics import AppWrapper, app, runApp 2 + from cmu_graphics import * 3 + from types import SimpleNamespace 4 + from random import randint, choice 5 + from time import sleep 6 + from sys import exit 7 + 8 + 9 + def 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 + 23 + def 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 + 32 + def 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 + 46 + def drawDot(dot: SimpleNamespace): 47 + drawCircle(dot.cx, dot.cy, dot.r, fill=dot.color) 48 + 49 + 50 + def 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 + 56 + def 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 + 65 + def 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 + 83 + def 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 + 109 + def 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 + 167 + runApp()