Tips

【pythonゲーム作成】pythonでマインスイーパー作ってみるよ【その8】

【pythonゲーム作成】pythonでマインスイーパー作ってみるよ【その8】

【pythonゲーム作成】pythonでマインスイーパー作ってみるよ【その8】

今回はpythonでシンプルなマインスイーパーを作成してみたいと思います。
windowsに搭載されていた昔ながらのマインスイーパーを目指してみます!

おなじみのこんなやつ
↓↓↓

tkinterモジュールでは完全再現とまではいきませんが、なるべく似ているものを
作れるようにしていきたいと思います!

前回までのコード(コメント多くなりすぎたので、少なくしました)
↓↓↓

from tkinter import *
import random   #追加する

####メイン画面の生成####
root = Tk()
root.title("マインスイーパ")
root.resizable(0,0)

###メニュー作成###
menu_ROOT = Menu(root)
root.configure(menu = menu_ROOT)

menu_GAME = Menu(menu_ROOT, tearoff = False)
menu_ROOT.add_cascade(label = 'ゲーム(G)', under = 4, menu = menu_GAME)

menu_GAME.add_command(label = "初級(B)", under = 3)
menu_GAME.add_command(label = "中級(I)", under = 3)
menu_GAME.add_command(label = "上級(E)", under = 3)

menu_ROOT.add_command(label = "終了(X)", under = 3)

###フレームオブジェクト作成###
root_frame = Frame(root, relief = 'groove', borderwidth = 5, bg = 'LightGray')
status_frame = Frame(root_frame, height = 50, relief = 'sunken', borderwidth = 3, bg = 'LightGray')
game_frame = Frame(root_frame, relief = 'sunken', borderwidth = 3, bg = 'LightGray')
root_frame.pack()
status_frame.pack(pady = 5, padx = 5, fill = 'x')
game_frame.pack(pady = 5, padx = 5)

####マス目の作成####
bomb_list = []

def left_click(event):
    event.widget.configure(relief = 'ridge', bd = '1')
    except_num = event.widget.num
    if len(bomb_list) == 0:
        while len(bomb_list) != 10:
            bomb_num = random.randint(0,80)
            if bomb_num != except_num and (bomb_num in bomb_list) == False:
                bomb_list.append(bomb_num)
        for i in bomb_list:
            frame_list[i].configure(bg = 'red')
    bomb_count = search_bomb(bomb_list, event.widget.num)
    if  bomb_count == 9 :
        print('地雷')
        for i in frame_list:
            i.bind("<1>", stop)
    else:
        print(bomb_count)
        event.widget.bind("<1>", stop)

i = 0
frame_list = []
for x in range(9):
    for y in range(9):
        frame = Frame(game_frame, width = 30, height = 30, bd = 3, relief = 'raised', bg = 'LightGray')
        frame.bind("<1>", left_click)
        frame.num = i
        frame_list.append(frame)
        frame.grid(row=x, column=y)
        i += 1

def search_bomb(list, num):
    around_list = []
    bomb_count = 0
    if num in list:
        return 9
    if num % 9 == 0:
        around_list.append(num-9)
        around_list.append(num-8)
        around_list.append(num+1)
        around_list.append(num+9)
        around_list.append(num+10)
    elif num % 9 == 8:
        around_list.append(num-10)
        around_list.append(num-9)
        around_list.append(num-1)
        around_list.append(num+8)    
        around_list.append(num+9)    
    elif num < 9:
        around_list.append(num-1)
        around_list.append(num+1)
        around_list.append(num+8)
        around_list.append(num+9)
        around_list.append(num+10)
    elif num > 72:
        around_list.append(num-10)
        around_list.append(num-9)
        around_list.append(num-8)
        around_list.append(num-1)
        around_list.append(num+1)
    else:
        around_list.append(num-10)
        around_list.append(num-9)
        around_list.append(num-8)
        around_list.append(num-1)
        around_list.append(num+1)
        around_list.append(num+8)
        around_list.append(num+9)
        around_list.append(num+10)
    for i in around_list:
        if i in list:
            bomb_count += 1
    return bomb_count

def stop(event):
    pass
    
root.mainloop()

それでは、レッツスタート!!

【STEP8】周囲の地雷の数をマス目上に表示する

現状ではクリックしたマスの周囲の地雷の数をprintでコンソール画面上に
表示するだけになっています。今回はちゃんとマス目上に地雷の数を表示する
ように変更したいと思います。

33行目から50行目のleft_click関数を書き換えます。書き換え前と書き換え後を
比較してみましょう。

≪書き換え前≫

def left_click(event):
    event.widget.configure(relief = 'ridge', bd = '1')
    except_num = event.widget.num
    if len(bomb_list) == 0:
        while len(bomb_list) != 10:
            bomb_num = random.randint(0,80)
            if bomb_num != except_num and (bomb_num in bomb_list) == False:
                bomb_list.append(bomb_num)
        for i in bomb_list:
            frame_list[i].configure(bg = 'red')
    bomb_count = search_bomb(bomb_list, event.widget.num)
    if  bomb_count == 9 :
        print('地雷')
        for i in frame_list:
            i.bind("<1>", stop)
    else:
        print(bomb_count)
        event.widget.bind("<1>", stop)

≪書き換え後≫

def left_click(event):
    event.widget.configure(relief = 'ridge', bd = '1')
    except_num = event.widget.num
    if len(bomb_list) == 0:
        while len(bomb_list) != 10:
            bomb_num = random.randint(0,80)
            if bomb_num != except_num and (bomb_num in bomb_list) == False:
                bomb_list.append(bomb_num)
    bomb_count = search_bomb(bomb_list, event.widget.num)
    if  bomb_count == 9 :
        for i in bomb_list:
            frame_list[i].configure(bg = 'red')
        for i in frame_list:
            i.bind("<1>", stop)
    else:
        bomb_count_label = Label(event.widget, text = bomb_count, bg = 'LightGray') 
        bomb_count_label.place(width = 28, height = 28)
        event.widget.bind("<1>", stop)

書き換え前9行目10行目の地雷の部分を赤色にするコードを、実際に地雷をクリックした際の
条件文の中(書き換え後11行目12行目)に変更しました。

また、書き換え後16行目で周囲の地雷の数を表示するためのラベルを作成しています。
そして17行目でそのラベルを表示しています。packメソッドではなく、placeメソッドを
使っています。placeメソッドを使うとサイズをピクセル単位で指定することができるので、
今回はplaceメソッドにしました。
≪packメソッドの場合≫

≪placeメソッドの場合≫

packメソッドだとどうしてもこのようにサイズがずれてしまいます。

また、ラベルのサイズもマス目よりほんの少しだけ小さくしました。
(マス目は30pxなので、ラベルを28pxに。)

次回は0のマス目をクリックした際に、一気にマスを開く機能を実装したいと思います!

新連載はじまりました!独学で学ぶPython基礎 連載リンク

独学で学ぶ-Pythonプログラミング 連載

Recent News

Recent Tips

Tag Search