I'm tying to recreate Minesweeper in python and i'm trying to recreate how in the game if the player chooses a tile without anything on it (In my code, a tile that has a 0) it will reveal all the tiles close to it that aren't mines (In my code, a tile that has an X). I've tried to to do this many times but nothing has worked. It would be written in the autoShow(i, j) function.
Can anyone help (Any other suggestions would be appreciated)?
import tkinter as tk
from tkinter import messagebox
from random import randint
def difficulty(diff):
global rows, cols, mines, size
if diff == 1:
rows = 9
cols = 9
mines = 10
size = "341x368"
elif diff == 2:
rows = 16
cols = 16
mines = 40
size = "606x654"
else:
rows = 16
cols = 30
mines = 99
size = "1139x606"
play()
def firstT(l, m):
global firstTurn
if firstTurn:
mPos = []
firstTurn = False
for x in range(mines):
minesLoop = True
while minesLoop:
x = randint(0, rows - 1)
y = randint(0, cols - 1)
if grid_text[x][y].get() != "X":
near = False
if near == False:
mPos.append([x, y])
minesLoop = False
grid_text[x][y].set("X")
[[labels[i][j].configure(text = grid_text[i][j].get()) for j in range(cols)] for i in range(rows)]
for i in range(rows):
for j in range(cols):
nearby = 0
for ii in range(i - 1, i + 2):
for jj in range(j - 1, j + 2):
if ii >= 0 and jj >= 0 and ii < rows and jj < cols:
if labels[i][j]["text"] == "" and labels[ii][jj]["text"] == "X" and not (i, j) in mPos:
nearby += 1
if labels[i][j]["text"] != "X":
grid_text[i][j] = str(nearby)
labels[i][j].configure(text = grid_text[i][j])
def autoShow(i, j):
pass
def show(i, j):
global gameOver
if gameOver:
return
firstT(i, j)
if labels[i][j]["text"] == "0":
autoShow(i, j)
elif labels[i][j]["text"] == "X":
messagebox.showinfo("Lose!", "You Lose")
game.focus_force()
gameOver = True
else:
grid[i][j].destroy()
def play():
global firstTurn, gameOver, game, grid, grid_text, labels
firstTurn = True
gameOver = False
game = tk.Toplevel(root)
game.title("Minesweeper")
game.geometry(size)
grid_text = [[tk.StringVar() for j in range(cols)] for i in range(rows)]
labels = [[tk.Label(game, text = grid_text[i][j].get()) for j in range(cols)] for i in range(rows)]
[[labels[i][j].grid(row = i, column = j) for j in range(cols)] for i in range(rows)]
grid = [[tk.Button(game, width = 4, height = 2, command = lambda i = i, j = j: show(i, j)) for j in range(cols)] for i in range(rows)]
[[grid[i][j].grid(row = i, column = j) for j in range(cols)] for i in range(rows)]
xoutside = [[tk.Button(game, width = 4, height = 2).grid(row = i, column = cols + 1) for j in range(cols)] for i in range(rows)]
youtside = [[tk.Button(game, width = 4, height = 2).grid(row = rows + 1, column = j) for j in range(cols)] for i in range(rows)]
diff(1)
You have to use recursion to run show(i-1, j)
, etc.
Because I run show(i-1, j)
without clicking button so I need also grid[i][j] = None
to recognize if button still exists.
I don't know if it doesn't need other tests in which place is shown.
def autoShow(i, j):
grid[i][j].destroy()
grid[i][j] = None
if i > 0:
show(i-1, j)
if j > 0:
show(i, j-1)
if i < rows-1:
show(i+1, j)
if j < cols-1:
show(i, j+1)
if i > 0 and j > 0:
show(i-1, j-1)
if i > 0 and j < cols-1:
show(i-1, j+1)
if i < rows-1 and j < cols-1:
show(i+1, j+1)
if i < rows-1 and j > 0:
show(i+1, j-1)
def show(i, j):
global gameOver
if gameOver:
return
firstT(i, j)
# check if button still exists
if grid[i][j] is None:
return
if labels[i][j]["text"] == "0":
autoShow(i, j)
elif labels[i][j]["text"] == "X":
grid[i][j].destroy()
grid[i][j] = None
messagebox.showinfo("Lose!", "You Lose")
game.focus_force()
gameOver = True
else:
grid[i][j].destroy()
grid[i][j] = None
Full code which I tested
import tkinter as tk
from tkinter import messagebox
from random import randint
def difficulty(diff):
global rows, cols, mines, size
if diff == 1:
rows = 9
cols = 9
mines = 10
size = "341x368"
elif diff == 2:
rows = 16
cols = 16
mines = 40
size = "606x654"
else:
rows = 16
cols = 30
mines = 99
size = "1139x606"
play()
def firstT(l, m):
global firstTurn
if firstTurn:
mPos = []
firstTurn = False
for x in range(mines):
minesLoop = True
while minesLoop:
x = randint(0, rows - 1)
y = randint(0, cols - 1)
if grid_text[x][y].get() != "X":
near = False
if near == False:
mPos.append([x, y])
minesLoop = False
grid_text[x][y].set("X")
[[labels[i][j].configure(text = grid_text[i][j].get()) for j in range(cols)] for i in range(rows)]
for i in range(rows):
for j in range(cols):
nearby = 0
for ii in range(i - 1, i + 2):
for jj in range(j - 1, j + 2):
if ii >= 0 and jj >= 0 and ii < rows and jj < cols:
if labels[i][j]["text"] == "" and labels[ii][jj]["text"] == "X" and not (i, j) in mPos:
nearby += 1
if labels[i][j]["text"] != "X":
grid_text[i][j] = str(nearby)
labels[i][j].configure(text = grid_text[i][j])
def autoShow(i, j):
grid[i][j].destroy()
grid[i][j] = None
if i > 0:
show(i-1, j)
if j > 0:
show(i, j-1)
if i < rows-1:
show(i+1, j)
if j < cols-1:
show(i, j+1)
if i > 0 and j > 0:
show(i-1, j-1)
if i > 0 and j < cols-1:
show(i-1, j+1)
if i < rows-1 and j < cols-1:
show(i+1, j+1)
if i < rows-1 and j > 0:
show(i+1, j-1)
def show(i, j):
global gameOver
if gameOver:
return
firstT(i, j)
if grid[i][j] is None:
return
if labels[i][j]["text"] == "0":
autoShow(i, j)
elif labels[i][j]["text"] == "X":
grid[i][j].destroy()
grid[i][j] = None
messagebox.showinfo("Lose!", "You Lose")
game.focus_force()
gameOver = True
else:
grid[i][j].destroy()
grid[i][j] = None
def play():
global firstTurn, gameOver, game, grid, grid_text, labels
firstTurn = True
gameOver = False
game = tk.Toplevel(root)
game.title("Minesweeper")
game.geometry(size)
grid_text = [[tk.StringVar() for j in range(cols)] for i in range(rows)]
labels = [[tk.Label(game, text = grid_text[i][j].get()) for j in range(cols)] for i in range(rows)]
[[labels[i][j].grid(row = i, column = j) for j in range(cols)] for i in range(rows)]
grid = [[tk.Button(game, width = 4, height = 2, command = lambda i = i, j = j: show(i, j)) for j in range(cols)] for i in range(rows)]
[[grid[i][j].grid(row = i, column = j) for j in range(cols)] for i in range(rows)]
xoutside = [[tk.Button(game, width = 4, height = 2).grid(row = i, column = cols + 1) for j in range(cols)] for i in range(rows)]
youtside = [[tk.Button(game, width = 4, height = 2).grid(row = rows + 1, column = j) for j in range(cols)] for i in range(rows)]
root = tk.Tk()
difficulty(1)
root.mainloop()