0

I'm working on making a battleship game for a school project using Pythons Tkinter, and I made these classes to have the player place their ships. The idea is that you can click on one of the ships in an area off to the side, and then click on a button on the board to place the ship. Problem is, the buttons place in a diagonal, and clicking on them brings the initial menu screen back up, which is odd

This is my first time working with Tk so I don't even know where to start

class ShipCreator:
    global board, BOARD_OFFSET
    ShipHolder = Frame(board)
    ShipHolder.place(x=800, y=BOARD_OFFSET)
    shipNum = 5
    activeShip = None

    def __init__(self, length, image, direction):
        # Length is the length integer, image an image, direction is 0 for facing up/down, 1 for facing left/right
        self.length = length
        self.imageTk = ImageTk.PhotoImage(image)
        self.direction = direction
        self.button = Button(ShipCreator.ShipHolder, image=self.imageTk, command=self.start_place)
        self.button.pack()

    def start_place(self):
        actionLabel.configure(text="Click where you'd like the bottom/left of the ship to be:")
        ShipCreator.activeShip = self

    def check_place(self, xcoord, ycoord):
        import Main
        can_place = True
        for i in range(self.length + 1):
            if self.direction == 0 and xcoord < len(Main.playerBoard):
                if ycoord + i < len(Main.playerBoard[xcoord]) and Main.playerBoard[xcoord][ycoord + i] != " ":
                    can_place = False
                    break
            elif ycoord < len(Main.playerBoard[xcoord + self.length]):
                if xcoord + i < len(Main.playerBoard) and Main.playerBoard[xcoord + i][ycoord] == " ":
                    can_place = False
                    break
        return can_place

    def place(self, xcoord, ycoord):
        import Main
        global playerBoard
        if self.check_place(xcoord, ycoord):
            playerBoard.create_image(78 * xcoord + 8, 78 * xcoord + 8 + BOARD_OFFSET, image=self.imageTk, anchor=NW)
            for i in range(self.length + 1):
                if self.direction == 0:
                    Main.playerBoard[xcoord][ycoord + i] = "S"
                else:
                    Main.playerBoard[xcoord + i][ycoord] = "S"
            del self.button
            ShipCreator.shipNum -= 1
            if ShipCreator.shipNum == 0:
                for i in range(10):
                    for j in range(10):
                        exec("del button" + str(i) + str(j))
                del ship1, ship2, ship3, ship4, ship5
                # TODO: Start actual game flow here
        else:
            ShipCreator.activeShip = None
            actionLabel.configure(text="Cannot place a ship there!")

class PlaceButton:
    def __init__(self, xcoord, ycoord):
        global BOARD_OFFSET
        self.xcoord = xcoord
        self.ycoord = ycoord
        self.button = Button(playerBoard, image=backgroundImageTK, command=self.place)
        self.button.place(x=78 * xcoord + 8, y=78 * xcoord + 8 + BOARD_OFFSET, anchor=NW, height=78, width=78)

    def place(self):
        if ShipCreator.activeShip is not None:
            ShipCreator.activeShip.place(self.xcoord, self.ycoord)

def open_game():  # Initializes the game, making the grid buttons for the players ships
    global shipImg1, shipImg2, shipImg3, shipImg4, shipImg5, ship1, ship2, ship3, ship4, ship5
    menu.pack_forget()
    board.pack(expand=True, fill=BOTH)
    for i in range(10):
        for j in range(10):
            exec("button" + str(i) + str(j) + " = PlaceButton(" + str(i + 1) + "," + str(j + 1) + ")")
    ship1 = ShipCreator(5, shipImg1, 0)
    ship2 = ShipCreator(4, shipImg2, 0)
    ship3 = ShipCreator(3, shipImg3, 0)
    ship4 = ShipCreator(4, shipImg4, 1)
    ship5 = ShipCreator(5, shipImg5, 1)

I expect the ships to be placed on top of the buttons, and instead they are placed under the buttons, and bring the initial menu sreen back up

  • I suggest you read and follow the advice in the accepted answer to the question [Best way to structure a tkinter application?](https://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application). This will allow you to get rid of the need to use so many `global` variabled (because they can be turned into class instance attributes). – martineau Jun 04 '19 at 17:52
  • Obviously that would be optimal, but I don't really have the time to completely rewritie all of my UI code so far to make it object based. What I need to do is fix the bugs – Ian Wright Jun 04 '19 at 21:44
  • The code in your question isn't a [mcve], and its use of global variables only makes debugging it more difficult and time consuming (for both you and others)... – martineau Jun 04 '19 at 21:58

0 Answers0