Author Topic: [Python] Tic Tac Toe  (Read 2314 times)

0 Members and 10 Guests are viewing this topic.

Offline Bugogy

  • /dev/null
  • *
  • Posts: 5
  • Cookies: 1
    • View Profile
[Python] Tic Tac Toe
« on: 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!

Code: (python) [Select]
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()

« Last Edit: May 24, 2013, 01:03:18 am by Bugogy »

Offline DeXtreme

  • Peasant
  • *
  • Posts: 95
  • Cookies: 8
  • I was there and you never knew.
    • View Profile
    • My Designs
Re: [Python] Tic Tac Toe
« Reply #1 on: May 23, 2013, 05:35:49 am »
Nice.This was one of my first projects too.Even uploaded the code somewhere around here ;D .

Offline pyte

  • Peasant
  • *
  • Posts: 79
  • Cookies: -7
    • View Profile
Re: [Python] Tic Tac Toe
« Reply #2 on: May 23, 2013, 06:18:35 am »
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

If you don't go into the tiger's cave, how will you get the cub?

Offline techb

  • Soy Sauce Feeler
  • Global Moderator
  • King
  • *
  • Posts: 2350
  • Cookies: 345
  • Aliens do in fact wear hats.
    • View Profile
    • github
Re: [Python] Tic Tac Toe
« Reply #3 on: May 23, 2013, 07:04:47 am »
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.
>>>import this
-----------------------------

Offline pyte

  • Peasant
  • *
  • Posts: 79
  • Cookies: -7
    • View Profile
Re: [Python] Tic Tac Toe
« Reply #4 on: May 23, 2013, 07:57:39 am »
A proper intro would also be welocomed in the Member Introduction board.
Never crossed my mind. :)
Thanx





If you don't go into the tiger's cave, how will you get the cub?

Offline Bugogy

  • /dev/null
  • *
  • Posts: 5
  • Cookies: 1
    • View Profile
Re: [Python] Tic Tac Toe
« Reply #5 on: May 23, 2013, 08:24:25 am »
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  :)

Offline Kulverstukas

  • Administrator
  • Zeus
  • *
  • Posts: 6627
  • Cookies: 542
  • Fascist dictator
    • View Profile
    • My blog
Re: [Python] Tic Tac Toe
« Reply #6 on: May 23, 2013, 05:41:39 pm »
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". There is a project I made using urwid, released here. 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.

Offline madara

  • Serf
  • *
  • Posts: 23
  • Cookies: 3
    • View Profile
Re: [Python] Tic Tac Toe
« Reply #7 on: May 25, 2013, 05:21:43 pm »
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 ;)
« Last Edit: May 26, 2013, 10:17:00 am by Kulverstukas »

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: [Python] Tic Tac Toe
« Reply #8 on: June 02, 2013, 09:12:17 pm »
That code is pretty bad.
Look at this:

Code: (Python) [Select]
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:

Code: [Select]
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?
« Last Edit: June 02, 2013, 09:35:59 pm by Deque »

Offline Bugogy

  • /dev/null
  • *
  • Posts: 5
  • Cookies: 1
    • View Profile
Re: [Python] Tic Tac Toe
« Reply #9 on: June 04, 2013, 10:25:33 pm »
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.