Python Tkinter уничтожает все кнопки рядом с выбранной с тем же текстом - PullRequest
0 голосов
/ 16 февраля 2020

Я пытаюсь воссоздать Сапер в python, и я пытаюсь воссоздать, как в игре, если игрок выбирает плитку без чего-либо на ней (в моем коде, плитка с 0), он покажет все плитки рядом с ним, которые не являются минами (в моем коде плитка с X). Я пытался сделать это много раз, но ничего не получалось. Это будет записано в функции autoShow (i, j).

Может ли кто-нибудь помочь (любые другие предложения будут оценены)?

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)

1 Ответ

1 голос
/ 16 февраля 2020

Вы должны использовать рекурсию для запуска show(i-1, j), et c.

Поскольку я запускаю show(i-1, j) без нажатия кнопки, поэтому мне также нужно grid[i][j] = None, чтобы узнать, существует ли кнопка.

Я не знаю, не нужны ли ей другие тесты, в которых место показано.

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

Полный код, который я тестировал

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()
...