Tic-Tac-Toe Help
Author |
Message |
Roman
|
Posted: Thu Jul 17, 2008 5:18 pm Post subject: Tic-Tac-Toe Help |
|
|
Hello.
I'm trying to make a single-player Tic-Tac-Toe game. While I'll have many more questions regarding AI later on, I have an optimization (I guess) question right now.
The code so far looks like so(below). This is just the graphic part of it, and I have two questions:
1) Is there any way to make multiple buttons with less code? Or is Copy/Paste the best it gets? If I have three buttons in a row, can I code it as one button and simply multiply it by three somehow?
2) I bound them all to handlers that would change the text from " " to "x" to "o" with the click of a mouse. So click once and you get "x", click again and you get "o". I have to redo the program now, and I'm wondering if/how I can bind ALL the buttons to ONE handler which would do the action, since the action is the same. I tried currying, but limited skill/understanding kinda got in the way I think there is a way, but I can't figure out how to make the handler work with ANY button.
e.g. I could have self.a1 = Button(self.row1, command=clicka1)
code: |
self.a1 = Button(self.row1, command = clicka1)
#goes to the handler
def clicka1(self):
if self.a1["text"] == " ":
self.a1["text"] == "x"
| etc.
But how do I make a universal click function that I could pass ALL my buttons to and which would do this for every one?
(This is the code of my GUI so far)
code: |
class GUI():
def __init__(self, parent):
#--------------------ROW 1-----------------------------------
self.row1 = Frame(parent)
self.row1.pack()
#--------------------ROW 1 Buttons---------------------------
self.a1 = Button(self.row1)
self.a1.configure(text=" ", background="green")
self.a1.pack(side=LEFT)
self.b1 = Button(self.row1)
self.b1.configure(text=" ", background="green")
self.b1.pack(side=LEFT)
self.c1 = Button(self.row1)
self.c1.configure(text=" ", background="green")
self.c1.pack(side=LEFT)
#--------------------ROW 2-----------------------------------
self.row2 = Frame(parent)
self.row2.pack()
#--------------------ROW 2 Buttons---------------------------
self.a2 = Button(self.row2)
self.a2.configure(text=" ", background="yellow")
self.a2.pack(side=LEFT)
self.b2 = Button(self.row2)
self.b2.configure(text=" ", background="yellow")
self.b2.pack(side=LEFT)
self.c2 = Button(self.row2)
self.c2.configure(text=" ", background="yellow")
self.c2.pack(side=LEFT)
#-------------------ROW 3------------------------------------
self.row3 = Frame(parent)
self.row3.pack()
#-------------------ROW 3 Buttons----------------------------
self.a3 = Button(self.row3)
self.a3.configure(text=" ", background="red")
self.a3.pack(side=LEFT)
self.b3 = Button(self.row3)
self.b3.configure(text=" ", background="red")
self.b3.pack(side=LEFT)
self.c3 = Button(self.row3)
self.c3.configure(text=" ", background="red")
self.c3.pack(side=LEFT)
root = Tk()
gui = GUI(root)
root.mainloop()
|
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
wtd
|
Posted: Thu Jul 17, 2008 6:20 pm Post subject: RE:Tic-Tac-Toe Help |
|
|
Use a list of lists of buttons. |
|
|
|
|
|
Roman
|
Posted: Wed Jul 23, 2008 2:22 pm Post subject: Re: Tic-Tac-Toe Help |
|
|
Well... with some help from my dad I went a different way, mostly cause I didn't get what you meant
I think I understand better now, but what I ended up with is the following:
code: |
from Tkinter import *
class TicTacButton (Button) :
def __init__(self, parent):
Button.__init__(self, parent, text = " ")
Button.bind(self,"<Button-1>", self.onClick)
def onClick(self, event):
bt = event.widget
if bt["text"] == " ":
bt["text"] = "x"
elif bt["text"] == "x":
bt["text"] = "o"
else:
bt["text"] = " "
class MyApp:
def __init__(self, parent):
self.Parent = root
for j in range (3) :
row = Frame(parent)
row.pack()
for i in range(3) : TicTacButton(row).pack(side=LEFT)
root = Tk()
myapp = MyApp(root)
root.mainloop()
|
What I want to do now is build a system that would record every click and the symbol - x or o - and send it to the AI. I'm not sure (actually, nearly clueless) how I'd go about doing that. For example, if I clicked on the center button, I would assign 2, 2, x to the click and send it off as the clickInfo variable. How could I do that without manually coding every button? I'll be struggling with it while I hope for a reply hehe. Thanks in advance.
EDIT:
Or would it be better for me to use some other widget that comes with a co-ordinate system? Buttons don't seem to be the best-suited thing for tic-tac-toe... |
|
|
|
|
|
Zeroth
|
Posted: Wed Jul 23, 2008 5:22 pm Post subject: Re: Tic-Tac-Toe Help |
|
|
Well, you need to create a list or structure of some sort to store the tictacbuttons in. As it is, they only exist with the Frame. To do this properly, would be to have a 2d list. A list... of lists. For each inner list in the outer list, the inner list corresponds to a row. See how it works yet?
It could be like...
code: |
grid= [[button1, button2, button3],
[button4, button5, button6],
[button7, button8, button9]]
|
Then, after a click, you could have the AI examine the grid of buttons. |
|
|
|
|
|
Roman
|
Posted: Thu Jul 24, 2008 1:40 am Post subject: Re: Tic-Tac-Toe Help |
|
|
Mhmm, I think I kind of understand the list of buttons, though maybe not exactly how to implement it. I'm still about two-three weeks into my programming career (with lots of distractions x_x)
But this is what I have now:
code: |
from Tkinter import *
import random
from XO_AI_V2 import TicTacAi
class TicTacButton (Button) :
def __init__(self, parent, x, y):
self.x = x
self.y = y
Button.__init__(self, parent, text = " ")
Button.bind(self,"<Button-1>", self.onClick)
def onClick(self, event):
bt = event.widget
if bt["text"] == " ":
bt["text"] = "x"
elif bt["text"] == "x":
bt["text"] = "o"
else:
bt["text"] = " "
if bt["text"] == "x" or "o":
turn = (self.x, self.y, bt["text"])
ai = TicTacAi()
ai = ai.isWin(turn)
if ai == True:
print "You win!"
else:
pass
class MyApp:
def __init__(self, parent):
self.Parent = root
for j in range (3) :
row = Frame(parent)
row.pack()
for i in range(3) :
TicTacButton(row, i, j).pack(side=LEFT)
self.row4 = Frame(parent)
self.row4.pack()
self.info = Button(self.row4, text="Info")
self.info.pack()
self.info.bind("<Button-1>", self.infoClick)
self.quit = Button(self.row4, text="Quit")
self.quit.pack()
self.quit.bind("<Button-1>", self.quitClick)
def infoClick(self, event):
print "\n"*100
print "-------------"
print "Information |"
print "-------------"
print
print "================================================================"
print "This is TIC-TAC-TOE"
print
print "So far, this is two-player only"
print
print 'Player One - "x"'
print 'Player Two - "o"'
print
print "To place an x, single click a button"
print "To place an o, double click a button"
print "The first one to get three x's or o's in a row wins!"
print
print 'Press "Quit" to leave the game'
print
print "Good luck!!!"
print "================================================================"
def quitClick(self, event):
self.Parent.destroy()
root = Tk()
myapp = MyApp(root)
root.mainloop()
|
Now it's time to replace my test-AI with real AI... we'll see how that goes haha. |
|
|
|
|
|
Zeroth
|
Posted: Thu Jul 24, 2008 8:50 am Post subject: Re: Tic-Tac-Toe Help |
|
|
Theres a few bugs in your code. For one, theres this:
code: |
if bt["text"] == "x" or "o":
|
It will always go off, since, if we put brackets around it, and see how Python sees it...
code: |
if (bt["text"]=="x") or ("o"):
|
Unfortunately, Python does not do what you would think it does and instead does the above. So, even if the square is blank, the if block still goes off. Not exactly what you want done.
There is also a second bug, subtle as well:
code: |
ai = TicTacAi()
ai = ai.isWin(turn)
if ai == True:
print "You win!"
else:
pass
|
This code should not be indented as part of the if block. It should be dedented, and will then always executed. Once you change the if conditional above, this block of code will only go off when the if conditional does so.
A few tips: look at your logic. Use brackets on your conditionals. Always be aware of what conditions will trigger a block of code. Basic stuff to experienced programmers, its the kind of stuff that trips new ones up.
But so far, looks like you're learning well. |
|
|
|
|
|
Roman
|
Posted: Sat Aug 02, 2008 11:30 pm Post subject: Re: Tic-Tac-Toe Help |
|
|
Thanks for the help, although I don't quite get the second mistake.
I've moved on to the AI part, and currently coding the part that checks for victory conditions. And my progress is mostly due to my dad, although I guess I should give myself some credit too ^^
Either way, thanks. I'll ask more questions if they come up
-Roman Zimine |
|
|
|
|
|
Roman
|
Posted: Wed Aug 06, 2008 7:05 pm Post subject: RE:Tic-Tac-Toe Help |
|
|
I'm not making another post for questions related to this so I hope people will check it ^^
I want to make a popup message that says "Game Over" and has a button to "Play Again", which, when activated, has a function. I found something like tkmessageBox but there weren't any code examples or anything of that sort. I'll keep looking, but if someone can help me that'd be great.
Also, I want to make a function that resets the whole game. Do I just make that function create a new instance of the class? Or is there some command?
I'll look for the answers myself, but if anyone can help that would be great Thank you.
EDIT: I got the message thing. Still looking for a way to reset.
EDIT2: Got everything ^^ Woo! |
|
|
|
|
|
Sponsor Sponsor
|
|
|
|
|