#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2012
    Posts
    8
    Rep Power
    0

    Tetris using Tkinter, problem removing complete rows


    I am following a tutorial to make tetris in python using Tkinter. I've got most of the meat of the program working, but I am having difficulty in getting it to properly remove a full row. I've traced my alogrythm many times and can't figure out why it won't work.

    the directions for the removeFullRow function are:

    "This function will iterate a variable, oldRow, from the bottom to the top of the board (that is, from rows-1 to 0). It will also start another variable, newRow, at the bottom of the board. Each oldRow that is not full is copied to the newRow, which is then decremented by one. Each oldRow that is full is not copied, and the fullRows counter is incremented. At the end, the rows on top are cleared (set to emptyColor) as necessary"

    Here's my code, I would've attached it in a zip since it's long but I couldn't figure out how to do that. The function in question is called removeFullRow()

    Code:
    import random
    import copy
    
    from Tkinter import *
    
    def mousePressed(event):
        redrawAll()
    
    def keyPressed(event):
      # for now, for testing purposes, just choose a new falling piece
      # whenever ANY key is pressed!
        
        if(event.keysym == "Up"):
            rotateFallingPiece()
        if(event.keysym == "Down"):
            moveFallingPiece(+1,0)
        if(event.keysym == "Left"):
            moveFallingPiece(0, -1)
        if(event.keysym == "Right"):
            moveFallingPiece(0,+1)
        elif (event.char == "r"):
            init()
        redrawAll()
    
    
    def fallingPieceIsLegal(fallingPieceRow,fallingPieceCol):
        fallingPiece = canvas.data.fallingPiece
        tetrisBoard = canvas.data.tetrisBoard
        for row in xrange(len(fallingPiece)):
            for col in xrange(len(fallingPiece[0])):
                if (fallingPiece[row][col]==True):
                    if(0 <= fallingPieceRow+row < len(tetrisBoard) and 0 <= fallingPieceCol+col < len(tetrisBoard[0]) and
                       tetrisBoard[fallingPieceRow+row][fallingPieceCol+col] == canvas.data.emptyColor):
                        continue
                    else:
                        return False
    def isGameOver():
        tetrisBoard = canvas.data.tetrisBoard
        
        
                    
            
    def moveFallingPiece(drow, dcol):
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        fallingPieceRow += drow
        fallingPieceCol += dcol
        if (fallingPieceIsLegal(fallingPieceRow, fallingPieceCol)== False):
            fallingPieceRow = canvas.data.fallingPieceRow
            fallingPieceCol = canvas.data.fallingPieceCol
            return False
    
        else:
            canvas.data.fallingPieceRow = fallingPieceRow
            canvas.data.fallingPieceCol = fallingPieceCol
            return True
        
                           
        
            
    def timerFired():
        moveFallingPiece(+1, 0)
        redrawAll()
        tetrisBoard = canvas.data.tetrisBoard
        fallingPiece = canvas.data.fallingPiece
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        delay = 300 # milliseconds
        if (moveFallingPiece(+1, 0) == False):
            placeFallingPiece()
            newFallingPiece()
            removeFullRow()
            
        canvas.after(delay, timerFired) # pause, then call timerFired again
    
    
    
    def redrawAll():
        canvas.delete(ALL)
        drawGame()
    
    def newFallingPiece():
        tetrisPieces = canvas.data.tetrisPieces
        tetrisPieceColors = canvas.data.tetrisPieceColors
        fallingPiece = tetrisPieces[random.randint(0, len(tetrisPieces)-1)]
        fallingPieceColor = tetrisPieceColors[random.randint(0, len(tetrisPieceColors)-1)]
        canvas.data.fallingPiece = fallingPiece
        canvas.data.fallingPieceColor = fallingPieceColor
        cols = canvas.data.cols
        fallingPieceCols = len(fallingPiece)
        fallingPieceRow = 0
        fallingPieceCol = cols/2 - fallingPieceCols/2
        canvas.data.fallingPieceRow = fallingPieceRow
        canvas.data.fallingPieceCol = fallingPieceCol
    
    
        
        
    
    def placeFallingPiece():
        fallingPiece = canvas.data.fallingPiece
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        fallingPieceColor = canvas.data.fallingPieceColor
        tetrisBoard = canvas.data.tetrisBoard
        for row in xrange(len(fallingPiece)):
            for col in xrange(len(fallingPiece[0])):
                if fallingPiece[row][col] == True:
                    tetrisBoard[fallingPieceRow+row][fallingPieceCol+col] = fallingPieceColor
    
    def drawGame():
        margin=20
        width = canvas.data.canvasWidth
        height = canvas.data.canvasHeight
        canvas.create_rectangle(0, 0, width + margin, height + margin, fill="orange")
        drawTetrisBoard()
        drawFallingPiece()
    
    def isFullRow(tetrisBoard, oldRow):
        fullRow = len(tetrisBoard[0])
        count = 0
        for i in xrange(len(tetrisBoard[oldRow])):
            if tetrisBoard[oldRow][i]!="blue":
                count+=1
                if count == fullRow:
                    return True
    
    def removeFullRow():
        tetrisBoard = canvas.data.tetrisBoard
        rows = len(tetrisBoard)
        cols = len(tetrisBoard[0])
        newTetrisBoard=[]
        newTetrisBoard+=[[canvas.data.emptyColor]*cols]*rows
        fullRows = 0
        newRow = len(tetrisBoard)-1
        for oldRow in xrange(rows-1, -1, -1):
            if not isFullRow(tetrisBoard, oldRow):
                i = 0
                for element in tetrisBoard[oldRow]:
                    newTetrisBoard[newRow][i] = element
                    i+=1
                newRow -=1
            else:
                fullRows +=1
        canvas.data.tetrisBoard = newTetrisBoard
    
        
    
    def fallingPieceCenter():
        fallingPiece = canvas.data.fallingPiece
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        rows = len(fallingPiece)
        cols = len(fallingPiece[0])
        centerRow = fallingPieceRow + rows/2
        centerCol = fallingPieceCol +cols/2
        return(centerRow, centerCol)
    
    def rotateFallingPiece():
        tetrisBoard = canvas.data.tetrisBoard
        fallingPiece = canvas.data.fallingPiece
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        newPiece = []
        oldPieceRow = fallingPieceRow
        oldPieceCol = fallingPieceCol
        oldCenterRow = fallingPieceCenter()[0]
        oldCenterCol = fallingPieceCenter()[1]
        #rotation
        newPiece = list(zip(*fallingPiece))
        canvas.data.fallingPiece = newPiece
        newCenterRow = fallingPieceCenter()[0]
        newCenterCol = fallingPieceCenter()[1]
        rows = len(newPiece)
        cols = len(newPiece[0])
        for row in xrange(rows):
            for col in xrange(cols):
                if newPiece[row][col] == True:
                    drawTetrisCell(tetrisBoard, oldPieceRow+newCenterRow-oldCenterRow,
                                   oldPieceCol+newCenterCol-oldCenterCol, canvas.data.fallingPieceColor)
    
    
    
                                              
    def drawFallingPiece():
        fallingPiece = canvas.data.fallingPiece
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        tetrisBoard = canvas.data.tetrisBoard
        rows = len(fallingPiece)
        cols = len(fallingPiece[0])
        for row in xrange(rows):
            for col in xrange(cols):
                if fallingPiece[row][col] == True:
                    drawTetrisCell(tetrisBoard, row+fallingPieceRow, col+fallingPieceCol, canvas.data.fallingPieceColor)
    
    def drawTetrisBoard():
        tetrisBoard = canvas.data.tetrisBoard
        rows = canvas.data.rows
        cols = canvas.data.cols
        for row in range(rows):
            for col in range(cols):
                drawTetrisCell(tetrisBoard, row, col, tetrisBoard[row][col])
    
    def drawTetrisCell(tetrisBoard, row, col, color ):
        margin = canvas.data.margin
        cellSize = canvas.data.cellSize
        left = margin + col * cellSize
        right = left + cellSize
        top = margin + row * cellSize
        bottom = top + cellSize
        canvas.create_rectangle(left, top, right, bottom, fill = color)
    
    def loadTetrisBoard():
        rows = canvas.data.rows
        cols = canvas.data.cols
        tetrisBoard = []
        emptyColor = canvas.data.emptyColor
        for row in range(rows):
            tetrisBoard += [[emptyColor] * cols]
        canvas.data.tetrisBoard = tetrisBoard
        tetrisBoard[0][0] = "red" # top-left is red
        tetrisBoard[0][cols-1] = "white" # top-right is white
        tetrisBoard[rows-1][0] = "green" # bottom-left is green
        tetrisBoard[rows-1][cols-1] = "gray" # bottom-right is gray
        
    
    
    
    def init():
        rows = canvas.data.rows
        cols = canvas.data.cols
        canvas.data.emptyColor = "blue"
        loadTetrisBoard()
        iPiece = [[ True, True, True,True]]
        jPiece = [[ True, False, False],
                  [ True, True,True]]
        lPiece = [[ False, False, True],
                  [ True,  True,  True]]
    
        oPiece = [[ True, True],
                  [ True, True]]
        sPiece = [[ False, True, True],
                  [ True,  True, False ]]
        tPiece = [[ False, True, False ],
                  [ True,  True, True]]
        zPiece = [[ True,  True, False ],
                  [ False, True, True]]
        tetrisPieces = [ iPiece, jPiece, lPiece, oPiece, sPiece, tPiece, zPiece ]
        tetrisPieceColors = [ "red", "yellow", "magenta", "pink", "cyan", "green", "orange" ]
        canvas.data.tetrisPieces = tetrisPieces
        canvas.data.tetrisPieceColors = tetrisPieceColors
        
        newFallingPiece()
        redrawAll()
        
        
    
    def run(rows, cols):
        # create the root and the canvas
        global canvas
        root = Tk()
        margin = 20
        cellSize = 30
        canvasWidth = 2*margin + cols*cellSize
        canvasHeight = 2*margin + rows*cellSize
        canvas = Canvas(root, width=canvasWidth, height=canvasHeight)
        canvas.pack()
        root.resizable(width=0, height=0)
        # Set up canvas data and call init
        class Struct: pass
        canvas.data = Struct()
        canvas.data.canvasWidth = canvasWidth
        canvas.data.canvasHeight = canvasHeight
        canvas.data.rows = rows
        canvas.data.cols = cols
        canvas.data.margin = margin
        canvas.data.cellSize = cellSize
        init()
        # set up events
        root.bind("<Button-1>", mousePressed)
        root.bind("<Key>", keyPressed)
        timerFired()
        # and launch the app
        root.mainloop()  # This call BLOCKS (so your program waits until you close the window!)
    
    run(15,10)
    im fairly sure the problem is when I'm copying the old row to the new board. thanks a lot
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,931
    Rep Power
    481
    I can't tell if you plan to use extra useless lines of code in the future or if they are just plain useless. Examine:
    Code:
    def moveFallingPiece(drow, dcol):
        fallingPieceRow = canvas.data.fallingPieceRow
        fallingPieceCol = canvas.data.fallingPieceCol
        fallingPieceRow += drow
        fallingPieceCol += dcol
        if (fallingPieceIsLegal(fallingPieceRow, fallingPieceCol)== False):
            fallingPieceRow = canvas.data.fallingPieceRow ################ statement has no useful purpose
            fallingPieceCol = canvas.data.fallingPieceCol ################ statement has no useful purpose
            return False
        else:
            canvas.data.fallingPieceRow = fallingPieceRow
            canvas.data.fallingPieceCol = fallingPieceCol
            return True
    I suppose this does not directly help you. Maybe if you clean it you'll understand your program.

    timerFired calls moveFallingPiece twice. Did you intend that? One time it checks the return value, another ignored.
    Last edited by b49P23TIvg; August 6th, 2012 at 10:51 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo