Python Forum
Battleships game in python with tkinter
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Battleships game in python with tkinter
#1
I am doing my best to create a battleships game in python with tkinter.

Currently the board consists of a list with lists of "~" and "around" it is a border of "#". The border is there to check that a ship can be placed on the board and not extend beyond the board. I know this seems redundant, which is why I humbly ask for improvements.

I am having two major problems with this though:

I have a hunch that I should be implementing classes but I am very new to them so I'd greatly appreciate some guidance.

My "AI" function (ai_shoots) is currently shooting on the same field that the player is shooting at, which it obviously shouldn't do. Instead it should shoot on your board. Press the 1 player button to play against the AI.

from tkinter import *
from tkinter import font
import tkinter.messagebox
from functools import partial
import random
import time
import sys
import os

root = Tk()
root.wm_title("BATTLESHIPS")
root.configure(background='gray19')
font1 = font.Font(family='Helvetica', size=12, weight='bold')
font_big = font.Font(family='Helvetica', size=16, weight='bold')
font_normal = font.Font(family='Helvetica', size=10, weight='normal')

ships = {"Aircraft Carrier": 4, "Battleship": 3, "Submarine": 2, "Destroyer": 1}
AI = False


def restart_program():
    python = sys.executable
    os.execl(python, python, *sys.argv)


def player_board():
    board = []
    t = []
    t += (10 + 2) * ['# ']
    board.append(t)  # Övre ram

    rad = ['# ']  # Vänster ram
    for r in range(0, 10):
        rad.append("~ ")
    rad.append('# ')  # Höger ram
    for k in range(0, 10):
        board.append(list(rad))

    board.append(t)  # Undre ram
    return board


def place_ship(ship, board):
    # w = 0  # Håller igång loopen
    while True:
        checkcoords = []
        x = random.randint(1, 10)  # Genererad x-koordinat
        y = random.randint(1, 10)  # Genererad y-koordinat
        o = random.randint(0, 1)  # Väljer placeringssätt
        if o == 0:
            ori = "v"  # Vertikalt
        else:
            ori = "h"  # Horisontellt
        if ori == "v" and y + ships[ship] > 10:
            pass
            # w = 0  # Säkerställer att båten kan placeras inom spelplanen
        elif ori == "h" and x + ships[ship] > 10:
            pass
            # w = 0
        else:
            if ori == "v":
                for i in range(-1, (ships[ship] + 1)):
                    for j in range(-1, 2):
                        checkcoords.append(board[y + i][x + j])
                if ': ' not in checkcoords:
                    for i in range(ships[ship]):
                        board[y + i][x] = ': '
                    break
            #                else:
            #                    w = 0
            elif ori == "h":
                for i in range(-1, (ships[ship] + 1)):
                    for j in range(-1, 2):
                        checkcoords.append(board[y + j][x + i])
                if ': ' not in checkcoords:
                    for i in range(ships[ship]):
                        board[y][x + i] = ': '
                    break


#                else:
#                    w = 0


def place_all_ships(board):
    for ship in ships:
        for antal in range(0, (5 - ships[ship])):
            place_ship(ship, board)


def popupwindow(msg):
    answer = tkinter.messagebox.askquestion("Game Over", msg + " Would you like to play again?")
    if answer == "yes":
        restart_program()
    elif answer == "no":
        quit()


def nr_players(number):
    global AI
    if number == 1:
        player2_or_AI.set("AI")
        AI = True
    else:
        player2_or_AI.set("Player 2")


info = StringVar()
player2_or_AI = StringVar()


def side_labels():
    # info = StringVar()
    Label(root, text="BATTLESHIPS", fg="white", bg="gray19", font=font_big).grid(row=0, column=10, columnspan=9)
    Label(root, textvariable=info, fg="white", bg="gray19", font=font1).grid(row=12, column=6, columnspan=18)

    for _ in range(10):
        Label(root, text="   ", bg="gray19").grid(row=_, column=0)
    Button(root, width=7, height=1, text="1 Player", font=font1, fg="white", activebackground="gray19",
           bg="gray19", command=lambda: nr_players(1)).grid(row=2, column=1)
    Button(root, width=7, height=1, text="2 Players", font=font1, fg="white", activebackground="gray19",
           bg="gray19", command=lambda: nr_players(2)).grid(row=3, column=1)
    Label(root, text="Get 20 hits to win", font=font_normal, fg="white", bg="gray19").grid(row=5, column=1)
    Label(root, text="1 Battleship 4 units", font=font_normal, fg="white", bg="gray19").grid(row=6, column=1)
    Label(root, text="2 Battleships 3 units", font=font_normal, fg="white", bg="gray19").grid(row=7, column=1)
    Label(root, text="3 Battleships 2 units", font=font_normal, fg="white", bg="gray19").grid(row=8, column=1)
    Label(root, text="4 Battleships 1 unit  ", font=font_normal, fg="white", bg="gray19").grid(row=9, column=1)

    for _ in range(10):
        Label(root, text="   ", bg="gray19").grid(row=_, column=2)

    for _ in range(10):
        Label(root, width=20, text="   ", bg="gray19").grid(row=_, column=25)


def ai_shoots(y_coord, x_coord, all_buttons, player_1_board, ai_score):
    # print("yes")
    if ai_score == 20:
        popupwindow("The computer has won.")
    if player_1_board[y_coord][x_coord] == ': ':
        ai_score += 1
        player_1_board[y_coord][x_coord] = 'X '
        all_buttons[y_coord - 1][x_coord - 1].configure(text="X", fg="black", bg="red3")
        if player_1_board[y_coord - 1][x_coord] == ': ':
            ai_shoots(y_coord - 1, x_coord, all_buttons, player_1_board, ai_score)
        elif player_1_board[y_coord + 1][x_coord] == ': ':
            ai_shoots(y_coord + 1, x_coord, all_buttons, player_1_board, ai_score)
        elif player_1_board[y_coord][x_coord - 1] == ': ':
            ai_shoots(y_coord, x_coord - 1, all_buttons, player_1_board, ai_score)
        elif player_1_board[y_coord][x_coord + 1] == ': ':
            ai_shoots(y_coord, x_coord + 1, all_buttons, player_1_board, ai_score)
        else:
            x = random.randint(1, 10)
            y = random.randint(1, 10)
            ai_shoots(y, x, all_buttons, player_1_board, ai_score)
    elif player_1_board[y_coord][x_coord] == 'X ' or player_1_board[y_coord][x_coord] == 'O ':
        x = random.randint(1, 10)
        y = random.randint(1, 10)
        ai_shoots(y, x, all_buttons, player_1_board, ai_score)
    else:
        player_1_board[y_coord][x_coord] = 'O '
        all_buttons[y_coord - 1][x_coord - 1].configure(text="O", fg="white")


def hit_or_miss(a, b, board, all_buttons, info, player, player_1_hits, player_2_hits, ai_score):
    global AI
    # print(player)
    if board[a + 1][b + 1] == 'O ' or board[a + 1][b + 1] == 'X ':  # Redan skjutit
        info.set("You have already fired there, " + player + "!")

    elif board[a + 1][b + 1] == ': ':  # Träff
        info.set("A hit, nice shot " + player + "!")
        board[a + 1][b + 1] = 'X '
        all_buttons[a][b].configure(text="X", fg="black", bg="red3", activebackground="red3")
        if player == "player 1":
            player_1_hits += 1
        else:
            player_2_hits += 1

    else:  # Miss
        info.set("Seems like you missed that one, " + player + "!")
        board[a + 1][b + 1] = 'O '
        all_buttons[a][b].configure(text="O", fg="White", activeforeground="white")
        # print(AI)
        if AI:
            x = random.randint(0, 10)
            y = random.randint(0, 10)
            ai_shoots(y, x, all_buttons, board, ai_score)
    if player_1_hits == 20 or player_2_hits == 20:
        popupwindow(player + " has won!")


def side(player, allbuttons):
    print(player)
    if player == "player 1":
        for row in range(10):
            for column in range(10):
                allbuttons[row][column].grid(row=1 + row, column=4 + column)

        label2 = Label(root, text="Player 1", font=font1, fg="white", bg="gray19")
        label2.grid(row=11, column=4, columnspan=10)
    else:
        for row in range(10):
            for column in range(10):
                allbuttons[row][column].grid(row=1 + row, column=15 + column)

        label3 = Label(root, textvariable=player2_or_AI, font=font1, fg="white", bg="gray19")
        label3.grid(row=11, column=15, columnspan=10)


def board_buttons(board, info, player, player_1_hits, player_2_hits, ai_score):
    allbuttons = []
    a = 0
    print(AI)
    for i in range(10):
        b = 0
        buttons = []
        for j in range(10):
            button = Button(root, width=2, height=1, font=font1, bg="sky blue", activebackground="sky blue",
                            command=partial(hit_or_miss, a, b, board, allbuttons,
                                            info, player, player_1_hits, player_2_hits, ai_score))
            buttons.append(button)
            b += 1
        allbuttons.append(list(buttons))
        a += 1

    side(player, allbuttons)


def middle_board_space():
    for _ in range(10):
        Label(root, text="   ", bg="gray19").grid(row=1 + _, column=14)


def main():
    player_1_hits = 0
    player_2_hits = 0
    ai_hits = 0

    player_1_board = player_board()
    player_2_board = player_board()

    place_all_ships(player_1_board)  # Sätter ut alla skeppen
    place_all_ships(player_2_board)

    info = StringVar()
    side_labels()

    board_buttons(player_1_board, info, "player 1", player_1_hits, player_2_hits, ai_hits)
    middle_board_space()
    board_buttons(player_2_board, info, "player 2", player_1_hits, player_2_hits, ai_hits)


main()
root.mainloop()
############################################
Reply


Messages In This Thread
Battleships game in python with tkinter - by Togeh - Sep-19-2018, 10:00 AM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020