I am currently attempting to build a battleship game using Tkinter. I am at an impass however, as I am not able to make the program properly "wait" for an answer and show the Tkinter window. My idea was that whenever a submit button would be pressed, a value would be set to true. As long as that value was false, then the program would just loop through a while loop. When this value is triggered, the next set of actions would be given along with setting that value back to false, and waiting for it to be true once more. Here is the code:
from Tkinter import *
import time
class Application(Frame):
def __init__(self,master):
self.user = False
Frame.__init__(self,master)
self.launch()
self.master = master
self.shiplist = []
self.board = [
["A",1],["B",1],["C",1],["D",1],["E",1],["F",1],["G",1],["H",1],["I",1],["J",1],
["A",2],["B",2],["C",2],["D",2],["E",2],["F",2],["G",2],["H",2],["I",2],["J",2],
["A",3],["B",3],["C",3],["D",3],["E",3],["F",3],["G",3],["H",3],["I",3],["J",3],
["A",4],["B",4],["C",4],["D",4],["E",4],["F",4],["G",4],["H",4],["I",4],["J",4],
["A",5],["B",5],["C",5],["D",5],["E",5],["F",5],["G",5],["H",5],["I",5],["J",5],
["A",6],["B",6],["C",6],["D",6],["E",6],["F",6],["G",6],["H",6],["I",6],["J",6],
["A",7],["B",7],["C",7],["D",7],["E",7],["F",7],["G",7],["H",7],["I",7],["J",7],
["A",8],["B",8],["C",8],["D",8],["E",8],["F",8],["G",8],["H",8],["I",8],["J",8],
["A",9],["B",9],["C",9],["D",9],["E",9],["F",9],["G",9],["H",9],["I",9],["J",9],
["A",10],["B",10],["C",10],["D",10],["E",10],["F",10],["G",10],["H",10],["I",10],["J",10],
]
self.letters = [["A",1],["B",2],["C",3],["D",4],["E",5],["F",6],["G",7],["H",8],["I",9],["J",10]]
def launch(self):
self.pack(fill=BOTH, expand=1)
Label(self, text="Your Board").grid(sticky=W,row = 0, column = 0)
Label(self, text="Enemy Board").grid(sticky=W, row = 0,column = 2)
canvas1 = Canvas(self)
canvas1.create_rectangle(2,2,250,250,outline= "black",fill = "white")
canvas1.grid(row=1, column=0, columnspan=2, rowspan=2)
canvas2 = Canvas(self)
canvas2.create_rectangle(2,2,250,250,outline= "black",fill = "white")
canvas2.grid(row=1, column=2, columnspan=2, rowspan=2)
self.actionLabel = Label(self,text = "Currently Placing:")
self.actionLabel.grid(row = 3,column= 0,sticky = W)
self.infoLabel1 = Label(self,text ="")
self.infoLabel1.grid(row = 4,column = 0)
self.infoLabel2 = Label(self,text = "")
self.infoLabel2.grid(row=5,column=0)
self.userinput = Entry(self,text = "Write here")
self.userinput.grid(row=6,column=0)
Button(self,text = "Submit",command = self.action).grid(row = 6,column = 1,sticky = W)
self.errorlabel = Label(self,text = "")
self.errorlabel.grid(row=7,column=0)
self.request_ships()
def action(self):
value = self.userinput.get()
self.user = True
print "action successful"
def request_ship(self,allegiance,name,size):
print allegiance,name,size
ship = [name,size]
error = False
if allegiance == "player":
print "here"
while error == False:
self.user = False
text1 = name + "Size: "+ str(size) + " cells."
self.infoLabel1.configure(text = text1)
self.infoLabel2.configure(text = "Would you like for your ship to be vertical or horizontal? v/h:")
if self.user == True:
if value != "vertical" and value != "horizontal" and value != "h" and value != "v":
self.errorlabel.configure(text = "Error! Incorrect Format!")
error = False
else:
self.user = False
if value == "h":
ship += value
self.infoLabel2.configure(text = "Please enter the leftmost coordinate of where you want to place your ship:")
if self.user== True:
if len(value) > 1 and len(value) <= 3 and (value[0] == "A"
or value[0] == "B" or value[0] == "C" or value[0] == "D"
or value[0] == "E" or value[0] == "F" or value[0] == "G"
or value[0] == "H" or value[0] == "I" or value[0] == "J") and (value[1] == "1"
or value[1] == "2" or value[1] == "3" or value[1] == "4"
or value[1] == "5" or value[1] == "6" or value[1] == "7"
or value[1] == "8" or value[1] == "9" or value[1] == "10"):
for i in range(len(self.board)):
if self.board[i][0] == value[0] and self.board[i][0] == value[1:]:
num = 0
for i in size:
coord+= i + num
num += 1
print ship
def request_ships(self):
print "request ships works"
self.request_ship("player","Aircraft Carrier",5)
def grid(self,gridinfo,shipinfo):
coord = 0
cellnum = 0
for number in range(100):
cell = Canvas(self)
for ship in shipinfo:
## if #####
print "tt"
cell.create_rectangle(coord,coord,25,25,outline="black",fill=color)
def main():
root = Tk()
app = Application(root)
app.geometry = ("1000x1000")
root.title("Battleship")
root.mainloop()
main()
The issue however, is that the window never appears when the request_ships function is loading, as it's endlessly going in a while loop. Any tips on how to fix this?
Some things to look into: you have while error == False
, but the only reference to error
within the loop is to assign False
to it. In the loop, you assign self.user = False
, but then almost everything in the loop relies on getting into if self.user == True
. You assign self.userinput.get()
to the local variable value
rather than to an instance variable. You should make more use of the in
operator to avoid making dozens of separate comparisons. You were only checking value[1]
in the large if
statement within if self.user == True
. Instead of checking whether a value is equal to True
or False
, you can just refer to that value, e.g. if self.user:
, because another way to express True == True
is simply True
(unless that variable has an uncertain type and you really do need to check whether it's True
or, say, a non-empty string). You're checking what's in the Entry
box before it's actually ready - you should put request_ships()
into some Button
's command, or at least wait a second with after()
. You're checking if self.board[i][0]
is equal to both value[0]
and value[1]
, which will only be true if the user enters something invalid like AA
. If we fix that to also check self.board[i][1]
, it still won't work because everything in an Entry
widget is a string, which must be converted to an int
. You cannot concatenate a string onto a list
- use append()
. Checking for vertical/horizontal, location, etc., one after the other, from a single function will run into issues, because you never wait for the user to enter a different value.
Here's a sample of request_ship()
with a few of these changes implemented so you can get an idea of where to go:
def request_ship(self,allegiance,name,size):
print allegiance,name,size
ship = [name,size]
error = True
if allegiance == "player":
print "here"
text1 = name + "Size: "+ str(size) + " cells."
self.infoLabel1.configure(text = text1)
self.infoLabel2.configure(text = "Would you like for your ship to be vertical or horizontal? v/h:")
if self.user:
if self.value not in ("vertical", "horizontal", "h", "v"):
self.errorlabel.configure(text = "Error! Incorrect Format!")
else:
self.user = False
if self.value == "h":
ship.append(self.value)
self.infoLabel2.configure(text = "Please enter the leftmost coordinate of where you want to place your ship:")
if self.user:
try:
v1 = int(self.value[1:])
except ValueError:
pass
if 1 < len(self.value) <= 3 and (self.value[0] in "ABCDEFGHIJ") and (v1 in range(1,11)):
for i in range(len(self.board)):
if self.board[i][0] == self.value[0] and self.board[i][1] == v1:
num = 0
for i in size:
coord+= i + num
num += 1
self.user = False
Please note that the above code is neither complete nor a drop-in replacement to make your program work. Your code will need some serious restructuring to deal with being a GUI program vs a command-line program.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments