def test_TriPeaks2(self): # checks if initboard makes same size board each time t1 = TriPeaks() t2 = TriPeaks() tx = t1.initBoard() ty = t2.initBoard() self.assertEqual(tx, ty)
def test_TriPeaks_decksize(self): #make sure that decksize is the same ta = TriPeaks() tb = TriPeaks() t1 = ta.deckSize() t2 = tb.deckSize() self.assertEqual(t1,t2)
def setupGame(self): self.game = TriPeaks() self.hasWon = False self.hasLost = False self.showHelp = False # Help instructions shown if True self.showHints = False # Legal cards shown if True self.showScore = False self.scores = self.game.highscoreTable() self.selectedCard = None # The card selected with the mouse self.lastClickTime = 0.0 # The time of last mouse click self.doubleClickInterval = 0.3 # The threshold interval between clicks in double mouse click self.animationQueue = [] # Cards that are moving self.waitingQueue = deque() # Cards waiting to be moved self.mousex = 0 # x coordinate of mouse event self.mousey = 0 # y coordinate of mouse event self.startx = 100 # Start drawing the board cards at this point self.starty = 100 # Start drawing the board cards at this point self.heapRect = pygame.Rect(400, 450, self.CARDWIDTH, self.CARDHEIGHT) # Rectangle around the heap cards self.deckRect = pygame.Rect(100, 450, self.CARDWIDTH, self.CARDHEIGHT) # Rectangle around the deck cards self.cardSound = pygame.mixer.Sound("deal.wav") self.sweepSound = pygame.mixer.Sound("sweep.wav") self.sadLoseSound = pygame.mixer.Sound("sadLose.wav") self.rockyWinSound = pygame.mixer.Sound("rocky.wav") self.shuffleSound = pygame.mixer.Sound("shuffle.wav") self.backgroundImg = pygame.image.load('woodBackground.jpg') self.initCardsPos()
def setUp(self): self.testCard1a = Card('H',10, 0, 0, None) self.testCard1b = Card('H',10, 0, 0, None) self.testCard2a = Card('S',5, 0, 0, None) self.testCard2b = Card('S',5, 0, 0, None) self.testCard3 = Card('T',3, 0, 0, None) self.initialDeck = Deck(52) self.sortedDeck = Deck(52) self.sortedDeck.cards.sort() self.shuffledDeck = Deck(52) self.shuffledDeck.shuffleCards() self.game1 = TriPeaks() self.game2 = TriPeaks() self.deckCard = self.game1.deck.cards[-1] self.heapCard = self.game1.heap[-1] self.legalCard = Card('H', (self.heapCard.value)%13+1, 3,3,None) self.illegalCard = Card('H', (self.heapCard.value)%13+5, 0,0,None)
class TriPeaksGUI(object): # Constants: FPS = 30 # Frames per second, the general speed of the program WINDOWWIDTH = 1000 # Window's width in pixels WINDOWHEIGHT = 600 # Windows' height in pixels CARDWIDTH = 73 # Card width in pixels CARDHEIGHT = 96 # Card height in pixels OFFSETX = CARDWIDTH/2.0 # To find the midpoint of card OFFSETY = CARDHEIGHT/2.0 # To find the midpoint of card GAPSIZE = 10 # Size of gap between cards in pixels BOARDCOLS = 10 # Number of columns of cards BOARDROWS = 4 # Number of rows of cards def __init__(self): pygame.init() self.setupGame() # Pre: A TriPeaksGUI object has been created # Post: The main game function is running until the game is stopped # Run: TriPeaksGUI.gameLoop() def gameLoop(self): global FPSCLOCK, DISPLAYSURF FPSCLOCK = pygame.time.Clock() # Clock that updates the screen with the frame rate FPS DISPLAYSURF = pygame.display.set_mode((self.WINDOWWIDTH, self.WINDOWHEIGHT)) # The game display surface pygame.display.set_caption('Tri Peaks') # Window title # Main game loop while True: DISPLAYSURF.blit(self.backgroundImg, (0,0)) self.drawBoard() # Draws the game board # Event handling loop for event in pygame.event.get(): if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE): pygame.quit() sys.exit() if event.type == KEYUP and event.key == K_r: self.restartGame() if event.type == KEYUP and event.key == K_h: self.showHints = not self.showHints # Test: show help if event.type == KEYUP and event.key == K_F1: self.showHelp = not self.showHelp self.showScore = False elif event.type == KEYUP and event.key == K_t: self.showScore = not self.showScore self.showHelp = False # Event when the mouse is moved elif event.type == MOUSEMOTION: self.onMouseMove(event) # Event when the mouse is double clicked elif event.type == MOUSEBUTTONDOWN and (time() - self.lastClickTime < self.doubleClickInterval): self.onMouseDoubleClick(event) # Event when the mouse button is down elif event.type == MOUSEBUTTONDOWN: self.onMouseDown(event) # Event when the mouse button has been released elif event.type == MOUSEBUTTONUP: self.onMouseReleased(event) self.game.elapsedTime() self.animateCard() if self.game.isPlaying: self.isGameOver() # Redraws the screen and waits a clock tick of one frame rate pygame.display.update() FPSCLOCK.tick(self.FPS) # Pre: event is a pygame.event object # Post: If a movable, legal card is selected with the mouse, it is moved to the heap # Run: TriPeaksGUI.onMouseMove(event) def onMouseDoubleClick(self, event): card = self.posToCard(*event.pos) if card is None or not self.game.isMovable(card.row, card.col): return if self.game.isLegal(card): self.animationQueue.append((card, (self.heapRect.x, self.heapRect.y), lambda: self.game.moveToHeap(card))) self.cardSound.play() # Pre: event is a pygame.event object # Post: If a movable card has been selected with the mouse, it follows the mouse motion # Run: TriPeaksGUI.onMouseMove(event) def onMouseMove(self, event): if not self.game.isPlaying: return if self.selectedCard is not None and self.game.isMovable(self.selectedCard.row, self.selectedCard.col): self.selectedCard.moveTo(event.pos[0]-self.OFFSETX, event.pos[1]-self.OFFSETY) # Pre: event is a pygame.event object # Post: If a movable card has been selected with the mouse, it becomes the selected card. If the card deck # is clicked, then a card is moved to the heap # Run: TriPeaksGUI.onMouseDown(event) def onMouseDown(self, event): self.lastClickTime = time() card = self.posToCard(*event.pos) if card is not None and self.game.isMovable(card.row, card.col): self.selectedCard = self.posToCard(*event.pos) elif self.deckRect.collidepoint(*event.pos) and len(self.game.deck.cards) > 0: self.animationQueue.append((self.game.deck.cards[-1], (self.heapRect.x, self.heapRect.y), lambda: self.game.toHeap())) #self.deckToHeapCard = self.game.deck.cards[-1] self.cardSound.play() # Pre: event is a pygame.event object # Post: If a legal card was selected then it moves to the heap if it collides with the heap card, # otherwise the card is moved back to its position in the board # Run: TriPeaksGUI.onMouseReleased(event) def onMouseReleased(self, event): if self.selectedCard is not None: x, y = self.cardToPos(self.selectedCard.row, self.selectedCard.col) selx, sely = event.pos selCardRect = pygame.Rect(selx, sely, self.CARDWIDTH, self.CARDHEIGHT) if selCardRect.colliderect(self.heapRect) and self.game.isLegal(self.selectedCard): self.game.moveToHeap(self.selectedCard) else: self.selectedCard.moveTo(x,y) self.selectedCard = None def animateCard(self): if len(self.animationQueue) == 0: return for i,triple in enumerate(self.animationQueue): card,dest,callback = triple dx = dest[0] - card.cardx dy = dest[1] - card.cardy distSq = dx**2 + dy**2 card.moveTo(card.cardx + dx/2.0, card.cardy + dy/2.0) if distSq < 1: callback() del(self.animationQueue[i]) def isGameOver(self): if self.game.hasWon(): self.game.isPlaying = False self.hasWon = True self.rockyWinSound.play() elif self.game.hasLost(): self.game.isPlaying = False self.hasLost = True self.sadLoseSound.play() def restartGame(self): pygame.mixer.stop() self.setupGame() def setupGame(self): self.game = TriPeaks() self.hasWon = False self.hasLost = False self.showHelp = False # Help instructions shown if True self.showHints = False # Legal cards shown if True self.showScore = False self.scores = self.game.highscoreTable() self.selectedCard = None # The card selected with the mouse self.lastClickTime = 0.0 # The time of last mouse click self.doubleClickInterval = 0.3 # The threshold interval between clicks in double mouse click self.animationQueue = [] # Cards that are moving self.waitingQueue = deque() # Cards waiting to be moved self.mousex = 0 # x coordinate of mouse event self.mousey = 0 # y coordinate of mouse event self.startx = 100 # Start drawing the board cards at this point self.starty = 100 # Start drawing the board cards at this point self.heapRect = pygame.Rect(400, 450, self.CARDWIDTH, self.CARDHEIGHT) # Rectangle around the heap cards self.deckRect = pygame.Rect(100, 450, self.CARDWIDTH, self.CARDHEIGHT) # Rectangle around the deck cards self.cardSound = pygame.mixer.Sound("deal.wav") self.sweepSound = pygame.mixer.Sound("sweep.wav") self.sadLoseSound = pygame.mixer.Sound("sadLose.wav") self.rockyWinSound = pygame.mixer.Sound("rocky.wav") self.shuffleSound = pygame.mixer.Sound("shuffle.wav") self.backgroundImg = pygame.image.load('woodBackground.jpg') self.initCardsPos() # Pre: A TriPeaksGUI object has been created # Post: The cards in the board are assigned their positions # Run: TriPeaksGUI.initCardsPos() def initCardsPos(self): self.shuffleSound.play() for row in range(self.BOARDROWS): for col in range(self.BOARDCOLS): if self.game.board[row][col] is not None: card = self.game.board[row][col] destx = self.startx + col*(self.CARDWIDTH+self.GAPSIZE) + (3-row)*self.GAPSIZE*4 desty = self.starty + row*(0.6*self.CARDHEIGHT) card.cardx = self.deckRect.x card.cardy = self.deckRect.y self.waitingQueue.append( (card, (destx,desty), lambda: self.dealCard()) ) self.waitingQueue[-1] = self.waitingQueue[-1][:2] + (lambda: None,) self.animationQueue.append(self.waitingQueue.popleft()) for card in self.game.deck.cards: card.cardx = self.deckRect.x card.cardy = self.deckRect.y def dealCard(self): self.cardSound.play() self.animationQueue.append(self.waitingQueue.popleft()) # Pre: A TriPeaksGUI object has been created # Post: The game board has been drawn # Run: TriPeaksGUI.drawBoard() def drawBoard(self): # Shows game score font = pygame.font.SysFont("comicsansms", 32) scoreStr = 'Score: ' + str(self.game.score) scoreText = font.render(scoreStr, True, (255, 255, 255)) DISPLAYSURF.blit(scoreText, (20, 20)) # Shows player moves moveStr = 'Moves: ' + str(self.game.moves) moveText = font.render(moveStr, True, (255, 255, 255)) DISPLAYSURF.blit(moveText, (400, 20)) # Shows game time elapsed timeStr = 'Time : ' + str(int(self.game.finaltime)) timeText = font.render(timeStr, True, (255, 255, 255)) DISPLAYSURF.blit(timeText, (800, 20)) # Shows key information font = pygame.font.SysFont("comicsansms", 18) restartStr = 'Press R to restart' quitStr = 'Press ESC to quit' helpStr = 'Press F1 to show/hide help' hintStr = 'Press H to show/hide legal cards' scoreStr = 'Press T to view the top 5 Tri Peaks players' restartText = font.render(restartStr, True, (255, 255, 255)) quitText = font.render(quitStr, True, (255, 255, 255)) helpText = font.render(helpStr, True, (255, 255, 255)) hintText = font.render(hintStr, True, (255, 255, 255)) scoreText = font.render(scoreStr, True, (255, 255, 255)) DISPLAYSURF.blit(restartText, (710, 510)) DISPLAYSURF.blit(quitText, (710, 530)) DISPLAYSURF.blit(helpText, (710, 550)) DISPLAYSURF.blit(hintText, (710, 570)) DISPLAYSURF.blit(scoreText, (710, 590)) # shows cards left cardsleftStr = 'Cards left : ' + str(int(self.game.deckSize())) cardsleftText = font.render(cardsleftStr, True, (255, 255, 255)) DISPLAYSURF.blit(cardsleftText, (20, 550)) # Shows help if help is "on" if self.showHelp: font = pygame.font.SysFont("comicsansms", 18) helpStr1 = 'TRI-PEAKS RULES:' helpStr2 = 'Move all cards from the board to the heap.' helpStr3 = 'You can move cards with value +/-1 the value' helpStr4 = 'of the top card on the heap. You can also click' helpStr5 = 'on the deck to add a card to the heap.' helpText1 = font.render(helpStr1, True, (255, 255, 255)) helpText2 = font.render(helpStr2, True, (255, 255, 255)) helpText3 = font.render(helpStr3, True, (255, 255, 255)) helpText4 = font.render(helpStr4, True, (255, 255, 255)) helpText5 = font.render(helpStr5, True, (255, 255, 255)) DISPLAYSURF.blit(helpText1, (600, 400)) DISPLAYSURF.blit(helpText2, (600, 420)) DISPLAYSURF.blit(helpText3, (600, 440)) DISPLAYSURF.blit(helpText4, (600, 460)) DISPLAYSURF.blit(helpText5, (600, 480)) if self.showScore: self.highScores() # Shows heap for (i, card) in enumerate(self.game.heap): cardImg = pygame.image.load(card.img) if not self.game.isPlaying: DISPLAYSURF.blit(cardImg, (400, 450), special_flags = BLEND_MULT) else: DISPLAYSURF.blit(cardImg, (400, 450)) # Shows animated cards for triple in self.animationQueue: cardImg = pygame.image.load(triple[0].img) DISPLAYSURF.blit(cardImg, (triple[0].cardx, triple[0].cardy)) # Shows cards in board for row in range(self.BOARDROWS): for col in range(self.BOARDCOLS): if self.game.board[row][col] is not None: if self.game.isMovable(row,col): cardImg = pygame.image.load(self.game.board[row][col].img) else: cardImg = pygame.image.load('panda2.png') if not self.game.isPlaying: DISPLAYSURF.blit(cardImg, (self.game.board[row][col].cardx, self.game.board[row][col].cardy), special_flags = BLEND_MULT) elif self.showHints and self.game.isMovable(row,col) and not self.game.isLegal(self.game.board[row][col]): DISPLAYSURF.blit(cardImg, (self.game.board[row][col].cardx, self.game.board[row][col].cardy), special_flags = BLEND_MULT) else: DISPLAYSURF.blit(cardImg, (self.game.board[row][col].cardx, self.game.board[row][col].cardy)) # Shows deck if self.game.deckSize() > 0: DISPLAYSURF.blit(pygame.image.load('panda2.png'), (100, 450)) # Winning message if self.hasWon: font = pygame.font.SysFont("comicsansms", 70) winStr = 'YOU WON!!!' winText = font.render(winStr, True, (0,255,0)) DISPLAYSURF.blit(winText, (300, 200)) # Losing message if self.hasLost: font = pygame.font.SysFont("comicsansms", 70) font2 = pygame.font.SysFont("comicsansms", 50) loseStr = 'YOU LOST!!!' againStr = 'Press R to start a new game' loseText = font.render(loseStr, True, (255,0,0)) againText = font2.render(againStr, True, (255,0,0)) DISPLAYSURF.blit(loseText, (300, 200)) DISPLAYSURF.blit(againText, (200, 270)) def highScores(self): font = pygame.font.SysFont("comicsansms", 18) table = 'Top 5' header = 'Name Points Time Moves' line = '------------------------------------' h = 420 for row in self.scores: w = 600 for col in row: DISPLAYSURF.blit(font.render(str(col)[0:6], True, (0, 0, 0)), (w, h)) w += 80 h += 20 lineText = font.render(line, True, (0, 0, 0)) tableText = font.render(table, True, (0, 0, 0)) headerText = font.render(header, True, (0, 0, 0)) DISPLAYSURF.blit(tableText, (700, 380)) DISPLAYSURF.blit(headerText, (600, 400)) DISPLAYSURF.blit(lineText, (600, 407)) def newHighScore: findScoreCol = 0 for row in self.scores: findScoreCol += 1 for col in row: if findScoreCol == 2 and self.game.score > col: font = pygame.font.SysFont("comicsansms", 35) DISPLAYSURF.blit(font.render("You got a new high score! Enter your name:", True, (255, 255, 255)), (350, 290)) nameStr = '' while not event.type == KEYUP and not event.key == K_ENTER: nameStr += str(event.key) nameText = font.render(nameStr, True, (255, 255, 255)) DISPLAYSURF.blit(nameText, (350, 310)) with open("highscores.csv", "w") as csvfile: a = csv.writer(csvfile, delimiter = ',') self.scores.append([nameStr, self.game.score, self.game.finaltime, self.game.moves]) self.scores.sort(key=lambda x: x[1]) self.scores.reverse() a.writerows(self.scores[0:5]) self.highScores() # Pre: row and col are integers # Post: Returns the left, top coordinates of the card at row, col # Run: TriPeaksGUI.cardToPos(row, col) def cardToPos(self, row, col): left = self.startx + col * (self.CARDWIDTH + self.GAPSIZE) + (3-row)*self.GAPSIZE*4 top = self.starty + row * 0.6*(self.CARDHEIGHT) return (left, top) # Pre: x and y are integers # Post: Returns the card at window coordinates (x,y), returns None if there is no card there # Run: TriPeaksGUI.posToCard(x,y) def posToCard(self, x,y): for cardCol in range(self.BOARDCOLS): for cardRow in range(self.BOARDROWS): left, top = self.cardToPos(cardRow, cardCol) cardRect = pygame.Rect(left, top, self.CARDWIDTH, self.CARDHEIGHT) if cardRect.collidepoint(x, y) and self.game.isMovable(cardRow, cardCol): return self.game.board[cardRow][cardCol] return None
def test_TriPeaks_Highscore(self): #checks if highscore works t1 = TriPeaks() x = t1.addScore(500) self.assertGreater(t1.score, 250)
class Test(unittest.TestCase): def setUp(self): self.testCard1a = Card('H',10, 0, 0, None) self.testCard1b = Card('H',10, 0, 0, None) self.testCard2a = Card('S',5, 0, 0, None) self.testCard2b = Card('S',5, 0, 0, None) self.testCard3 = Card('T',3, 0, 0, None) self.initialDeck = Deck(52) self.sortedDeck = Deck(52) self.sortedDeck.cards.sort() self.shuffledDeck = Deck(52) self.shuffledDeck.shuffleCards() self.game1 = TriPeaks() self.game2 = TriPeaks() self.deckCard = self.game1.deck.cards[-1] self.heapCard = self.game1.heap[-1] self.legalCard = Card('H', (self.heapCard.value)%13+1, 3,3,None) self.illegalCard = Card('H', (self.heapCard.value)%13+5, 0,0,None) def test_Card1(self): #make sure that the cards are different self.assertNotEqual(self.testCard2a,self.testCard3) def test_Card2(self): #make sure that that the cards are equal self.assertEqual(self.testCard1a,self.testCard1b) def test_Card3(self): #make sure that that the cards are equal self.assertEqual(self.testCard2a,self.testCard2b) def test_shuffleCards(self): # make sure that shuffle maintains the same cards self.shuffledDeck.cards.sort() self.assertTrue(self.shuffledDeck.cards == self.sortedDeck.cards) def test_deckSize(self): #make sure that decksize is the same self.assertEqual(self.game1.deckSize(),self.game2.deckSize()) def test_initBoard(self): #make sure that initboard makes same size board each time self.assertEqual(self.game1.initBoard(), self.game2.initBoard()) def test_addScore(self): #make sure that addScore adds to the score self.game1.addScore(500) self.assertEqual(self.game1.score, 500) def test_Moves(self): #makes sure that moves starts at 0 self.assertEqual(self.game1.moves,0) def test_isMovable1(self): #make sure that card is movable self.assertTrue(self.game1.isMovable(3,3)) def test_isMovable2(self): #make sure that card is not movable self.assertFalse(self.game1.isMovable(1,1)) def test_isLegal1(self): # make sure that card is legal self.assertTrue(self.game1.isLegal(self.legalCard)) def test_isLegal2(self): # make sure that card is illegal self.assertFalse(self.game1.isLegal(self.illegalCard)) def test_moveToHeap(self): # make sure that card is added to heap movedCard = self.game1.moveToHeap(self.legalCard) self.assertEqual(movedCard, self.legalCard) self.assertIn(self.legalCard, self.game1.heap) def test_toHeap(self): # make sure that card is removed from deck and added to heap self.game1.toHeap() self.assertIn(self.deckCard, self.game1.heap) self.assertNotIn(self.deckCard, self.game1.deck.cards)