示例#1
0
class Board:
    def __init__(self,displaysurf,fontobj):
        self.displaysurf = displaysurf
        self.fontobj = fontobj

        self.board = self.getBlankBoard()
        self.boardWithPieces = self.getBlankBoard()
        self.piece = Piece(random.choice(list(SHAPES)))

        self.completedLines = 0
        self.totalCompletedLines = 0
        self.score = 0
        self.level = LEVELONE
        self.gameState = ACTIVE
        self.softDropDistance = 0
        self.hardDropDistance = 0
        #draw the board
        self.draw()

    def draw(self):
        # draw the border around the board
        pygame.draw.rect(self.displaysurf, BORDERCOLOR,
                         (XMARGIN - BORDERWIDTH, YMARGIN - BORDERWIDTH,
                         (BOARDWIDTH * BOXSIZE) + BORDERWIDTH*2, (BOARDHEIGHT * BOXSIZE) + BORDERWIDTH*2), 0)

        # fill the background of the board
        pygame.draw.rect(self.displaysurf, BOARDGAMECOLOR, (XMARGIN, YMARGIN, BOXSIZE * BOARDWIDTH, BOXSIZE * BOARDHEIGHT))

        if self.gameState == ACTIVE:
            self.drawPiece()
        
        # draw the individual boxes on the board
        for x in range(BOARDWIDTH):
            for y in range(BOARDHEIGHT):
                self.drawBox(x, y, self.board[x][y])   

        if self.gameState == PAUSE:
            pausedSurf = self.fontobj.render('PAUSED', True, WHITE)
            pausedRect = pausedSurf.get_rect()
            pausedRect.topleft = (XMARGIN + (BOARDWIDTH * BOXSIZE)/2 - pausedRect.width/2, YMARGIN + (BOXSIZE * BOARDHEIGHT / 2))
            pygame.draw.rect(self.displaysurf, BOARDGAMECOLOR, pausedRect)
            self.displaysurf.blit(pausedSurf, pausedRect)

        elif self.gameState == OVER:
            overSurf = self.fontobj.render('GAMEOVER!', True, WHITE)
            overRect = overSurf.get_rect()
            overRect.topleft = (XMARGIN + (BOARDWIDTH * BOXSIZE)/2 - overRect.width/2, YMARGIN + (BOXSIZE * BOARDHEIGHT / 2))
            pygame.draw.rect(self.displaysurf, BOARDGAMECOLOR, overRect)
            self.displaysurf.blit(overSurf, overRect)

        elif self.gameState == WIN:
            winSurf = self.fontobj.render('YAY! YOU WON!', True, WHITE)
            winRect = winSurf.get_rect()
            winRect.topleft = (XMARGIN + (BOARDWIDTH * BOXSIZE)/2 - winRect.width/2, YMARGIN + (BOXSIZE * BOARDHEIGHT / 2))
            pygame.draw.rect(self.displaysurf, BOARDGAMECOLOR, winRect)
            self.displaysurf.blit(winSurf, winRect)
            win2surf = self.fontobj.render("'P' to Play again!", True, WHITE)
            win2Rect = win2surf.get_rect()
            win2Rect.topleft = (XMARGIN + (BOARDWIDTH * BOXSIZE)/2 - winRect.width/2, YMARGIN + BOXSIZE * (1 + BOARDHEIGHT / 2))
            pygame.draw.rect(self.displaysurf, BOARDGAMECOLOR, win2Rect)
            self.displaysurf.blit(win2surf, win2Rect)


    def clearOldPiece(self):
        for x in range(4):
            for y in range(4):
                if self.piece.piece[x][y] != BLANK and self.board[self.piece.x+x][self.piece.y+y] != BLANK:
                    self.board[self.piece.x+x][self.piece.y+y] = BLANK

    def drawPiece(self,dX=0,dY=0):
        #clear the old piece
        self.clearOldPiece()

        #change the coordinates
        self.piece.x += dX
        self.piece.y += dY

        #check if valid
        if not self.isValidMove(None):
            self.gameState = OVER

        #place the piece on the board
        for x in range(4):
            for y in range(4):
                if self.isOnBoard(bX=self.piece.x+x,bY=self.piece.y+y):
                    if self.piece.piece[x][y] != BLANK:     #only draw the nonblank tiles
                        self.board[self.piece.x+x][self.piece.y+y] = self.piece.piece[x][y]

    def setPiece(self):
        #place the piece on the boardWithPieces.
        for x in range(4):
            for y in range(4):
                if self.isOnBoard(bX=self.piece.x+x,bY=self.piece.y+y):
                    if self.piece.piece[x][y] != BLANK:     #only draw the nonblank tiles
                        self.boardWithPieces[self.piece.x+x][self.piece.y+y] = self.piece.piece[x][y]
                        self.board[self.piece.x+x][self.piece.y+y] = self.piece.piece[x][y]

    def newPiece(self,shapeType):
        self.piece = Piece(shapeType)

    #draw each box in the board based on the given x,y, coordinate and box type
    def drawBox(self,x,y,boxType):
        if boxType == I:
            boxColor = RED
        elif boxType == J:
            boxColor = YELLOW
        elif boxType == L:
            boxColor = PURPLE
        elif boxType == O:
            boxColor = BLUE
        elif boxType == S:
            boxColor = LIGHTBLUE
        elif boxType == T:
            boxColor = GREEN
        elif boxType == Z:
            boxColor = ORANGE
        else:
            boxColor = BLACK

        #draw box border
        pygame.draw.rect(self.displaysurf, BLACK, (x*BOXSIZE + XMARGIN, y*BOXSIZE + YMARGIN, BOXSIZE, BOXSIZE))
        
        #draw box fill
        pygame.draw.rect(self.displaysurf, boxColor, 
                        (x*BOXSIZE + XMARGIN + BBWIDTH, y*BOXSIZE + YMARGIN + BBWIDTH, 
                        BOXSIZE - BBWIDTH, BOXSIZE - BBWIDTH))

    def getBlankBoard(self):
        board = []
        # create and return a new blank board data structure
        for i in range(BOARDWIDTH):
            board.append([BLANK] * BOARDHEIGHT)
        return board

    def clearBoard(self):
        for x in range(BOARDWIDTH):
            for y in range(BOARDHEIGHT):
                self.board[x][y] = BLANK
                self.boardWithPieces[x][y] = BLANK

    #def getNextPiece(self):

    def movePiece(self, action):
        isSet = False
        
        if action == DROP:
            while self.isValidMove(action):
                self.clearOldPiece()
                self.piece.y += 1
                self.hardDropDistance += 1
            self.setPiece()
            isSet = True

        elif action == DOWN:
            if self.isValidMove(action):
                self.drawPiece(dY=1)
            else:
                self.setPiece()
                isSet = True
        elif action == LEFT:
            if self.isValidMove(action):
                self.drawPiece(dX=-1)
        elif action == RIGHT:
            if self.isValidMove(action):
                self.drawPiece(dX=1)
        elif action == ROTATE:
            if self.isValidMove(action):
                self.rotate()

        return isSet
    
    def rotate(self):
        #clear the old piece
        for x in range(4):
            for y in range(4):
                    if self.piece.piece[x][y] != BLANK:
                        self.board[self.piece.x+x][self.piece.y+y] = BLANK
        self.piece.rotate()

    #checks if provided coordinates are still on the board.
    def isOnBoard(self,bX=0,bY=0):
        if (0 <= bX < BOARDWIDTH) and (0 <= bY < BOARDHEIGHT):
            return True
        else:
            return False

    '''
    isValidMove()
    input
        action - directional or rotational action
    output
        boolean - True if valid action, otherwise False
    '''
    def isValidMove(self,action):
        valid = True

        #generate a list of valid moves base of piece's current position
        #TODO The following block of code can still be condensed

        if action == DOWN or action == DROP:
            for y in reversed(range(self.piece.gridSize)):
                for x in range(self.piece.gridSize):
                    if self.piece.piece[x][y] != BLANK: #if current box is not blank, check below it on the boardWithPieces
                        if self.isOnBoard(bX=(self.piece.x + x), bY=(self.piece.y + y + 1)):    #check if the next spot is on the board
                            if self.boardWithPieces[self.piece.x + x][self.piece.y + y + 1] != BLANK:     #check if the next spot is blank
                                valid = False
                        else:
                            valid = False
        elif action == LEFT:
            for x in range(self.piece.gridSize):
                for y in range(self.piece.gridSize):
                    if self.piece.piece[x][y] != BLANK: #if current box is not blank, check to the left of it
                        if self.isOnBoard(bX=(self.piece.x + x - 1), bY =(self.piece.y + y)):   #check if the next spot is on the board
                            if self.boardWithPieces[self.piece.x + x - 1][self.piece.y + y] != BLANK:     #check if the next spot is blank
                                valid = False
                        else:
                            valid = False
        elif action == RIGHT:
            for x in reversed(range(self.piece.gridSize)):
                for y in range(self.piece.gridSize):
                    if self.piece.piece[x][y] != BLANK: #if current box is not blank, check to the left of it
                        if self.isOnBoard(bX=(self.piece.x + x + 1), bY =(self.piece.y + y)):   #check if the next spot is on the board
                            if self.boardWithPieces[self.piece.x + x + 1][self.piece.y + y] != BLANK: #check if the next spot is blank
                                valid = False
                        else:
                            valid = False
        elif action == ROTATE:
             #Initialize temporary variables
            tempRotatedPiece = self.piece.setPiece(BLANK)

            #Rotate the piece
            for col in range(self.piece.gridSize):
                for index, cell in zip(reversed(range(self.piece.gridSize)),self.piece.piece[col]):
                    tempRotatedPiece[index][col] = cell

            for x in range(self.piece.gridSize):
                for y in range(self.piece.gridSize):
                    if tempRotatedPiece[x][y] != BLANK:
                        if self.isOnBoard(bX=(self.piece.x + x), bY= (self.piece.y + y)):
                            if self.boardWithPieces[self.piece.x + x][self.piece.y + y] != BLANK:
                                valid = False
                        else:
                            valid = False
        else:   #check current position
            for x in range(self.piece.gridSize):
                for y in range(self.piece.gridSize):
                    if self.piece.piece[x][y] != BLANK: #if current box is not blank, check under it
                        if self.isOnBoard(bX=(self.piece.x + x), bY =(self.piece.y + y)):   #check if the next spot is on the board
                            if self.boardWithPieces[self.piece.x + x][self.piece.y + y] != BLANK:
                                valid = False
                        else:
                            valid = False

        return valid

    #scan for completed rows, update completedLines, clear them.
    def clearCompletedRows(self):
        y = BOARDHEIGHT - 1;
        while y >= 0:
            if self.isCompletedRow(y):
                self.completedLines += 1
                #clear row by shifting board down
                for y1 in reversed(range(y)):
                    for x in range(BOARDWIDTH):
                        self.boardWithPieces[x][y1+1] = self.boardWithPieces[x][y1]
                        self.board[x][y1+1] = self.board[x][y1]
            else:
                y -= 1

        self.totalCompletedLines += self.completedLines
        self.level = 1 + int(self.totalCompletedLines/10)
        self.updateScore()

    def updateScore(self):
        #scores for completed lines
        if self.completedLines == 1:
            self.score += (ONELINEPTS * self.level)
        elif self.completedLines == 2:
            self.score += (TWOLINEPTS * self.level)
        elif self.completedLines == 3:
            self.score += (THREELINEPTS * self.level)
        elif self.completedLines == 4:   #TETRIS!!
            self.score += (FOURLINEPTS * self.level)

        #score for soft and hard dropping
        self.score += self.softDropDistance * 1
        self.score += self.hardDropDistance * 4

        #clear old tallies
        self.completedLines = 0
        self.softDropDistance = 0
        self.hardDropDistance = 0


    
    #returns a boolean if a row is completed
    def isCompletedRow(self, y):
        completed = True
        for x in range(BOARDWIDTH):
            if self.boardWithPieces[x][y] == BLANK:
                completed = False
        return completed

    def checkGameState(self):
        if self.level == 11:
            self.gameState = WIN

    def reset(self):
        self.clearBoard()
        self.completedLines = 0
        self.totalCompletedLines = 0
        self.score = 0
        self.level = LEVELONE
        self.gameState = ACTIVE
        self.softDropDistance = 0
        self.hardDropDistance = 0
示例#2
0
class Queue:
    def __init__(self,displaysurf):
        self.panel = self.getBlankPanel()
        self.displaysurf = displaysurf
        self.piece = Piece(random.choice(list(SHAPES)))
        self.piece.x = 1
        self.piece.y = 1

    def draw(self):
        queueX = XMARGIN + BOXSIZE + (BOARDWIDTH * BOXSIZE)
        queueY = YMARGIN
        queueWidth = PANELWIDTH * BOXSIZE
        queueHeight = PANELHEIGHT * BOXSIZE

        #draw the panel border
        pygame.draw.rect(self.displaysurf, BORDERCOLOR, (queueX - BORDERWIDTH, queueY - BORDERWIDTH, 
                        queueWidth + BORDERWIDTH*2,queueHeight + BORDERWIDTH*2))

        #draw the panel
        pygame.draw.rect(self.displaysurf, BOARDGAMECOLOR, (queueX, queueY, queueWidth, queueHeight))

        #draw the piece
        self.drawPiece()

        #draw the panel to the screen
        for x in range(PANELWIDTH):
            for y in range(PANELHEIGHT):
                self.drawBox(x, y, self.panel[x][y])

    #draw each box in the board based on the given x,y, coordinate and box type
    def drawBox(self,x,y,boxType):
        if boxType == I:
            boxColor = RED
        elif boxType == J:
            boxColor = YELLOW
        elif boxType == L:
            boxColor = PURPLE
        elif boxType == O:
            boxColor = BLUE
        elif boxType == S:
            boxColor = LIGHTBLUE
        elif boxType == T:
            boxColor = GREEN
        elif boxType == Z:
            boxColor = ORANGE
        else:
            boxColor = BLACK

        #draw box border
        pygame.draw.rect(self.displaysurf, BLACK, (x*BOXSIZE + PANELPIXELX, y*BOXSIZE + PANELPIXELY, BOXSIZE, BOXSIZE))
        
        #draw box fill
        pygame.draw.rect(self.displaysurf, boxColor, 
                        (x*BOXSIZE + PANELPIXELX + BBWIDTH, y*BOXSIZE + PANELPIXELY + BBWIDTH, 
                        BOXSIZE - BBWIDTH, BOXSIZE - BBWIDTH))

    def drawPiece(self):
        #clear the old piece
        self.clearOldPiece()

        #place the piece on the board.
        for x in range(4):
            for y in range(4):
                self.panel[self.piece.x+x][self.piece.y+y] = self.piece.piece[x][y]

    def clearOldPiece(self):
        for x in range(4):
            for y in range(4):
                self.panel[x][y] = BLANK

    def getNextPiece(self):
        nextPieceType = self.piece.pieceType
        
        #get a new random shape
        self.piece.pieceType = random.choice(list(SHAPES))
        
        #replace the queued piece
        self.piece.piece[:] = self.piece.setPiece(self.piece.pieceType)

        #return the next piece
        return nextPieceType

    def getBlankPanel(self):
        panel = []
        # create and return a new blank board data structure
        for i in range(PANELWIDTH):
            panel.append([BLANK] * PANELHEIGHT)
        return panel

    def reset(self):
        self.clearOldPiece()