CMU Coding Bootcamp
at main 7.2 kB view raw
1from cmu_graphics.cmu_graphics import app, AppWrapper 2from cmu_graphics import * 3from random import randint 4from time import sleep 5from sys import exit 6 7 8def onAppStart(app_inst: AppWrapper): 9 app_inst.rows = 8 10 app_inst.cols = 10 11 app_inst.boardLeft = 25 12 app_inst.boardTop = 85 13 app_inst.boardWidth = 350 14 app_inst.boardHeight = 280 15 app_inst.cellBorderWidth = 1 16 app_inst.snake = [(randint(0, app_inst.rows - 1), randint(0, app_inst.cols - 1))] 17 app_inst.direction = [0, 0] 18 app_inst.fruit = None 19 app_inst.gameOver = False 20 app_inst.portals = [(-1, -1), (-1, -1)] 21 makePortals(app_inst) 22 app_inst.poison = None 23 24 25def makePortals(app_inst: AppWrapper): 26 while ( 27 manhattenDist(app_inst.portals[0], app_inst.portals[1]) < 5 28 or distanceToWall(app_inst, app_inst.portals[0]) < 2 29 or distanceToWall(app_inst, app_inst.portals[1]) < 2 30 ): 31 app_inst.portals = [ 32 (randint(0, app_inst.rows - 1), randint(0, app_inst.cols - 1)), 33 (randint(0, app_inst.rows - 1), randint(0, app_inst.cols - 1)), 34 ] 35 36 37def distanceToWall(app_inst: AppWrapper, pos): 38 return min(pos[0], app_inst.rows - pos[0] - 1, pos[1], app_inst.cols - pos[1] - 1) 39 40 41def manhattenDist(p1, p2): 42 return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]) 43 44 45def onKeyPress(app_inst: AppWrapper, key): 46 if key == "up" and not app_inst.direction[0]: 47 app_inst.direction = [-1, 0] 48 elif key == "down" and not app_inst.direction[0]: 49 app_inst.direction = [1, 0] 50 elif key == "left" and not app_inst.direction[1]: 51 app_inst.direction = [0, -1] 52 elif key == "right" and not app_inst.direction[1]: 53 app_inst.direction = [0, 1] 54 elif key == "r": 55 onAppStart(app_inst) 56 elif key == "q": 57 exit() 58 elif key == "space": 59 app_inst.gameOver = True 60 61 62def moveSnake(app_inst: AppWrapper): 63 if app_inst.gameOver: 64 return 65 head = app_inst.snake[0] 66 newHead = ( 67 (head[0] + app_inst.direction[0]) % app_inst.rows, 68 (head[1] + app_inst.direction[1]) % app_inst.cols, 69 ) 70 app_inst.snake.insert(0, newHead) 71 if newHead in app_inst.portals: 72 app_inst.snake[0] = app_inst.portals[1 - app_inst.portals.index(newHead)] 73 elif newHead == app_inst.poison: 74 app_inst.gameOver = True 75 if len(app_inst.snake) > 1: 76 app_inst.snake.pop() 77 for segment in app_inst.snake[1:]: 78 if app_inst.snake[0] == segment: 79 app_inst.gameOver = True 80 81 82def onStep(app_inst: AppWrapper): 83 if not app_inst.fruit: 84 makeFruit(app_inst) 85 makePoison(app_inst) 86 head = app_inst.snake[0] 87 if head == app_inst.fruit: 88 app_inst.fruit = None 89 app_inst.snake.append(app_inst.snake[-1]) 90 moveSnake(app_inst) 91 92 93def getCell(app_inst: AppWrapper, pos): 94 if pos in app_inst.snake: 95 return "snake" 96 elif pos == app_inst.fruit: 97 return "fruit" 98 elif pos in app_inst.portals: 99 return "portal" 100 elif pos == app_inst.poison: 101 return "poison" 102 elif pos == None: 103 return "empty" 104 return None 105 106 107def makeFruit(app_inst: AppWrapper): 108 fruit = None 109 while getCell(app_inst, fruit) is not None: 110 fruit = (randint(0, app_inst.rows - 1), randint(0, app_inst.cols - 1)) 111 app_inst.fruit = fruit 112 break 113 114 115def makePoison(app_inst: AppWrapper): 116 poison = None 117 while getCell(app_inst, poison) is not None: 118 poison = (randint(0, app_inst.rows - 1), randint(0, app_inst.cols - 1)) 119 app_inst.poison = poison 120 break 121 122 123def redrawAll(app_inst: AppWrapper): 124 drawLabel("Snake!", 200, 30, size=16) 125 drawBoard(app_inst) 126 drawBoardBorder(app_inst) 127 drawFruit(app_inst) 128 drawPoison(app_inst) 129 drawPortals(app_inst) 130 drawSnake(app_inst) 131 sleep(0.1875) 132 if app_inst.gameOver: 133 drawGameOver(app_inst) 134 135 136def drawPoison(app_inst: AppWrapper): 137 if app_inst.poison is not None: 138 cellLeft, cellTop = getCellLeftTop(app_inst, *app_inst.poison) 139 cellWidth, cellHeight = getCellSize(app_inst) 140 drawCircle( 141 cellLeft + cellWidth / 2, 142 cellTop + cellHeight / 2, 143 cellWidth / 2 - 6, 144 fill="purple", 145 ) 146 147 148def drawPortals(app_inst: AppWrapper): 149 for portal in app_inst.portals: 150 cellLeft, cellTop = getCellLeftTop(app_inst, portal[0], portal[1]) 151 cellWidth, cellHeight = getCellSize(app_inst) 152 drawCircle( 153 cellLeft + cellWidth / 2, 154 cellTop + cellHeight / 2, 155 cellWidth / 2 - 6, 156 fill="black", 157 ) 158 159 160def drawGameOver(app_inst: AppWrapper): 161 drawRect(app_inst.width / 2 - 150, app_inst.height / 2 - 50, 300, 100, fill="white") 162 drawLabel("Game Over!", app_inst.width / 2, app_inst.height / 2 - 20, size=16) 163 drawLabel( 164 f"Score: {len(app_inst.snake)-1}", 165 app_inst.width / 2, 166 app_inst.height / 2, 167 size=12, 168 ) 169 drawLabel( 170 "Press R to restart", app_inst.width / 2, app_inst.height / 2 + 20, size=12 171 ) 172 drawLabel("Press Q to quit", app_inst.width / 2, app_inst.height / 2 + 40, size=12) 173 174 175def drawFruit(app_inst: AppWrapper): 176 if app_inst.fruit is not None: 177 cellLeft, cellTop = getCellLeftTop(app_inst, *app_inst.fruit) 178 cellWidth, cellHeight = getCellSize(app_inst) 179 drawCircle( 180 cellLeft + cellWidth / 2, 181 cellTop + cellHeight / 2, 182 cellWidth / 2 - 8, 183 fill="red", 184 ) 185 186 187def drawSnake(app_inst: AppWrapper): 188 cellWidth, cellHeight = getCellSize(app_inst) 189 for i, segment in enumerate(app_inst.snake): 190 cellLeft, cellTop = getCellLeftTop(app_inst, segment[0], segment[1]) 191 color = "green" if i == 0 else "gray" 192 drawCircle( 193 cellLeft + cellWidth / 2, 194 cellTop + cellHeight / 2, 195 cellWidth / 2 - 4, 196 fill=color, 197 ) 198 199 200def drawBoard(app_inst: AppWrapper): 201 for row in range(app_inst.rows): 202 for col in range(app_inst.cols): 203 drawCell(app_inst, row, col) 204 205 206def drawBoardBorder(app_inst: AppWrapper): 207 drawRect( 208 app_inst.boardLeft, 209 app_inst.boardTop, 210 app_inst.boardWidth, 211 app_inst.boardHeight, 212 fill=None, 213 border="black", 214 borderWidth=2 * app_inst.cellBorderWidth, 215 ) 216 217 218def drawCell(app_inst: AppWrapper, row, col): 219 cellLeft, cellTop = getCellLeftTop(app_inst, row, col) 220 cellWidth, cellHeight = getCellSize(app_inst) 221 drawRect( 222 cellLeft, 223 cellTop, 224 cellWidth, 225 cellHeight, 226 fill=None, 227 border="gray", 228 borderWidth=app_inst.cellBorderWidth, 229 ) 230 231 232def getCellLeftTop(app_inst: AppWrapper, row, col): 233 cellWidth, cellHeight = getCellSize(app_inst) 234 cellLeft = app_inst.boardLeft + col * cellWidth 235 cellTop = app_inst.boardTop + row * cellHeight 236 return (cellLeft, cellTop) 237 238 239def getCellSize(app_inst: AppWrapper): 240 cellWidth = app_inst.boardWidth / app_inst.cols 241 cellHeight = app_inst.boardHeight / app_inst.rows 242 return (cellWidth, cellHeight) 243 244 245def main(): 246 runApp() 247 248 249main()