[PYTHON] I made a game called Battle Ship using pygame and tkinter

0. First

If you want to see how the things you make this time work, please see here (youtube video). I think that the video will explain more deeply than the explanation here.

1. Download sound effects and BGM

This time, I used the free Sound effects and BGM. Also, when using sound effects in pygame, it must be a wav file, so here I converted from mp3 to wav.

2. Write the process

Please see Github because it will be long if you put the whole code. Here, we will explain each function one by one.

First, import the library to be used this time. This time we will use numpy to manipulate the matrix.

library.py


import pygame
from pygame.locals import *
import numpy as np
import tkinter as tk
import random

And this is, as the name implies, a function that draws a field. The field this time is in the shape of a grid. I haven't done much difficult things here, so if you take a closer look, you'll understand. There is also a function called p2_field, but what it does is the same as this function.

battle_ship.py


def p1_field(win):
    rows = 10
    x = 55
    y = 55
    sizeBwn = 65

    for i in range(rows):
        x += sizeBwn
        y += sizeBwn
        pygame.draw.line(win,(0,0,0),(x,55),(x,705))
        pygame.draw.line(win,(0,0,0),(55,y),(705,y))

    pygame.draw.line(win,(0,0,0),(55,55),(55,705),5)
    pygame.draw.line(win,(0,0,0),(55,55),(705,55),5)
    pygame.draw.line(win,(0,0,0),(55,705),(705,705),5)
    pygame.draw.line(win,(0,0,0),(705,55),(705,705),5)
    
    drawnumbers(87.5,win)
    drawstring(87.5,win)
    font = pygame.font.SysFont('comicsens',100)
    text = font.render("Your Field",5,(0,0,255))
    win.blit(text,(380-text.get_width()/2,730))

This is the last one called in the previous function. It draws numbers and alphabets, but it's almost like a decoration, with little to do with the game.

battle_ship.py


def drawnumbers(pos,win):
    for b in num_list:
        font = pygame.font.SysFont('comicsens',25)
        text = font.render(b,1,(0,0,0))
        win.blit(text,(pos - (text.get_width()/2),5))
        pos += 65

def drawstring(pos,win):
    for i in st_list:
        font = pygame.font.SysFont('comicsens',25)
        text = font.render(i,1,(0,0,0))
        win.blit(text,(5,pos - (text.get_width()/2)))
        pos += 65

This is the function that will be called when you are in the position of the ship. This time it will be called first. This uses the same one I introduced to Qiita earlier in How to change only the color of the button pressed in Tkinter. I taught you a simple method, but it didn't work when I drew the ship, so I'll put it on hold.

battle_ship.py


def setting_ships():
    column = -1
    row = 0
    root = tk.Tk()
    root.title('Set Your Ships')
    root.geometry('470x310')
    for i in range(101):
        if i > 0:
            if i%10 == 1:
                row += 1 
                column = -1
            column += 1
            text=f'{i}'
            btn = tk.Button(root, text=text)
            btn.grid(column=column, row=row)
            btn.config(command=collback(btn,i))  
    root.mainloop()
    main()

def collback(btn,i):
    def nothing():
        btn.config(bg='#008000')
        numbers.append(i)
    return nothing

This is the next function to be called. This draws the field and calls a function called draw_ships.

battle_ship.py


def main():
    pygame.display.set_caption("battle ship")     
    win.fill((255,255,255)) 
    p1_field(win)
    p2_field(win)
    draw_ships(array_1,numbers)
    bomb_buttons()

    pygame.quit()

This is draw_ships. The array passed here and the array passed to other functions are the same and are two-dimensional arrays. Here, draw the position of the ship specified in Tkinter on the field. The list called numbers contains the numbers of the buttons you pressed.

battle_ship.py


array_1 = np.zeros([10,10],dtype=int)
array_2 = np.zeros([10,10],dtype=int)

def draw_ships(array, numbers):
    width = 65
    numbers = np.sort(numbers)
    for i in numbers:
        array.flat[i-1] = 1
    array = array.reshape(-1,1)
    for i in np.where(array == 1)[0]:
        index = i//10
        if i >= 10:
            columns = int(str(i)[1:])
        else:
            columns = i
        pygame.draw.rect(win,(0,0,0),(55+width*columns,55+width*index,width,width),0)
    pygame.display.update()
    ai_ships(array_2)

And this is the next function to be called. Although it is written as ai, this is simply a random installation of ships. You can't see the other ai ship, so just store the ship's position in the array.

battle_ship.py


def ai_ships(array):
    num_5 = random.randint(0,5)
    num_4_1 = random.randint(8,9)
    num_4_2 = random.randint(3,6)
    num_3_1 = random.randint(3,6)
    num_3_2 = random.randint(5,7)
    num_2 = random.randint(2,6)
    num_1_1 = random.randint(0,2)
    num_1_2 = random.randint(5,9)
    if num_5 >= 7:
        array[num_5:num_5+5,0] = 1
    if num_5 <= 6:
        array[-5:,0] = 1
    array[num_3_1,num_3_2:num_3_2+3] = 1
    array[num_2,2:4] = 1
    array[num_4_1,num_4_2:num_4_2+4] = 1
    array[num_1_1,num_1_2] = 1
    array = array.reshape(-1,1)
    pygame.display.update()

Then the game starts and the button is displayed again. Whether or not it was hit by a function called bombing in collback and the subsequent processing are performed.

battle_ship.py


def bomb_buttons():
    column = -1
    row = 0
    root = tk.Tk()
    root.title('bombing')
    root.geometry('470x310')
    for i in range(101):
        if i > 0:
            if i%10 == 1:
                row += 1 
                column = -1
            column += 1
            text=f'{i}'
            btn = tk.Button(root, text=text)
            btn.grid(column=column, row=row)
            btn.config(command=collback2(btn,i))      
    root.mainloop()

def collback2(btn,i):
    def nothing2():
        btn.config(bg='#008000')
        bombing(i,btn)
    return nothing2

This is the function called bombing. The list used here, bomb, contains values from 0 to 99. Then, if there is a ship in the specified place, the button will be red and a red circle will be drawn on the field with a sound effect. If there is no ship, a black circle will be drawn. And when your turn is over, it will be ai's turn. If either ship is wiped out, the game is over and the winner is the one who wiped out.

battle_ship.py


bomb = [i for i in range(100)]

def bombing(i,btn):
    global p1_counter,p2_counter
    font = pygame.font.SysFont('comicsens',100)
    i -= 1
    array = array_2.reshape(-1,1) 
    width = 65  
    index=i//10
    if i >= 10:
        columns = int(str(i)[1:])
    else:
        columns = i
    if array[i] == 1:
        pygame.draw.circle(win,(255,0,0),((730+columns*width)+width//2,(55+index*width)+width//2),width//2,0)
        bombed_sound.play()
        p1_counter += 1
        btn.config(bg='#FF0000')
    elif array[i] == 0:
        pygame.draw.circle(win,(0,0,0),((730+columns*width)+width//2,(55+index*width)+width//2),width//2,0)
        failed.play()
    if p1_counter == 15:
        pygame.mixer.music.stop()
        text = font.render('You Win!!',5,(255,0,0))
        win.blit(text,(750-text.get_width()/2,200))
        pygame.display.update()
        victory.play()

    num = random.choice(bomb)
    bomb.pop(bomb.index(num))
    array1 = array_1.reshape(-1,1)
    index=num//10
    if num >= 10:
        columns = int(str(num)[1:])
    else:
        columns = num
    if array1[num] == 1:
        pygame.draw.circle(win,(255,0,0),((55+columns*width)+width//2,(55+index*width)+width//2),width//2,0)
        p2_counter += 1
        bombed_sound.play()
    elif array1[num] == 0:
        pygame.draw.circle(win,(0,0,0),((55+columns*width)+width//2,(55+index*width)+width//2),width//2,0)
    if p2_counter == 15:
        pygame.mixer.music.stop()
        text = font.render('You Lose...',1,(0,0,255))
        win.blit(text,(750-text.get_width()/2,200))
        pygame.display.update()
        lose.play()

    pygame.display.update()

Finally

How to make this battleship game is also explained in Youtube, so please have a look if you like it. If you have any questions, please use the comment section of the video or the comment section of this article. Also, if you like it, please subscribe to the channel.

Recommended Posts

I made a game called Battle Ship using pygame and tkinter
〇✕ I made a game
I made a school festival introduction game using Ren’py
I made a simple typing game with tkinter in Python
I made a Numer0n battle game in Java (I also made AI)
I made a puzzle game (like) with Tkinter in Python
I made a Chatbot using LINE Messaging API and Python
I made a Line-bot using Python!
I made a poker game server chat-holdem using websocket with python
I made a Chatbot using LINE Messaging API and Python (2) ~ Server ~
I tried playing a ○ ✕ game using TensorFlow
Beginner: I made a launcher using dictionary
I made a life game with Numpy
I made a roguelike game with Python
I made a crazy thing called typed tuple
[Python] I made a Youtube Downloader with Tkinter.
I tried to make a ○ ✕ game using TensorFlow
I made a bin picking game with Python
I made a list site of Kindle Prime Reading using Scrapy and GitHub Actions
I made a login / logout process using Python Bottle.
I made a Christmas tree lighting game with Python
I made a vim learning game "PacVim" with Go
I made a window for Log output with Tkinter
I made a LINE BOT with Python and Heroku
I made a falling block game with Sense HAT
I scraped the Organization member team and made a ranking
Create a game to control puzzle & dragons drops using pygame
I made a quick feed reader using feedparser in Python
I made a VGG16 model using TensorFlow (on the way)
I tried to make a stopwatch using tkinter in python
I made a muscle training estimation app using Qore SDK
I made a python text
I made a discord bot
Life game with Python [I made it] (on the terminal & Tkinter)
[Python3] I made a decorator that declares undefined functions and methods.
I made a simple network camera by combining ESP32-CAM and RTSP.
Build a game leaderboard on Alibaba cloud using Python and Redis
I made a Nyanko tweet form with Python, Flask and Heroku
I made RNN learn a sine wave and made a prediction: Hyperparameter adjustment
I made a Dir en gray face classifier using TensorFlow --(1) Introduction
I made a Dir en gray face classifier using TensorFlow-④ Face extraction
[Python] I wrote a REST API using AWS API Gateway and Lambda.
I made a program that automatically calculates the zodiac with tkinter
I made a chatbot with Tensor2Tensor and this time it worked
[Kaggle] I made a collection of questions using the Titanic tutorial
I compared hardware, software, OS, and Linux with a game console
I made a music bot using discord.py and Google Drive API (tested with Docker → deployed to Heroku)
I made a C ++ learning site
I made a CUI-based translation script (2)
Create a python GUI using tkinter
I made a wikipedia gacha bot
I made a fortune with Python.
I made a CUI-based translation script
Zura made like a life game
I made a daemon with Python
I made a Dir en gray face classifier using TensorFlow --⑩ Face classification test
I made a Dir en gray face classifier using TensorFlow --⑥ Learning program
I made a Dir en gray face classifier using TensorFlow --⑬ Playing (final)
I made a Dir en gray face classifier using TensorFlow --- ⑧ Learning execution
I made a Dir en gray face classifier using TensorFlow --⑫ Web release
I made a network to convert black and white images to color images (pix2pix)