Моя программа тральщика работает очень хорошо, пока я не нажму на верхнюю левую плитку. Все выглядит хорошо - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь сделать тральщик в Python с помощью tkinter. Когда программа проверяет наличие бомб, она работает нормально, если только щелчок плитки не равен 0, 0 (вверху слева), и в этом случае программа всегда имеет tileNorth и tileWest True, в результате чего программа проверяет переменную, которая не существует. Это вызывает ошибку и оставляет ячейку 0, 0 пустой. Проверка работает в любой другой плитке, включая углы, только не в верхнем левом углу. Этого не должно быть.

TLDR: Моя программа minesweeper работает просто отлично, но она всегда сбивается с 0, 0 и выдает ошибку. Я не понимаю, в чём дело ...

Ошибка:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
    return self.func(*args)
  File "<string>", line 11, in <lambda>
  File "/home/pi/Documents/Python/Minesweeper/Minesweeper.py", line 133, in tileClicked
    stringVar_{x}_{y}.set(tileValue)""")
  File "<string>", line 56
    if bomb_-1_-1 == True:
              ^
SyntaxError: invalid token

В ней упоминается bomb_-1_-1, который не существует и не может существовать ... Это почему этот оператор if должен работать.

Мой код:


import random
import tkinter

# Functions

def tileClicked(x, y): # Function is ran when a tile is clicked. The tile is defined by the inputted 'x' and 'y' values.

    exec(f"""

global tileNorth, tileEast, tileSouth, tileWest

if y > 0:
    tileNorth = True

else:
    tileNorth = False

if x < game.size[0] - 1:
    tileEast = True

else:
    tileEast = False

if y < game.size[1] - 1:
    tileSouth = True

else:
    tileSouth = False

if x > 0:
    tileWest = True

else:
    tileWest = False""")

    print(f"""{tileNorth}
{tileEast}
{tileSouth}
{tileWest}
DIV""")

    exec(f"""

print("{x}, {y}")

if bomb_{x}_{y} == True:
    stringVar_{x}_{y}.set("Bomb")
    game.failed = True

if x == 0 and y == 0:
    tileValue = int(0)

    if tileNorth == True:

        if tileEast == True:

            if bomb_{x + 1}_{y - 1} == True:
                tileValue += 1

    if tileEast == True:

        if bomb_{x + 1}_{y} == True:
            tileValue += 1

    if tileSouth == True:

        if tileEast == True:

            if bomb_{x + 1}_{y + 1} == True:
                tileValue += 1

        if tileWest == True:

            if bomb_{x - 1}_{y + 1} == True:
                tileValue += 1

        if bomb_{x}_{y + 1} == True:
            tileValue += 1

    if tileWest == True:

        if bomb_{x - 1}_{y} == True:
            tileValue += 1

else:
    tileValue = int(0)

    if tileNorth == True:

        if tileEast == True:

            if bomb_{x + 1}_{y - 1} == True:
                tileValue += 1

        if tileWest == True:

            if bomb_{x - 1}_{y - 1} == True:
                tileValue += 1

        if bomb_{x}_{y - 1} == True:
            tileValue += 1

    if tileEast == True:

        if bomb_{x + 1}_{y} == True:
            tileValue += 1

    if tileSouth == True:

        if tileEast == True:

            if bomb_{x + 1}_{y + 1} == True:
                tileValue += 1

        if tileWest == True:

            if bomb_{x - 1}_{y + 1} == True:
                tileValue += 1

        if bomb_{x}_{y + 1} == True:
            tileValue += 1

    if tileWest == True:

        if bomb_{x - 1}_{y} == True:
            tileValue += 1

    if tileValue == 0:
        tileValue = "Clear"

    stringVar_{x}_{y}.set(tileValue)""")

# Classes

class game:
    title = "Minesweeper"
    bg = "white"
    fg = "black"
    size = [10, 10]
    tileWidth = 3
    tileHeight = 2
    failed = False
    bombFrequency = 4
    flagMode = False

# Execution

window = tkinter.Tk() # The window.
window.title(game.title)
window.config(bg = game.bg)

mainFrame = tkinter.Frame(window, bg = game.bg) # Main frame that everything is located in.

titleFrame = tkinter.Frame(mainFrame, bg = game.bg) # Title frame.
titleLabel = tkinter.Label(titleFrame, bg = game.bg, fg = game.fg, text = game.title, font = "none 20").grid(row = 0, column = 0)
titleFrame.grid(row = 0, column = 0)

tileFrame = tkinter.Frame(mainFrame, bg = game.bg) # Frame where tiles are located.

x = 0
y = 0

for tiles_x in range(game.size[0]): # Generates tiles.

    for tiles_y in range(game.size[1]):

        exec(f"""global tile_{x}_{y}, stringVar_{x}_{y}, bomb_{x}_{y}
bomb_{x}_{y} = random.randint(1, game.bombFrequency)

if bomb_{x}_{y} == 1:
    bomb_{x}_{y} = True

else:
    bomb_{x}_{y} = False

stringVar_{x}_{y} = tkinter.StringVar(tileFrame)
tile_{x}_{y} = tkinter.Button(tileFrame, bg = 'lightgrey', fg = 'black', width = game.tileWidth, height = game.tileHeight, textvariable = stringVar_{x}_{y}, command = lambda: tileClicked({x}, {y})).grid(row = {y}, column = {x})""")

        y += 1

    x += 1
    y = 0

tileFrame.grid(row = 1, column = 0)

mainFrame.pack() # The main frame is packed so everything is centered.

window.mainloop()

Мне все равно, если вы считаете, что динамические c переменные неэффективны, это мой выбор. Я не хочу, чтобы люди комментировали мои методы выполнения задачи ... если только это не вызывает проблемы ...

Спасибо!

1 Ответ

3 голосов
/ 16 января 2020

Использование динамических c переменных - плохая практика, и ваш опыт - хорошая демонстрация того, почему.

Имена переменных не могут иметь знак минус. Знак минус интерпретируется как оператор арифмети c. Таким образом, bomb_-1_-1 интерпретируется как bomb_ - 1_ - 1. Часть bomb_ понимается как имя переменной, 1 - как число, но подчеркивание после этого числа вызывает синтаксическую ошибку.

Это также демонстрирует, что динамический код c не так уж велик: синтаксические ошибки появляются только при определенных обстоятельствах (например, при выборе определенной ячейки).

Быстрое исправление, просто чтобы показать обходной путь, это сначала протестировать значения x и y:

if {x} >= 0 and {y} >= 0 and bomb_{x}_{y} == True:

Вам нужно будет выполнить аналогичные тесты для любого другого места, где вы создаете динамическую ссылку c, например который. Также:

if {x} >= 1 and {y} >= 1 and bomb_{x-1}_{y-1} == True:

... et c.

Но это действительно исправление ужасного дизайна.

Обратите внимание, что даже если только одна из переменных является отрицательной, вы оцените выражение, которое вы на самом деле не намеревались. Вы можете получить это, когда только y == -1: bomb_5_-1. Это не приводит к синтаксической ошибке, но оценивается как bomb_5_ минус 1. Очевидно, что это не предусмотрено алгоритмом.

Вместо динамических переменных c и анализа кода во время выполнения используйте списки. Они могут быть вложенными, чтобы иметь 2D покрытие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...