質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1615閲覧

『python 初心者』pythonでマインスイーパーを作成しています。リストの範囲の外を指定しないようにしたいです。

Yutaro

総合スコア1

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/05/09 08:14

編集2022/05/09 08:17

20*20 のマインスイーパーを作成しているのですが、
①周辺マス(8マス)が空白であることを判定する再帰処理で、20*20のリストの範囲外を判定してしまった時に”index 20 is out of bounds for axis 0 with size 20”とエラーが起きる。
②爆弾が置いてあるマスの周り8マスに爆弾の数を表示する処理で、下1行と右一列に数字が表示されないバグが起きてしまいます。

リストの範囲外を判定しないようにするにはどうしたら良いのでしょうか?

ご教示いただければ幸いです。

以下がコードとなっています。
(1部抜粋しております)

python

1import tkinter as tk 2import math 3import random 4from tkinter import messagebox 5import numpy as np 6 7 8canvas = None 9#ボードの情報を格納するリスト 10cells = np.array([[0 for i in range(20)]for j in range(20)]) 11#ますが開いてるかを判定するリスト 12open_cells = np.array([[0 for i in range(20)]for j in range(20)]) 13bomb_count = 0 14open_count = 0 15 16BOM = 20 17SQUARE_LENGTH = 30 18RADIUS = SQUARE_LENGTH / 2 - 5 19POSITION = {"x": 8, "y": 8} 20BORDER_WIDTH = 2 21NUMBER = 20 22LENGTH = SQUARE_LENGTH * NUMBER + BORDER_WIDTH * NUMBER 23CELL_DIFF_NUMBERS = [ [-1, -1], [0, -1], [1, -1], 24 [-1, 0], [1, 0], 25 [-1, 1], [0, 1], [1, 1] ] 26 27def set_field(): 28 canvas.create_rectangle(POSITION["x"], POSITION["y"], LENGTH + POSITION["x"], LENGTH + POSITION["y"], tag="rect_1", fill="darkgray", width=BORDER_WIDTH) 29 30 for i in range(NUMBER - 1): 31 x = POSITION["x"] + SQUARE_LENGTH * (i + 1) + BORDER_WIDTH * i + BORDER_WIDTH 32 y = POSITION["y"] + SQUARE_LENGTH * (i + 1) + BORDER_WIDTH * i + BORDER_WIDTH 33 canvas.create_line(x, POSITION["y"], x, LENGTH + POSITION["y"], width=BORDER_WIDTH) 34 canvas.create_line(POSITION["x"], y, LENGTH + POSITION["x"], y, width=BORDER_WIDTH) 35 36def set_bomb(): 37 global bomb_count 38 while bomb_count < BOM: 39 x = random.randint(0, NUMBER - 1) 40 y = random.randint(0, NUMBER - 1) 41 if cells[y][x] == 0: 42 cells[y][x] = -1 43 set_item("bom", x, y) 44 bomb_count += 1 45 46def count_cell(): 47 for x in range(NUMBER - 1): 48 for y in range(NUMBER - 1): 49 if cells[y][x] == -1: 50 continue 51 count = 0 52 for arround_x in range(-1,2): 53 for arround_y in range(-1,2): 54 if cells[y + arround_y][x + arround_x] == -1: 55 count += 1 56 cells[y][x] = count 57 set_item(count, x, y) 58 59 60def set_item(kind, x, y): 61 center_x = POSITION["x"] + BORDER_WIDTH * x + BORDER_WIDTH / 2 + SQUARE_LENGTH * x + SQUARE_LENGTH / 2 62 center_y = POSITION["y"] + BORDER_WIDTH * y + BORDER_WIDTH / 2 + SQUARE_LENGTH * y + SQUARE_LENGTH / 2 63 64 canvas.create_rectangle(center_x - SQUARE_LENGTH / 2, center_y - SQUARE_LENGTH / 2, center_x + SQUARE_LENGTH / 2, center_y + SQUARE_LENGTH / 2,tag="none", fill="white", width=0) 65 66 if kind != None: 67 if kind == "bom": 68 canvas.create_rectangle(center_x - SQUARE_LENGTH / 2, center_y - SQUARE_LENGTH / 2, center_x + SQUARE_LENGTH / 2, center_y + SQUARE_LENGTH / 2, fill="pink", width=0, tag="mine") 69 canvas.create_oval(center_x - RADIUS, center_y - RADIUS, center_x + RADIUS, center_y + RADIUS, fill="red", width=0, tag="mine") 70 elif kind == "F": 71 canvas.create_rectangle(center_x - SQUARE_LENGTH / 2, center_y - SQUARE_LENGTH / 2, center_x + SQUARE_LENGTH / 2, center_y + SQUARE_LENGTH / 2, tag="flag", fill="lightgray", width=0) 72 canvas.create_text(center_x, center_y, text=kind, justify="center", font=("F", 25), tag="flag", fill="red") 73 elif kind == "B": 74 canvas.create_rectangle(center_x - SQUARE_LENGTH / 2, center_y - SQUARE_LENGTH / 2, center_x + SQUARE_LENGTH / 2, center_y + SQUARE_LENGTH / 2, tag="flag", fill="darkgray", width=0) 75 else: 76 canvas.create_rectangle(center_x - SQUARE_LENGTH / 2, center_y - SQUARE_LENGTH / 2, center_x + SQUARE_LENGTH / 2, center_y + SQUARE_LENGTH / 2,tag="count_text", fill="cyan", width=0) 77 canvas.create_text(center_x, center_y, text=kind, justify="center", font=("", 25),tag="count_text") 78 79def point_to_numbers(event_x, event_y): 80 x = math.floor((event_x - POSITION["x"]) / (SQUARE_LENGTH + BORDER_WIDTH)) 81 y = math.floor((event_y - POSITION["y"]) / (SQUARE_LENGTH + BORDER_WIDTH)) 82 return x, y 83 84 85def create_canvas(): 86 root = tk.Tk() 87 root.geometry(f"""{LENGTH + POSITION["x"] * 2}x{LENGTH + POSITION["y"] * 2}""") 88 root.title("マインスイーパー") 89 canvas = tk.Canvas(root,relief=tk.RAISED, width=(LENGTH + POSITION["x"]), height=(LENGTH + POSITION["y"])) 90 canvas.place(x=0, y=0) 91 92 return root, canvas 93 94 95def game_over(): 96 canvas.itemconfig("rect_1", fill="") 97 canvas.itemconfig("none", fill="") 98 canvas.delete("flag") 99 messagebox.showerror("game_over", "爆弾をクリックしてしまった。。") 100 101def game_clear(): 102 if cells.size - bomb_count == open_count: 103 canvas.itemconfig("rect_1", fill="") 104 canvas.itemconfig("none", fill="") 105 canvas.delete("flag") 106 messagebox.showinfo("game clear!", "ゲームをクリアしました!") 107 108 109def click(event): 110 x, y = point_to_numbers(event.x, event.y) 111 open_cell(x, y) 112 open_number(x, y) 113 game_clear() 114 115def open_cell(x, y): 116 global open_count 117 if open_cells[y][x] != 1: 118 if cells[y][x] == 0: 119 set_item(None, x, y) 120 open_cells[y][x] = 1 121 open_count += 1 122 for cell_diff_number in CELL_DIFF_NUMBERS: 123 diff = cell_diff_number 124 if y >= 0 and y < NUMBER and x >= 0 and x < NUMBER: 125 if cells[y + diff[1]][x + diff[0]] == 0: 126 item = None 127 open_cell(x + diff[0], y + diff[1]) 128 else: 129 item = cells[y + diff[1]][x + diff[0]] 130 set_item(item, x + diff[0], y + diff[1]) 131 if open_cells[y + diff[1]][x + diff[0]] != 1: 132 open_count += 1 133 open_cells[y + diff[1]][x + diff[0]] = 1 134 135def open_number(x, y): 136 global open_count 137 if open_cells[y][x] != 1: 138 if cells[y][x] == -1: 139 game_over() 140 else: 141 set_item(cells[y][x], x, y) 142 open_cells[y][x] = 1 143 open_count += 1 144 145def flag(event): 146 x,y = point_to_numbers(event.x, event.y) 147 if open_cells[y][x] == 0: 148 set_item("F", x, y) 149 open_cells[y][x] = -1 150 elif open_cells[y][x] == -1: 151 set_item("B", x, y) 152 open_cells[y][x] = 0 153 154def play(): 155 global canvas 156 root, canvas = create_canvas() 157 set_bomb() 158 count_cell() 159 set_field() 160 canvas.bind("<Button-1>", lambda event: click(event)) 161 canvas.bind("<Button-2>", lambda event: flag(event)) 162 root.mainloop() 163 164play()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

①周辺マス(8マス)が空白であることを判定する再帰処理で、20*20のリストの範囲外を判定してしまった時に”index 20 is out of bounds for axis 0 with size 20”とエラーが起きる。

他の方の回答の通り、範囲外にアクセスしないように「いちいち確認してから」アクセスする必要があります。範囲外かどうかの判定を含めた値の取得用の関数を作るとすっきりしますね。
CELL_DIFF_NUMBERSを中心座標を与えて返すような関数もいいかもしれませんね。

また、そもそものデータに番兵を入れる方法もあります。この場合は、盤面より一回り大きいデータ(22x22)を用意して外周には何も入れず、表示対象にもしないのです。 ロジックをすっきりさせることができます。

②爆弾が置いてあるマスの周り8マスに爆弾の数を表示する処理で、下1行と右一列に数字が表示されないバグが起きてしまいます。

以下の場所で19個しか回していないからでしょう。領域外になるのを避けているのだと思いますが、対象方法が違うのでしょう。

python

1def set_field(): 2 # 略 3 for i in range(NUMBER - 1):

投稿2022/05/09 09:39

TakaiY

総合スコア12769

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Yutaro

2022/05/11 05:05

上手く動かせることができました! ご丁寧にありがとうございました。
guest

0

リストをアクセスする際に、そのリストのサイズをチェックして、そこから外れるようなら、アクセスしないようにすればよろしい

投稿2022/05/09 08:43

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問