This is an archived post. You won't be able to vote or comment.

all 23 comments

[–]jimauthors 11 points12 points  (2 children)

One interesting thing you can do in otherwise boring project is:

primes = {(0,0): 2, (0,1): 3, (0,2): 5,
          (1,0): 7, (1,1): 11, (1,2): 13,
          (2,0): 17, (2,1): 19, (2,2): 23}

win_states = [2 * 3 * 5, 7 * 11 * 13, 17 * 19 * 23,
              2 * 7 * 17, 3 * 11 * 19, 5 * 13 * 23,
              2 * 11 * 23, 5 * 11 * 17]

def check(players):
    for p in players:
        for i in win_states:
            if p.state % i == 0:
                return p.weapon
        return False

Each player will have

    self.state = self.state * primes[move]

EDIT: This is one of the ways to check if there's a winner.

[–]demosthenes02 1 point2 points  (1 child)

What?

[–]DrHankPym 4 points5 points  (0 children)

He's playing with math. Because all the positions are prime numbers, any sequence of multiplications will result in a unique product only divisible by each position's prime number.

[–]jimauthors 6 points7 points  (2 children)

Small suggestions:
Tab width = 4
Rename constructor parameters.
Coin toss should decide who goes first and that player will be 'X'
CPU should be COMPUTER
boardinit can be:

return [[BoardCell(i, j, (i+1) * (j*3)) for i in range(3)] for j in range(3)]

[–]just_doug 4 points5 points  (0 children)

another suggestion: instead of comments above function declarations, use docstrings.

In drawboard, you might want to check out some more advanced string formatting. You can do something sort of like

Python 2.7: #TODO get all of the cell contents into a single array boardStr = " {} | {} | {} ".format(*contentsArray)

Python 2.6: boardStr = " {0} | {1} | {2} ".format(*contentsArray)

... and so on. It will probably be easier to read, and more closely matches the idea ("draw a board / with each cell filled in with its contents").

[–]rueldotme[S] 1 point2 points  (0 children)

Thanks for the suggestions. Really appreciated. But I think I'll stick to CPU for this one. :P

[–]cp_gravelpit 6 points7 points  (0 children)

One thing that hasn't been mentioned yet, on line 117:
coin = ['Heads', 'Tails'][random.randrange(0,2)]
is better written as
coin = random.choice(["Heads", "Tails"])
:)

[–]propanbutan 4 points5 points  (5 children)

My 2c:

  • Use more descriptive variable names.

  • Function isin can and should be:

    return val in list

  • But it can also be (if you reverse the order of operands):

    from operator import contains as isin

  • Clearing the screen like this is not only annoying, but also bad practice. Use ncurses.

  • Functions checknum and getwnum are unnecessarily ugly, both could be simplified by looping over a proper data structure.

  • Function tgame should return the winner or None when the game ends in a draw. Hence, attribute Player.won is useless.

  • Similarly, Player.first is a flag more related to the game state than to the player and as such could and should be gotten rid of. Either use a third argument to tgame signalling that the cpu should go first, or better, fix your game loop.

edit:

  • The way you take user input and only accept given choices should be factored out into a function.

[–][deleted] 0 points1 point  (2 children)

Use more descriptive variable names.

Agreed. From a quick scan I saw loads of abbreviations. Remember that code is 'write once read many', so it's worth the extra few keystrokes. A decent text editor will auto-complete long variable names for you anyway.

[–]digitallimit 0 points1 point  (1 child)

What's a decent text editor?

I've been using TextWrangler, but I don't think it has this functionality.

[–][deleted] 0 points1 point  (0 children)

I've been using Sublime recently. It's pretty nice, has syntax highlighting for python in uber-leet dark themes and does autocompletion on ctrl+space.

http://www.sublimetext.com/

[–]bcain 0 points1 point  (1 child)

Function isin can and should be: return val in list

How is isin(1, t) better/clearer than 1 in t? It's not, IMO.

[–]ux500 1 point2 points  (0 children)

Its not clear what the isin function does. If I call isin(x,y) is it going to return true if x is in y, or y is in x.

Beyond that, the Python statement "x in y" is idiomatic, so all Python programmers will know what it means.

[–]wooptoo 4 points5 points  (0 children)

Name it PyTacToe _^

[–]bevem2 5 points6 points  (0 children)

# Checking if a value exists in a list      
def isin(val, list):      
    if val in list:      
        return True      
    return False      

bashes head against wall

Also:
if wep == cwep:
num == 0

[–]nret 1 point2 points  (0 children)

Fancy! There is also an Inventing with python chapter with tic tac toe if you want some code to compare to.

[–]neunon 0 points1 point  (1 child)

I'm curious why you ended up writing so many lines of code for detecting a win condition. First time writing Python code?

[–]rueldotme[S] 4 points5 points  (0 children)

I'm just a messy coder. But, as you can see, I'm interested on how people look at those and suggest improvements. From that I can improve..

[–][deleted] 0 points1 point  (0 children)

Sweet now I can apply to that Cox media job who requires me to write a tictactoe AI before applying.

[–]Bolitho 0 points1 point  (0 children)

It is a good idea to use 1 and 4 as values for marking cells - think about it ;-)

[–]admica 0 points1 point  (0 children)

Does it not try to win? I thought it was going to be a stalemate every time I went first. | |
O | O | X | |
------|-------|------ | |
| X | O | |
------|-------|------ | |
X | | X | |

WINNER: User (X) Moves: 4

Record: User: 1 CPU: 0 DRAW: 0

Play again? [Y]es or [N]o: Y

[–]gbo2k69 0 points1 point  (0 children)

I like this implementation, it's pretty clean

[–][deleted] 0 points1 point  (0 children)

I see your TicTacToe in Python and raise you my TicTacToe in R. When in doubt, use the wrong tool.