Tic Tac Toe "Cats Game"/End Game I have made my first game in Python.

My program can determine when there is a winner, however I am unsure what to do if the board is full and there is NO winner (a cats game).

import cTurtle
import random
import sys

def DrawTicTacToeBoard(t):
    #Vertical Lines of board
    t.pensize(3)
    t.up()
    t.goto(.5,-.5)
    t.down()
    t.goto(.5,2.5)
    t.up()
    t.goto(1.5,-.5)
    t.down()
    t.goto(1.5,2.5)
    #Horizontal Lines of board
    t.up()
    t.goto(-.5,.5)
    t.down()
    t.goto(2.5,.5)
    t.up()
    t.goto(-.5,1.5)
    t.down()
    t.goto(2.5,1.5)

def flipPlayer(currentPlayer):
    if currentPlayer==0:
        currentPlayer=1
    else:
        currentPlayer=0
    return currentPlayer

def drawWhiteBox(t,x,y):
    t.up()
    t.goto(x-.25,y+.25)
    t.down()
    t.color("white")
    t.begin_fill()
    for i in range(4):
        t.forward(.8)
        t.right(90)
    t.end_fill()
    t.color("black")

def drawMarker(t,currentPlayer,markerList,move,boardLoL):
    by=int(move[0:1])
    bx=int(move[2:])
    y=by+(.22)
    x=bx-(.15)
    drawWhiteBox(t,x,y)
    t.up()
    t.goto(x,y)
    boardLoL[by][bx]=markerList[currentPlayer]
    t.write(markerList[currentPlayer],move=False,align="left",font=("Arial",48,"normal"))

def getValidMove(validMoveList,markerList,currentPlayer,boardLoL):
    move = ""
    while move not in validMoveList:
        move = input("Enter location to place your marker " + markerList[currentPlayer] + ", or EXIT to end game =&gt; ")
        if move=="EXIT":
            sys.exit()
        if move in validMoveList:
            by=int(move[0])
            bx=int(move[2:])
            if boardLoL[by][bx]=="":
                return move
            else:
                print("Location already occupied")
                move=""

def gameWon(b):
    for row in range(3):
        if b[row][0]==b[row][1] and b[row][1]==b[row][2] and b[row][0]!="":
            print("Way to go",b[row][0])
            return b[row][0]
    for column in range(3):
        if b[0][column]==b[1][column] and b[1][column]==b[2][column] and b[0][column]!="":
            print("Way to go",b[column][0])
            return b[0][column]
    for diag in range(2):
        if b[0][0]==b[1][1] and b[1][1]==b[2][2] and b[0][0]!="":
            print("Way to go",b[0][0])
            return b[0][0]
        if b[2][0]==b[1][1] and b[1][1]==b[0][2] and b[2][0]!="":
            print("Way to go",b[2][0])
            return[2][0]



    return ""

def boardIsFull(boardLoL):
    return False




def main():
    boardLoL=[["","",""],["","",""],["","",""]]
    markerList=["O","X"]
    validMoveList=["0,0","0,1","0,2","1,0","1,1","1,2","2,0","2,1","2,2"]
    joe=cTurtle.Turtle()
    joe.setWorldCoordinates(-2,3,4,-1)
    joe.ht()
    currentPlayer=random.randint(0,1)
    DrawTicTacToeBoard(joe)
    move = ""
    while boardIsFull(boardLoL)==False and gameWon(boardLoL)=="" and move !="EXIT":
        move = getValidMove(validMoveList,markerList,currentPlayer,boardLoL)
        drawMarker(joe,currentPlayer,markerList,move,boardLoL)
        currentPlayer=flipPlayer(currentPlayer)
    gameWon(boardLoL)
    boardIsFull(boardLoL)

main()
import cTurtle
import random
import sys



Excellent!  Many people use wildcard imports, (from &lt;module&gt; import *), but you didn't.  You even alphabetized your imports.  Keep up the good work.

PEP 8, the Python style guide, has this to say in the Function Names section:


  Function names should be lowercase, with words separated by underscores as necessary to improve readability.
  
  mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility.


That means that DrawTicTacToeBoard would be draw_tic_tac_toe_board, for example.

Your spacing does not comply with PEP 8.  Specifically:


  Always surround these binary operators with a single space on either side: assignment (=), augmented assignment (+=,-= etc), comparisons (==,&lt;,&gt;,!=,&lt;&gt;,&lt;=,&gt;=,in,not in,is,is not), Booleans (and,or,not).

#Vertical Lines of board
t.pensize(3)
t.up()
t.goto(.5,-.5)
t.down()
t.goto(.5,2.5)
t.up()
t.goto(1.5,-.5)
t.down()
t.goto(1.5,2.5)



I realize that you want to save characters, but -.5 is a little hard to read.  It almost looks like the - is one argument and 5 is another argument.  The extra 0 between the two would greatly improve readability.  Speaking of saving characters, you could use a for loop ... probably.  I haven't come up with anything that I really like, though.  You should also consider a different name for your argument.  Perhaps turtle would be more descriptive.


def flipPlayer(currentPlayer):
    if currentPlayer==0:
        currentPlayer=1
    else:
        currentPlayer=0
    return currentPlayer



This function is included in two rules mentioned above, but I mention it here because there is a much easier way to do it:

def flip_player(current):
    return (current + 1) % 2


Read more about the modulus operator and when to use it.


for i in range(4):
    t.forward(.8)
    t.right(90)



Again, you should be using a more descriptive name, but I brought up the for loop because you use i as your variable name.  There isn't anything wrong with using it, but in cases where the variable is not used, it is common practice in Python to use _ as the variable name.  It just makes it a little more obvious that it is an unused variable.


move = input("Enter location to place your marker " + markerList[currentPlayer] + ", or EXIT to end game =&gt; ")



That line is 110 characters not including indentation.  PEP 8 says:


  Limit all lines to a maximum of 79 characters.


Perhaps it would be better to define a template and format it in the loop:

template = "Enter location to place your marker {}, or EXIT to end game =&gt; "
while move not in valid_move_list:
    move = input(template.format(marker_list[current_player]))
    ...


I would also change how you check your conditions in the while loop.  Here is what I would do:

while True:
    move = input(template.format(marker_list[current_player]))
    if move == "EXIT":
        sys.exit()
    elif move in valid_move_list:
        y, x = map(int, move.split())
        if not boardLoL[y][x]:
            return move
        else:
            print("Location already occupied")
    else:
        print("Invalid move")


There is no need for while to be checking anything since you account for all cases inside.  I also added an else: so that the user would know why he was being asked again for input.


def gameWon(b):
    for row in range(3):
        if b[row][0]==b[row][1] and b[row][1]==b[row][2] and b[row][0]!="":
            print("Way to go",b[row][0])
            return b[row][0]
    for column in range(3):
        if b[0][column]==b[1][column] and b[1][column]==b[2][column] and b[0][column]!="":  
            print("Way to go",b[column][0])
            return b[0][column]
    for diag in range(2):
        if b[0][0]==b[1][1] and b[1][1]==b[2][2] and b[0][0]!="":
            print("Way to go",b[0][0])
            return b[0][0] 
        if b[2][0]==b[1][1] and b[1][1]==b[0][2] and b[2][0]!="":
            print("Way to go",b[2][0])
            return[2][0]



You can simplify that to this:

def game_won(board):
    for row in board:
        if len(set(row)) == 1:
            return row[0]
    for column in zip(*board):
        if len(set(column)) == 1:
            return column[0]
    for diag in range(2):
        ...


I would do all of the printing outside of the function.  In your main() function, it would be like this:

print(game_won(boardLoL))


instead of:

game_won(boardLol)


I'm not crazy about the diagonal searching, but I can't think of anything better at the moment.  Maybe it's because I've been awake for ... yawn


return[2][0]



I don't think that's what you meant.  Perhaps, return b[2][0]


def boardIsFull(boardLol):
    return False



Haven't added it yet, huh?  Maybe this:

def board_is_full(board):
    return all(all(row) for row in board)


Yeah, nifty.  You see, all(row) makes sure that each item in row is a Truthy value.  Any non-empty string is Truthy, so if any of the cells in that row is empty, all(row) will return False.  Since I am running all() on each of those all() calls, it returns False if any cell in the board is empty, but True otherwise.


while boardIsFull(boardLoL)==False and gameWon(boardLoL)=="" and move !="EXIT":



Any condition is checking a boolean.  That is, if ...: is seeing if ... is True.  Using if ... == True: is redundant because you could have just used if ...:.  Consequently, if ... == False: is redundant because you could have used if not ...:  You can simplify that line like this:

while not board_is_full(boardLoL) and not game_won(boardLoL) and move != "EXIT":


That line is one character too long for PEP 8.  I would suggest changing boardLoL to board in all places.  What is LoL doing there anyway?  Are you laughing as you type?

I hope I haven't sounded too harsh, but it's been a late night.