CMU 15-112: Fundamentals of Programming and Computer Science
Capture The Flag From Lecture (No Timer)


Note: This code has been lightly cleaned up since lecture, but it's still messy. It may not follow our style guide, some design decisions are debatable, and it's not well documented. Still, if you'd like to work through a medium-sized timerless game this is a good resource.

from cmu_112_graphics import * import random ########################################### # Helpers ########################################### def make2dList(rows, cols, startValue): return [[startValue]*cols for row in range(rows)] def isInBounds(app, row, col): return 0 <= row < len(app.board) and 0 <= col < len(app.board[0]) def getCell(app, x, y): cellWidth = app.width // len(app.board[0]) cellHeight = app.height // len(app.board) row = y // cellHeight col = x // cellWidth return row, col def getCellBounds(app, row, col): cellWidth = app.width // len(app.board[0]) cellHeight = app.height // len(app.board) left = cellWidth * col top = cellHeight * row right = left + cellWidth bottom = top + cellHeight return left, top, right, bottom ########################################### # Model ########################################### def randomlyPlaceObjectOnBoard(app, object): while True: row = random.randrange(len(app.board)) col = random.randrange(len(app.board[0])) if app.board[row][col] == '': app.board[row][col] = object break def findObjectInBoard(app, object): for row in range(len(app.board)): for col in range(len(app.board[0])): if app.board[row][col] == object: return (row, col) return (-1, -1) def initRound(app): app.gameOver = False app.winner = None app.board = make2dList(15, 15, '') randomlyPlaceObjectOnBoard(app, 'player1') randomlyPlaceObjectOnBoard(app, 'player2') randomlyPlaceObjectOnBoard(app, 'flag1') randomlyPlaceObjectOnBoard(app, 'flag2') def appStarted(app): app.wins = [0, 0] # [player1 wins, player2 wins] initRound(app) ########################################### # Controller ########################################### def playerKeyPressed(app, event, keys, player): rightKey, leftKey, upKey, downKey = keys currRow, currCol = findObjectInBoard(app, player) if event.key == rightKey: newRow, newCol = currRow, currCol + 1 elif event.key == leftKey: newRow, newCol = currRow, currCol - 1 elif event.key == upKey: newRow, newCol = currRow - 1, currCol elif event.key == downKey: newRow, newCol = currRow + 1, currCol if not isInBounds(app, newRow, newCol): return targetObject = app.board[newRow][newCol] if targetObject == '': app.board[currRow][currCol] = '' app.board[newRow][newCol] = player elif targetObject.startswith('flag') and targetObject[-1] == player[-1]: app.board[currRow][currCol] = '' app.board[newRow][newCol] = player app.wins[int(player[-1])-1] += 1 # player1 indexes into wins[0] app.gameOver = True app.winner = player def keyPressed(app, event): if app.gameOver: if event.key == 'r': initRound(app) return playerOneKeys = ('Right', 'Left', 'Up', 'Down') playerTwoKeys = ('d', 'a', 'w', 's') if event.key in playerOneKeys: playerKeyPressed(app, event, playerOneKeys, 'player1') elif event.key in playerTwoKeys: playerKeyPressed(app, event, playerTwoKeys, 'player2') def mousePressed(app, event): if app.gameOver: return row, col = getCell(app, event.x, event.y) if app.board[row][col] == '': app.board[row][col] = 'rock' ########################################### # View ########################################### def drawCell(app, canvas, row, col): left, top, right, bottom = getCellBounds(app, row, col) canvas.create_rectangle(left, top, right, bottom) if app.board[row][col] == 'player1': canvas.create_oval(left, top, right, bottom, fill='red') if app.board[row][col] == 'player2': canvas.create_oval(left, top, right, bottom, fill='blue') if app.board[row][col] == 'rock': canvas.create_oval(left, top, right, bottom, fill='grey') if app.board[row][col] == 'flag1': canvas.create_polygon(left, top, left, bottom, right, top + (bottom - top) // 2, fill='red' ) if app.board[row][col] == 'flag2': canvas.create_polygon(left, top, left, bottom, right, top + (bottom - top) // 2, fill='blue' ) def drawGameOver(app, canvas): spacer = 60 messages = [ f'{app.winner.title()} won!', f'Player1 Wins: {app.wins[0]}', f'Player2 Wins: {app.wins[1]}', f'Press \'r\' to play again' ] for i in range(len(messages)): canvas.create_text(app.width//2,app.height//4 + i*spacer, text=messages[i], font='Arial 30' ) def redrawAll(app, canvas): if app.gameOver: drawGameOver(app, canvas) return for row in range(len(app.board)): for col in range(len(app.board[0])): drawCell(app, canvas, row, col) runApp(width=500, height=500)