EvilZone
Programming and Scripting => Scripting Languages => : Bugogy May 23, 2013, 02:58:38 AM
-
Hello Evilzone! First time poster, short time lurker here. I have recently started digging into programming and went with Python! Just for educational purposes on my behalf, I want to post this Tic Tac Toe game I have been working on! I am open to any suggestions to improve what may seem like redundant code. Thanks in advance!
from random import randint
import time
import os #For pretty color reasons
raw_input("Welcome to tic-tac-toe! Press Entert to start:")
board = []
numTries, player_wins, computer_wins = 0, 0, 0
def makeBoard():
global board
for i in range(0, 10):
board.append("[ ]")
def printBoard():
#Print the game
global board
print board[1], board[2], board[3]
print board[4], board[5], board[6]
print board[7], board[8], board[9]
def move():
#Prompt the player to make a move
os.system("color a")
global numTries
numTries = 0
#Take input and check if spot is available
try:
x = int(raw_input("\nIt's your turn(1-9):"))
if not board[x] == "[X]" and not board[x] == "[O]":
board[x] = "[X]"
else:
print "That spot is already chosen."
move()
except:
print("You must have screwed up.")
move()
printBoard()
checkForWin()
time.sleep(.5)
computeMove()
def computeMove():
#Generate random spot on the board, make move if available
os.system("color c")
global numTries
global board
numTries += 1
selection = randint(1, 9)
if not board[selection] == "[X]" and not board[selection] == "[O]":
board[selection] = "[O]"
print ("\nComputer has chosen.")
#AI - Place move against you -- each row has 3 combinations
#Only executes if random move is unsuccessful on first try
#Row 1
elif board[1] == "[X]" and board[2] == "[ ]" and board[3] == "[X]":
board[2] = "[O]"
elif board[1] == "[ ]" and board[2] == "[X]" and board[3] == "[X]":
board[1] = "[O]"
elif board[1] == "[X]" and board[2] == "[X]" and board[3] == "[ ]":
board[3] = "[O]"
#Row 2
elif board[4] == "[X]" and board[5] == "[ ]" and board[6] == "[X]":
board[5] = "[O]"
elif board[4] == "[ ]" and board[5] == "[X]" and board[6] == "[X]":
board[4] = "[O]"
elif board[4] == "[X]" and board[5] == "[X]" and board[6] == "[ ]":
board[6] = "[O]"
#Row 3
elif board[7] == "[X]" and board[8] == "[ ]" and board[9] == "[X]":
board[8] = "[O]"
elif board[7] == "[ ]" and board[8] == "[X]" and board[9] == "[X]":
board[7] = "[O]"
elif board[7] == "[X]" and board[8] == "[X]" and board[9] == "[ ]":
board[9] = "[O]"
#Diagonal 1
elif board[1] == "[X]" and board[5] == "[ ]" and board[9] == "[X]":
board[5] = "[O]"
elif board[1] == "[ ]" and board[5] == "[X]" and board[9] == "[X]":
board[1] = "[O]"
elif board[1] == "[X]" and board[5] == "[X]" and board[9] == "[ ]":
board[9] = "[O]"
#Diagonal 2
elif board[3] == "[X]" and board[5] == "[ ]" and board[7] == "[X]":
board[5] = "[O]"
elif board[3] == "[ ]" and board[5] == "[X]" and board[7] == "[X]":
board[3] = "[O]"
elif board[3] == "[X]" and board[5] == "[X]" and board[7] == "[ ]":
board[7] = "[O]"
else:
if numTries > 20:
raw_input("It's a cat's game!")
restart()
computeMove()
printBoard()
checkForWin()
move()
def checkForWin():
#Define win combinations - 8 possible for each X and O
global board
global numTries
global player_wins
global computer_wins
if board[1] == "[X]" and board[2] == "[X]" and board[3] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[4] == "[X]" and board[5] == "[X]" and board[6] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[7] == "[X]" and board[8] == "[X]" and board[9] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[1] == "[X]" and board[4] == "[X]" and board[7] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[2] == "[X]" and board[5] == "[X]" and board[8] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[3] == "[X]" and board[6] == "[X]" and board[9] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[1] == "[X]" and board[5] == "[X]" and board[9] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
if board[3] == "[X]" and board[5] == "[X]" and board[7] == "[X]":
raw_input("You win!")
player_wins += 1
restart()
#Computer's combinations
if board[1] == "[O]" and board[2] == "[O]" and board[3] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[4] == "[O]" and board[5] == "[O]" and board[6] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[7] == "[O]" and board[8] == "[O]" and board[9] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[1] == "[O]" and board[4] == "[O]" and board[7] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[2] == "[O]" and board[5] == "[O]" and board[8] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[3] == "[O]" and board[6] == "[O]" and board[9] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[1] == "[O]" and board[5] == "[O]" and board[9] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[3] == "[O]" and board[5] == "[O]" and board[7] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
def whoStarts():
#If even number you start, odd number computer starts
i = randint(0, 10)
if i % 2 == 0:
move()
else:
computeMove()
def restart():
#Restart the game
global board
global player_wins
global computer_wins
os.system("color f")
board = []
print "\nYour score: ", player_wins
print "Computer score: ", computer_wins
raw_input("\n~~~~~~~~~~~~~~~~~~~~~~~~~Press Enter to play again!~~~~~~~~~~~~~~~~~~~~~~~~~")
makeBoard()
whoStarts()
if __name__ == "__main__":
makeBoard()
whoStarts()
-
Nice.This was one of my first projects too.Even uploaded the code somewhere around here ;D .
-
First, i welcome you to the evilzone Family not like the "dad" here but a bro.
Python for sure will be a good language for you as you sail along and learn more on the same, i also admit am impressed to see the Tic Tac Toe as your first program in python. ;D
-
Good use of functions. Next step would be wrap it into a class, and maybe add some flare to it like colors. Curses could help you there if you wanna keep it terminal based, or maybe step it up to GUI.
A proper intro would also be welocomed in the Member Introduction board.
-
A proper intro would also be welocomed in the Member Introduction board.
Never crossed my mind. :)
Thanx
-
Thank you guys for the positive feedback! Also, thank you for introducing Curses to me, that looks really interesting to work with. I'll get right on that introduction :)
-
Nice code and well structured too, I can't think of anything to point out. For Curses you could check out a wrapper called "Urwid (http://excess.org/urwid/)". There is a project I made using urwid, released here (http://evilzone.org/evilzone-releases/d0xbase/). You could check it out what is it capable of. I find urwid to be much more understandable than Curses itself.
But keep in mind that Curses is a linux only feature, but it can run on windows with Cygwin.
-
as first script wow! :)
some little advice for less redundancy in code : list is mutable object -->
then , within functions, You can avoid (but in Python: You must!! ;D) declare it as global ;
hereafter You'll 'update' it in a pythonic OOP way ;)
-
That code is pretty bad.
Look at this:
if board[1] == "[O]" and board[2] == "[O]" and board[3] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[4] == "[O]" and board[5] == "[O]" and board[6] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[7] == "[O]" and board[8] == "[O]" and board[9] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[1] == "[O]" and board[4] == "[O]" and board[7] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[2] == "[O]" and board[5] == "[O]" and board[8] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[3] == "[O]" and board[6] == "[O]" and board[9] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[1] == "[O]" and board[5] == "[O]" and board[9] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
if board[3] == "[O]" and board[5] == "[O]" and board[7] == "[O]":
raw_input("You LOSE!")
computer_wins += 1
restart()
You have a shitload of code repetition. This is not necessary, nor is it in any way good.
You can reduce the lines of code to 1/2 of what you have by now, maybe even more.
If you are interested in improvement, I can show you by example how to do this.
The code is not flexible. I.e. you can't use your checkForWin() function for boards that use a different representation. You mix up logic and UI (also not flexible, no separation of concerns which is one of the most important design principles for good code).
You also have too many global variables. Avoid them.
After playing around with it I got into this situation:
Computer has chosen.
[X] [O] [O]
[O] [X] [X]
[O] [X] [O]
sh: 1: color: not found
It's your turn(1-9):1
That spot is already chosen.
Every spot is chosen, nevertheless I am asked for my input. No way out. This is even worse, because of your exception handling, which makes it impossible to use Ctrl+D to quit the program. I had to kill -9 it.
Do not catch all exceptions, but only the ones you need.
Also: Did you know that the player can make a legit move in index 0?
-
Thank you for the response! I'll look into the issues you addressed, try to clean up the repetition, and reduce the usage of global variables. I highly appreciate your feedback and will take this opportunity to learn from my mistakes.