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
#2
Hi :)
I had do use some different imports for Tkinter to get it running.
The problem with the AI was that you passed ai_shoot the same board as you used for player_2. And on top of that the all_button array only holds the buttons from the field where it has been triggered. Since ai_shoot only is triggered when you click a button on the player_2 field, the buttons of that field are used. You can bypass this by using a global array where you store all buttons from both fields. After creation, the buttons of player_1 would be at the first index. You should consider blocking the click event on player_1 field while AI is ingame. Since clicking these buttons still work, they would trigger the AI as well.

Objects are the most important part of python. You worked with some objects yourself while programming this game. You can imagine it that way: Objects are build out of classes, like an actual chair is build by using a blueprint. Since there are different kind of chairs, each chair may have different attributes. There are chairs without a back piece or chairs with just 3 legs. There are even chairs with wheels. In your case you could make your players as Objects of the player class. Each player has a score, a name, board and ships. The AI even has the right to act without a human.
The overall board itself could be a class which has different methods like: hit_or_miss and attributes like all buttons and a width/height.
This book is good and captures everything:
http://books.tarsoit.com/Python%203%20Ob...dition.pdf (19.09.2018)
Though it is quite a lot if you need it asap :D Python2 and Python3 differ in some points but the important things you need right now are identical.
These got the essentials:
https://www.johnny-lin.com/pyintro/ed01/...s/ch07.pdf (19.09.2018)
https://pdfs.semanticscholar.org/present...051677.pdf (19.09.2018)

If I may, I would like to give you some programming tips:
1. ALWAYS comment in english. I know that it is quicker and easier to comment in you native language, but sharing the code is quite difficult. The guy on the other end of the screen has to find out what you did. Also not each symbol is used in each language. I for myself had the problem that your comments were not in ascii format. It is also great for improving english skills and writing english commands right away, if you want to work in the IT or CS field.
2. Do yourself a favour, and comment more ;) It is horrible to not look at your own code for some days and when you get back on it you have to figure out what you did.

from Tkinter import *
from tkFont import Font
import tkMessageBox
from functools import partial
import random
import time
import sys
import os

root = Tk()
root.wm_title("BATTLESHIPS")
root.configure(background='gray19')
font1 = Font(family='Helvetica', size=12, weight='bold')
font_big = Font(family='Helvetica', size=16, weight='bold')
font_normal = 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)

    rad = ['# ']
    for r in range(0, 10):
        rad.append("~ ")
    rad.append('# ')
    for k in range(0, 10):
        board.append(list(rad))

    board.append(t)
    return board


def place_ship(ship, board):
    # w = 0
    while True:
        checkcoords = []
        x = random.randint(1, 10)
        y = random.randint(1, 10)
        o = random.randint(0, 1)
        if o == 0:
            ori = "v"  # Vertikalt
        else:
            ori = "h"  # Horisontellt
        if ori == "v" and y + ships[ship] > 10:
            pass
            # w = 0
        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 = tkMessageBox.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()
every_button = []


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, 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 '
        every_button[0][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 '
        every_button[0][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, board2):
    global AI
    # print(player)
    if board[a + 1][b + 1] == 'O ' or board[a + 1][b + 1] == 'X ':
        info.set("You have already fired there, " + player + "!")

    elif board[a + 1][b + 1] == ': ':
        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, board2, 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, board2):
    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, board2))
            buttons.append(button)
            b += 1
        allbuttons.append(list(buttons))
        a += 1
    every_button.append(allbuttons)
    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)
    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, player_2_board)
    middle_board_space()
    board_buttons(player_2_board, info, "player 2", player_1_hits, player_2_hits, ai_hits, player_1_board)


main()
root.mainloop()
Reply


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

Forum Jump:

User Panel Messages

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