1
\$\begingroup\$

I am really new to programming, and I made this simple tic tac toe app in python and C++. Please tell me what can be improved

Code:

import os

toDraw = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
turnsPlayed = 0
playerTurn = 1


def reset():
    global turnsPlayed
    turnsPlayed = 0
    global toDraw
    toDraw = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
    global playerTurn
    playerTurn = 1


def reDrawBoard(gameOver):
    print(f"TIC TAC TOE\nPlayer one in X and Player two is O\n"
          f"\n   |   |   \n "
          f"{toDraw[0]} | {toDraw[1]} | {toDraw[2]} "
          f"\n___|___|___\n   |   |   \n "
          f"{toDraw[3]} | {toDraw[4]} | {toDraw[5]} "
          f"\n___|___|___\n   |   |   \n "
          f"{toDraw[6]} | {toDraw[7]} | {toDraw[8]} "
          f"\n   |   |   \n\n")
    if not gameOver:
        print(f"Player {str(playerTurn)}, Enter a number: ")

    #
    #  This prints (something similar to) -
    #
    #  TIC TAC TOE
    #  Player one is X and Player two is O
    #
    #     |   |
    #   1 | 2 | 3
    #  ___|___|___
    #     |   |
    #   4 | 5 | 6
    #  ___|___|___
    #     |   |
    #   7 | 8 | 9
    #     |   |
    #
    #  Player <1 or 2>, Enter a number:
    #


def checkIfWin():  # 0 - Game in progress; 1 - Player 1 wins; 2 - Player 2 wins
    one = toDraw[0]
    two = toDraw[1]
    three = toDraw[2]
    four = toDraw[3]
    five = toDraw[4]
    six = toDraw[5]
    seven = toDraw[6]
    eight = toDraw[7]
    nine = toDraw[8]

    if ((one == "X" and two == "X" and three == "X") or
            (one == "X" and four == "X" and seven == "X") or
            (one == "X" and five == "X" and nine == "X") or
            (seven == "X" and five == "X" and three == "X") or
            (seven == "X" and eight == "X" and nine == "X") or
            (three == "X" and six == "X" and nine == "X") or
            (four == "X" and five == "X" and six == "X") or
            (two == "X" and five == "X" and six == "X")):
        return 1
    elif ((one == "Y" and two == "Y" and three == "Y") or
            (one == "Y" and four == "Y" and seven == "Y") or
            (one == "Y" and five == "Y" and nine == "Y") or
            (seven == "Y" and five == "Y" and three == "Y") or
            (seven == "Y" and eight == "Y" and nine == "Y") or
            (three == "Y" and six == "Y" and nine == "Y") or
            (four == "Y" and five == "Y" and six == "Y") or
            (two == "Y" and five == "Y" and six == "Y")):
        return 2
    else:
        return 0

while True:
    clear = lambda : os.system('clear')
    reDrawBoard(False)
    toPlay = ""
    while True:
        try:
            toPlay = int(input())
            if toPlay > 9:
                print(f"\nInvalid Value. Try again.\nPlayer {str(playerTurn)}, Enter a number: ")
                continue
        except ValueError:
            print(f"\nInvalid Value. Try again.\nPlayer {str(playerTurn)}, Enter a number: ")
            continue

        try:
            if toPlay == int(toDraw[toPlay - 1]):
                break
        except ValueError:
            print(f"Position already occupied. Please try again.\nPlayer {str(playerTurn)}, Enter a number: ")
            continue
    if playerTurn == 1:
        toDraw[toPlay -1] = "X"
        turnsPlayed += 1
        playerTurn = 2
    else:
        toDraw[toPlay - 1] = "O"
        turnsPlayed += 1
        playerTurn = 1
    result = checkIfWin()
    if result == 1:
        reDrawBoard(True)
        response = input("PLAYER ONE WINS!!\nWould you like to play again? (Y/N): ").lower()
        if response != "y":
            #clear the screen
            exit()
        reset()
        continue
    if result == 2:
        reDrawBoard(True)
        response = input("PLAYER TWO WINS!!\nWould you like to play again? (Y/N): ").lower()
        if response != "y":
            #clear the screen
            exit()
        reset()
        continue
    if turnsPlayed == 9:
        reDrawBoard(True)
        response = input("DRAW!!\nWould you like to play again? (Y/N): ").lower()
        if response != "y":
            #clear the screen
            exit()
        reset()
        continue
\$\endgroup\$
  • \$\begingroup\$ search for tic tac toe python on code review, and you will already find tens of tips on improving the code \$\endgroup\$ – Maarten Fabré Mar 6 at 8:49
  • \$\begingroup\$ @MaartenFabré Thanks, but I don't really understand all of the code in the other questions :) . Will try to improve what I can. \$\endgroup\$ – Holyprogrammer Mar 6 at 8:54
2
\$\begingroup\$

One improvement I suggest is that in the beginning of your code, you could create a list of sets, in which each set would be a winning board configuration and then create two sets to record the players moves, like this:

winningMoves = [{1,2,3}, {1,4,7}, {1,5,9}, {7,5,3}, {7,8,9}, {3,6,9}, {4, 5, 6}, {2, 5, 8}]
playerOneMoves = set()
playerTwoMoves = set()

In the part that you check which player made the move, you would insert an "add(toPlay)" for both players, like this:

if playerTurn == 1:
    toDraw[toPlay -1] = "X"
    playerOneMoves.add(toPlay)
    turnsPlayed += 1
    playerTurn = 2

If I'm right, if you make things like this, you could reduce that great amount of code in checkIfWin() function to just:

def checkIfWin():  # 0 - Game in progress; 1 - Player 1 wins; 2 - Player 2 wins

    for move in winningMoves:
        if move.issubset(playerOneMoves):
            return 1
        elif move.issubset(playerTwoMoves):
            return 2
    return 0

The issubset() method will return True if move is a subset of the set that contains the player's moves. Which means it will return True if all elements in move are also in playerOneMoves or playerTwoMoves.

Also, instead of printing the board with format, you could develop a way of printing each part of the board individually inside a loop, for example:

for num in range(1,10):

    if num in list(playerOneMoves):
        print("[{}]".format('X'), end = '')
    elif num in list(playerTwoMoves):
        print("[{}]".format('O'), end = '')
    else:
        print("[{}]".format(num), end = '')
    if num%3 ==0:
        print("")

(Of course you could improve the style!)

The reason for that is that it would allow you to suppress toDraw completely and simplify your code even more.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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