Jump to content
  • Advertisement
Sign in to follow this  
steveworks

TicTacToe conditional help

This topic is 3655 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am a begginning python programmer and I need some help with a TicTacToe program I am trying to write. My biggest issue is my innability to make a specific winner. I cannot for the life of me make a way to check if either player wins that works. Right now I only have a broken function that is supposed to check if player 1 'X' wins. here is my code. I couldn't figure out how to make it go into a seperate piece that scrolls down like other people.
b = ['_','_','_','_','_','_','_','_','_']
w = 1
check = 0
def printboard():
        print '[',b[0],'][',b[1],'][',b[2],']'  '       [ 1 ][ 2 ][ 3 ]'
        print '[',b[3],'][',b[4],'][',b[5],']'  '       [ 4 ][ 5 ][ 6 ]'
        print '[',b[6],'][',b[7],'][',b[8],']'  '       [ 7 ][ 8 ][ 9 ]'

def plr1():
        s = int(raw_input('player 1 make your move'))
        b[s - 1] = 'X'

def plr2():
        s = int(raw_input('player 2 make your move'))
        b[s - 1] = 'O'

def winner1():
        check = b[0] + b[1] + b[2]
        checking1()
        check = b[3] + b[4] + b[5]
        checking1()
        check = b[6] + b[7] + b[8]
        checking1()
        check = b[0] + b[3] + b[6]
        checking1()
        check = b[1] + b[4] + b[7]
        checking1()
        check = b[2] + b[5] + b[8]
        checking1()
        check = b[0] + b[4] + b[8]
        checking1()
        check = b[6] + b[4] + b[2]
        checking1()
    
def checking1():
        if check == 'XXX':
            print 'player 1 is the winner'
            w = 2
          
        
while True:
        printboard()
        plr1()
        winner1()
        if w = = 2:
            break
        printboard()
        plr2()
        if w = = 2:
             break



If someone can point me to a place that gives ideas on ways that I can make an efficient working conditional please post. Any help on making this work is highly appreciated. If anyone needs anymore information I'll gladly post it. [Edited by - steveworks on June 17, 2008 10:26:07 PM]

Share this post


Link to post
Share on other sites
Advertisement
Use the [ source ] [ /source ] tags (without spaces) to format your code, python is very hard to read without the indentation :)

Share this post


Link to post
Share on other sites
I think the problem is that in your functions your not telling python that your using a global variable

At the start of each function that uses check (or any other global variable) you need

global check (or global <variable name> )


Things like printboard probably work because when your reading from a variable python is smart enough to figure out your referring to the global variable. In winner1() however python doesnt know whether something like

check = b[0] + b[1] + b[2]

is assigning to a global variable or creating a local variable within the function and assign to that. By default it will create the local variable which is destroyed at the end of the function when it goes out of scope, leaving your global variable unchanged.

Share this post


Link to post
Share on other sites
In programming, the normal way we pass information between functions is to pass it in via the parameters, and out via the return value. This is why they're called functions: they calculate some function of the input, and return the output. Just as in mathematics.

When we write code, one of the major goals is to keep things organized. One aspect of this is making sure that functions do all the work that they're supposed to, and only that work. Usually, we can figure out what work is appropriate from the function name.

Let's analyze the existing code. In checking1(), we want to receive the "check" value, and we determine as a result whether or not player 1 is the winner. Right now, we store that result by setting the 'w' global variable. Instead, we'll return a value. The key phrase "whether or not" tells us that we want to return a boolean: True meaning player 1 won, False meaning he didn't.

To receive the 'check' value, we'll use a parameter to the function. To call checking1(), we'll pass the appropriate value from winner1() each time. Notice how each time checking1() is called, 'check' (which is now a parameter, or 'argument' to checking1) takes on a different value - the one that was passed.

In winner1(), we want to check if any of the checking1() calls returned True. Fortunately for us, Python (assuming you have version 2.5 installed) provides a built-in function for this purpose, called 'any'. It takes a sequence of values, and returns if any of them are true (technically, if any of them evaluate as True when converted to bool). We can make a tuple out of all the checking1() results, call any(), and return that result. Then, the main loop makes use of that value.

The print statement to indicate the winner belongs in the main loop, not buried inside checking1(). Why? Well, first off, the organization point that I mentioned earlier (one guiding principle is that a function doesn't talk about the same value it calculates: that way, the calling function loses the flexibility to shut it up :) ), and second, because a player could simultaneously "win" in multiple ways at once, and we don't want to print the message multiple times if that happens.


b = ['_','_','_','_','_','_','_','_','_']

def printboard():
print '[',b[0],'][',b[1],'][',b[2],']' ' [ 1 ][ 2 ][ 3 ]'
print '[',b[3],'][',b[4],'][',b[5],']' ' [ 4 ][ 5 ][ 6 ]'
print '[',b[6],'][',b[7],'][',b[8],']' ' [ 7 ][ 8 ][ 9 ]'

def plr1():
s = int(raw_input('player 1 make your move'))
b[s - 1] = 'X'

def plr2():
s = int(raw_input('player 2 make your move'))
b[s - 1] = 'O'

def winner1():
# There are two sets of parentheses enclosing the
# checking1 calls here: the outer set is to make the function call,
# and the inner set is to create the tuple that is passed to any().
return any((
checking1(b[0] + b[1] + b[2]),
checking1(b[3] + b[4] + b[5]),
checking1(b[6] + b[7] + b[8]),
checking1(b[0] + b[3] + b[6]),
checking1(b[1] + b[4] + b[7]),
checking1(b[2] + b[5] + b[8]),
checking1(b[0] + b[4] + b[8]),
checking1(b[6] + b[4] + b[2])
))

def checking1(check):
return check == 'XXX'


while True:
printboard()
plr1()
if winner1():
print 'Player 1 is the winner'
break
# etc.



As an exercise, write the corresponding code to handle player 2. Then I can show you how to handle both players with the same set of functions, and also start explaining about how to give functions better names. :)

Share this post


Link to post
Share on other sites
Zahlman, you REALLY need to write a book and publish it. You'd get stinkingly rich by all the newbies and medium level programmers buying your book.

Share this post


Link to post
Share on other sites
I finished the code like you asked and I managed to get it to run well. My only problem is that I am able to overwrite other players choices. here is the source.


b = ['_','_','_','_','_','_','_','_','_']

def printboard():
print '[',b[0],'][',b[1],'][',b[2],']' ' [ 1 ][ 2 ][ 3 ]'
print '[',b[3],'][',b[4],'][',b[5],']' ' [ 4 ][ 5 ][ 6 ]'
print '[',b[6],'][',b[7],'][',b[8],']' ' [ 7 ][ 8 ][ 9 ]'

def plr1():
s = int(raw_input('player 1 make your move'))
b[s - 1] = 'X'

def plr2():
s = int(raw_input('player 2 make your move'))
b[s - 1] = 'O'

def winner1():
return any((
checking1(b[0] + b[1] + b[2]),
checking1(b[3] + b[4] + b[5]),
checking1(b[6] + b[7] + b[8]),
checking1(b[0] + b[3] + b[6]),
checking1(b[1] + b[4] + b[7]),
checking1(b[2] + b[5] + b[8]),
checking1(b[0] + b[4] + b[8]),
checking1(b[6] + b[4] + b[2])
))

def winner2():
return any((
checking2(b[0] + b[1] + b[2]),
checking2(b[3] + b[4] + b[5]),
checking2(b[6] + b[7] + b[8]),
checking2(b[0] + b[3] + b[6]),
checking2(b[1] + b[4] + b[7]),
checking2(b[2] + b[5] + b[8]),
checking2(b[0] + b[4] + b[8]),
checking2(b[6] + b[4] + b[2])
))
def checking1(check):
return check == 'XXX'

def checking2 (check):
return check == 'OOO'

while True:
printboard()
plr1()
if winner1():
printboard()
print 'player 1 is the winner'
break
printboard()
plr2()
if winner2():
printboard()
print 'player 2 is the winner'
break

[\source]

Share this post


Link to post
Share on other sites
I don't know python at all, but you just need to add some checking on your input.

You can check the array location (the input from the player) is still '_', if it is, then process the input, otherwise, loop back until the player gives you a valid input. That will fix your overwrite issue.

The other thing you will want to check is if the board is full then there is a draw.

Great job so far!

Share this post


Link to post
Share on other sites
Ok, now you are using return values.

The second thing is to look at what you pass into the functions. Look at winner1 and winner2 (together with checking1 and checking2). Aren't they very-very similar? Now if only we could remove one of them by passing the only thing that makes them different as a function argument...

Now, plr1 and plr2 are also very similar. And if you are planning to add some checks to them, wouldn't it also be nice if it was one and the same function?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!