2
\$\begingroup\$

I'd just like to ask if there's anyway to make the functions play_Game() or is_move_valid() anymore efficient. For example, using a loop of some sort, I haven't been able to figure out how and would like any help in trying to make those functions shorter.

#TicTacToe
import sys
rows=[[0,1,2],[3,4,5],[6,7,8]]
columns =[[0,3,6],[1,4,7],[2,5,8]]
diagonals=[[0,4,8],[2,4,6]]
count=0

def display_Grid():
    print("\n")
    print(grid[0][0], "|" , grid[0][1], "|" , grid[0][2])
    print("---------")
    print(grid[1][0], "|", grid[1][1], "|", grid[1][2])
    print("---------")
    print(grid[2][0], "|", grid[2][1], "|", grid[2][2])

def check_turn():
    if count%2 == 0:
        player_1()
    else:
        player_2()

def game_over(shape):
    try:
        sys.exit()

    except SystemExit:
        print(shape," won")
        win = True
        quit()
def player_1():
    p_number = ("Player one")
    p_shape = p1
    play_Game(p_number, p_shape)

def player_2():
    p_number = ("Player two")
    p_shape = p2
    play_Game(p_number, p_shape)

def checkDraw():
    try:
        if count==10:
            sys.exit()

    except SystemExit:
        print("Draw")
        quit()

def check_win(shape):
    directions=[rows,columns,diagonals]
    for i in directions:
        for j in i:
            status = map(lambda val: True if grid[int(val/3)][val%3] == shape else False, j)
            if all(status):
                return True

    return False


def play_Game(p_number, p_shape):
    global count
    checkDraw()
    print(p_number, ",enter where you would like to move on the grid: ")
    move = int(input(""))
    if move in (1, 2, 0):
        valid = is_move_valid(move)
        if valid:
            count+=1
            grid[0][move] = p_shape
            display_Grid()
        else:
            check_turn()
    elif move in (3, 4, 5):
        valid = is_move_valid(move)
        if valid:
            count+=1
            move2 = move-3
            grid[1][move2] = p_shape
            display_Grid()
        else:
            check_turn()
    elif move in (6, 7, 8):
        valid = is_move_valid(move)
        if valid:
            count+=1
            move2 = move-6
            grid[2][move2] = p_shape
            display_Grid()
        else:
            check_turn()

    else:
        print("Enter one of the numbers visible on the grid: ")

    if check_win(p_shape):
        game_over(p_shape)
    else:
        None
    if count%2 == 0:
        player_1()
    else:
        player_2()

def is_move_valid(move):
    print(move)
    if move in(0, 1, 2):
        if grid[0][move] in ("X", "O"):
            print("This place has already been picked...")
            return False
        else:
            None
    elif move in(3, 4, 5):
        move2 = move-3
        if grid[1][move2] in ("X", "O"):
            print("This place has already been picked...")
            return False
        else:
              None
    elif move in(6, 7, 8):
        move2 = move-6
        if grid[2][move2] in ("X", "O"):
            print("This place has already been picked...")
            return False
        else:
              None

    return True

win = False    
grid = [[0,1,2],[3,4,5],[6,7,8]]
p_number = (" ")
display_Grid()
choose = input("Player one, would you like to be 'X' or 'O'?: ")
while win != True:
    try:
         if choose == "X":
             p2 = "O"
             p1 = choose
             player_1()
         elif choose == "O":
             p1 = "O"
             p2 = "X"
             player_1()
         else:
             print("Enter x or o: ")
             choose = input("Player 1, would you like to be 'X' or 'O'?: ")
    except ValueError:
        print("Please enter X OR O")
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Divide Logic and User Intereaction

Why should a function to decide if a move is valid print to the screen? What if you want to change the message? Will you look inside a logic function to change a user-interface message?

I like to keep as many as possible of my functions "pure" so that they only make a calculation and return a result and build a thin interaction skin over it.

Long story short, is_move_valid should not print anything.

Simplification

As far as simplification is concerned, you can just flatten the board, and the function becomes:

def is_move_valid(move):
    return flatten(board)[move] not in ("X", "O")
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.