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


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

今回は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')

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

root.mainloop()

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

【STEP6】クリックした場所の周りに地雷が何個あるか判定する

それでは地雷の個数を判定する関数を定義していきます。
もう力技でゴリゴリ書いていきます。前回までの上記コードの53行目と55行目の間
に追加していきましょう。

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

これが最適な処理なのかどうかは分かりませんが…とりあえず正しい地雷の判定はできます。
第一引数のlistには地雷番号のリストであるbomb_list、第二引数のnumにはクリックしたマス目
の番号が渡されることを想定しています。

4行目~5行目で、地雷が配置されているマスをクリックした際の処理を記述しています。
クリックしたマス目の番号がリストの中に存在するパターンですね。
その場合は数字の「9」を返すようにしています。

6行目~11行目では、マス目が9の倍数、つまり左端の列の判定をしています。
num-9でクリックしたマス目の真上のマス目を、num-8で右上のマス目を、というように
周囲のマス目の番号を取得し、その値をaround_listに格納しています。

同様に12行目~17行目は右端を、18行目~23行目は上端を、24行目~29行目は下端を、
30行目~28行目はそれ以外の端ではないマス目でのそれぞれの処理を記述しています。

39~41行目で繰り返し処理を行っています。
周囲のマス目の番号をfor-in文で1つずつ取得し、その値が地雷番号のリストに
あるかどうかを判定しています。ある場合は地雷の数を表すbomb_countを1ずつ増やしていきます。

最後にその地雷の数を返しています。

では、次にこの関数を実際に実行して、マス目をクリックした際に地雷の数を表示するように
しましょう。
一番上の前回までのコードの、43行目の部分に次のコードを追記します。

    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('地雷')
    else:
        print(bomb_count)

インデントが分かりにくくなるのでif文の頭から書きましたが、実際に追記している部分は
8行目~12行目だけです。

定義したsearch_bomb関数を実行し、戻り値をbomb_countに代入しています。
地雷のマスをクリックしたときは9を返すようにしていたと思います(関数の4行目、5行目の部分)
ので、9行目10行目の条件文で値が9だった場合は「地雷」と表示するようにしています。

それ以外は普通に数値を返すようにしています。

これで地雷判定の完成です!
実際に実行してみると、周囲の地雷の個数がコンソール上に表示されるはずです。

今回はこれで終わりにしたいと思います!

  • このエントリーをはてなブックマークに追加

PAGE TOP