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
Edward
67.2k4 gold badges120 silver badges284 bronze badges
asked Mar 6, 2019 at 8:30
\$\endgroup\$
2
  • \$\begingroup\$ search for tic tac toe python on code review, and you will already find tens of tips on improving the code \$\endgroup\$ Commented Mar 6, 2019 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\$ Commented Mar 6, 2019 at 8:54

1 Answer 1

1
\$\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.

answered Mar 6, 2019 at 13:09
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.