# 8.29: The isOnBoard() and isValidPosition() Functions

- Page ID
- 14605

def isOnBoard(x, y): return x >= 0 and x < BOARDWIDTH and y < BOARDHEIGHT def isValidPosition(board, piece, adjX=0, adjY=0): # Return True if the piece is within the board and not colliding for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): isAboveBoard = y + piece['y'] + adjY < 0 if isAboveBoard or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK: continue if not isOnBoard(x + piece['x'] + adjX, y + piece['y'] + adjY): return False if board[x + piece['x'] + adjX][y + piece['y'] + adjY] != BLANK: return False return True

The `isOnBoard()`

is a simple function which checks that the XY coordinates that are passed represent valid values that exist on the board. As long as both the XY coordinates are not less `0`

or greater than or equal to the `BOARDWIDTH`

and `BOARDHEIGHT`

constants, then the function returns `True`

.

The `isValidPosition()`

function is given a board data structure and a piece data structure, and returns `True`

if all the boxes in the piece are both on the board and not overlapping any boxes on the board. This is done by taking the piece’s XY coordinates (which is really the coordinate of the upper right box on the 5x5 boxes for the piece) and adding the coordinate inside the piece data structure. Here’s a couple pictures to help illustrate this:

On the left board, the falling piece’s (that is, the top left corner of the falling piece’s) XY coordinates are \( (2, 3) \) on the board. But the boxes inside the falling piece’s coordinate system have their own coordinates. To find the "board" coordinates of these pieces, we just have to add the "board" coordinates of the falling piece’s top left box and the "piece" coordinates of the boxes.

On the left board, the falling piece’s boxes are at the following "piece" coordinates:

\[ (2, 2), (3, 2), (1, 3), (2, 3) \nonumber \]

When we add the \( (2, 3) \) coordinate (the piece’s coordinates on the board) to these coordinates, it looks like this:

\[ (2 + 2, 2 + 3), (3 + 2, 2 + 3), (1 + 2, 3 + 3), (2 + 2, 3 + 3) \nonumber \]

After adding the \( (2, 3) \) coordinate the boxes are at the following "board" coordinates:

\[ (4, 5), (5, 5), (3, 6), (4, 6) \nonumber \]

And now that we can figure out where the falling piece’s boxes are as board coordinates, we can see if they overlap with the landed boxes that are already on the board. The nested `for`

loops on lines 7 [396] and 8 [397] go through each of the possible coordinates on the falling piece.

We want to check if a box of the falling piece is either off of the board or overlapping a box on the board. (Although one exception is if the box is above the board, which is where it could be when the falling piece just begins falling.) Line 9 [398] creates a variable named `isAboveBoard`

that is set to `True`

if the box on the falling piece at the coordinates pointed to be x and y is above the board. Otherwise it is set to `False`

.

The `if`

statement on line 10 [399] checks if the space on the piece is above the board or is blank. If either of those is `True`

, then the code executes a continue statement and goes to the next iteration. (Note that the end of line 10 [399] has `[y][x]`

instead of `[x][y]`

. This is because the coordinates in the `PIECES`

data structure are reversed. See the previous section, "Setting Up the Piece Templates").

The `if`

statement on line 12 [401] checks that the piece’s box is not located on the board. The `if`

statement on line 14 [403] checks that the board space the piece’s box is located is not blank. If either of these conditions are `True`

, then the `isValidPosition()`

function will return `False`

. Notice that these `if`

statements also adjust the coordinates for the `adjX`

and `adjY`

parameters that were passed in to the function.

If the code goes through the nested `for`

loop and hasn’t found a reason to return `False`

, then the position of the piece must be valid and so the function returns `True`

on line 16 [405].