【问题标题】:Python minesweeper game - user chooses grid size and how many minesPython扫雷游戏 - 用户选择网格大小和多少地雷
【发布时间】:2021-08-17 08:35:40
【问题描述】:

我有以下 python 代码,但我真的很难让它工作。

这是一个终端中的基本扫雷游戏。这个版本与其他版本有点不同,它应该首先询问用户网格有多大,然后要插入多少地雷。剩下的就是你的好老基本扫雷了。

def display():
    for x in range(SIZE):
        if x == 0:
            print(" ", end="")
            for i in range(SIZE):
                print("   " + str(i), end="")
            print("\n  |-" + "--|-" * (SIZE - 1) + "--|")
            print("0 |", end="")
            for y in range(SIZE):
                print(" " + str(BOARD[x][y].status) + "|", end="")
            print("\n  |-" + "--|-" * (SIZE -1) + "--|")
        elif x == SIZE -1:
            print(str(SIZE-1) + " |", end="")
            for y in range(SIZE):
                print(" " + str(BOARD[x][y].status) + "|", end="")
            print("\n  |-" + "--|-" * (SIZE -1) + "--|")
        else:
            print(str(x) + " |", end="")
            for y in range(SIZE):
                print(" " + str(BOARD[x][y].status) + "|", end="")
            print("\n  |-" + "--|-" * (SIZE-1) + "--|")

class Square:
    def __init__(self, x, y):
        self.status = "- "
        self.row = x
        self.column = y
        self.mine = False
        self.neighbours = []
        self.danger = 0

    def status_get(self):
        return this.status

def first_move():
    # establish mine locations, ignoring stating dig
    print("""Where would you like to start?\n""")
    while True:
        a, b = input("Enter an x and y coodinate, comma separated, to dig the first square: ").split(",")
        x = int(a)
        y = int(b)
        if x >= SIZE or y >= SIZE:
            print("Out of bounds, try again.")
            continue
        else:
            for m in range(MINES):
                place_mines(x, y)
            welfare(BOARD[x][y])
            break

def place_mines(x, y):
    # Recursively place mines, ignoring starting square
    global BOARD
    h = random.randint(0, SIZE - 1)
    w = random.randint(0, SIZE - 1)
    if h == x and w == y:
        place_mines(x, y)
    else:
        if not BOARD[h][w].mine:
            BOARD[h][w].mine = True
            for sqr in BOARD[h][w].neighbours:
                sqr.danger += 1
        else:
            place_mines(x, y)

def next_turn():
    # keeps promting to dig, flag, or end the game
    move = input("What would you like to do? ").lower()
    if move == "!quit":
        print("Thank you, come again.")
        quit(0)
    elif move == "d":
        dig()
        display()
    elif move == "f":
        flag()
        display()
    elif move == "r":
        unflag()
        display()
    elif move == "!help":
        print("!quit = Quit game.")
        print("d = Uncover a square.")
        print("f = Plant a flag marking a square as containing a mine.")
        print("r = Remove a flag.")
    else:
        print("You'll have to speak up... Try again.")

def unflag():
    # Unflags a previously flagged square
    while True:
        a, b = input("Supply an x and y coordinate to unflag: ").split(",")
        x = int(a)
        y = int(b)
        if x >= SIZE or y >= SIZE:
            print("Out of bounds, try again.")
            continue
        else:
            global BOARD
            if BOARD[x][y].status == "F ":
                BOARD[x][y].status = "- "
            break

def flag():
    # flag a square to indicate a mine
    while True:
        a, b = input("Supply an x and y coordinate to flag: ").split(",")
        x = int(a)
        y = int(b)
        if x >= SIZE or y >= SIZE:
            print("Out of bounds, try again.") 
            continue
        else:
            global BOARD
            BOARD[x][y].status = "F "
            global FLAGS
            if BOARD[x][y].mine and BOARD[x][y].status == "F ":
                FLAGS += 1
            break

def dig():
    # Uncover a square. If it's a bomb it's game over. Otherwise, reveal nearby squares
    while True:
        a, b = input("Supply an x and y coordinate to dig: ").split(",")
        x = int(a)
        y = int(b)
        if x >= SIZE or y >= SIZE:
            print("Out of bounds, try again.")
            continue
        else:
            if BOARD[x][y].mine is True:
                print("BANG! You have died!")
                for x in range(SIZE):
                    for y in range(SIZE):
                        sqr = BOARD[x][y]
                        if sqr.mine:
                            sqr.status = "@"
                display()
                quit(0)
            else:
                BOARD[x][y].status = "x"
                welfare(BOARD[x][y])
                break


def welfare(sqr, history=[]):
    # update square state after each dig to reveal mine status
    if sqr.danger == 0:
        sqr.status = "x "
        for box in sqr.neighbours:
            if box not in history:
                history.append(box)
                welfare(box, history)
    else:
        if not sqr.mine:
            sqr.status = str(sqr.danger) + " "
        #for box in sqr.neighbours:
        #    if not box.mine:
        #        if box not in history:
        #            history.append(box)
        #            welfare(box, history)

def win_state():
    # is it over, can I go home now?
    global FLAGS
    global MINES
    global BOARD
    correct = 0
    if FLAGS == MINES:
        for x in range(SIZE):
            for y in range(SIZE):
                sqr = BOARD[x][y]
                if sqr.mine and sqr.status == "F ":
                    correct += 1
                    if correct == MINES:
                        print("Congratulations!\n")
                        print("You found " + str(MINES) + " mines and didn't die.")
                        exit(0)
            



def startup():
    # set game parameters, give all the squares their neighbours
    print("It's Minesweeper, how wide do you want the board?")
    global SIZE
    while True:
        SIZE = int(input("Give me a size, between 3 and 10 inclusive "))
        if SIZE not in range(3, 11):
            print("Did I stutter? Try again. ")
            continue
        else:
            global MINES
            while True:
                MINES = int(input("How many mines do you want? "))
                if MINES >= SIZE ** 2:
                    print("Whoa! That's too many. Try Again. ")
                    continue
                else:
                    break
            print("OKAY")
            # initialise an empty board
            global BOARD
            BOARD = [[None for _ in range(SIZE)] for _ in range(SIZE)]
            
            # fill that board with square objects
            for s in range(SIZE):
                for d in range(SIZE):
                    BOARD[s][d] = Square(s, d)
            # link each square to it's neighbour
            
            for a in range(SIZE):
                for b in range(SIZE):
                    sqr = BOARD[a][b]
                    if a == 0:
                        sqr.neighbours.append(BOARD[a + 1][b])
                        if b != SIZE - 1:
                            sqr.neighbours.append(BOARD[a + 1][b + 1])
                            sqr.neighbours.append(BOARD[a][b + 1])
                        if b != 0:
                            sqr.neighbours.append(BOARD[a][b - 1])
                            sqr.neighbours.append(BOARD[a + 1][b - 1])
                    elif a == SIZE - 1:
                        sqr.neighbours.append(BOARD[a - 1][b])
                        if b != SIZE - 1:
                            sqr.neighbours.append(BOARD[a][b + 1])
                            sqr.neighbours.append(BOARD[a - 1][b + 1])
                        if b != 0:
                            sqr.neighbours.append(BOARD[a - 1][b - 1])
                            sqr.neighbours.append(BOARD[a][b - 1])
                    else:
                        sqr.neighbours.append(BOARD[a + 1][b])
                        sqr.neighbours.append(BOARD[a - 1][b])
                        if b != SIZE - 1:
                            sqr.neighbours.append(BOARD[a - 1][b + 1])
                            sqr.neighbours.append(BOARD[a][b + 1])
                            sqr.neighbours.append(BOARD[a + 1][b + 1])
                        if b != 0:
                            sqr.neighbours.append(BOARD[a - 1][b - 1])
                            sqr.neighbours.append(BOARD[a][b - 1])
                            sqr.neighbours.append(BOARD[a + 1][b - 1]) 
                      
                        


startup()
while True:
    next_turn()
    win_state()

【问题讨论】:

  • 到底是什么问题?
  • 它循环初始化并且从未真正开始游戏。所以它会询问棋盘的大小,然后是地雷的数量,然后它会循环回到再次询问棋盘的大小。
  • 没有什么可以阻止startup函数中的第一个while True:循环。
  • 你不需要global X,除非你有一个声明X = something。您可以使用全局变量,甚至可以修改全局变量,只是无法替换它们。

标签: python python-3.x


【解决方案1】:

这是您的代码经过稍微重新组织的版本。你忘了打电话给first_move。您在 status 是否必须包含尾随空白方面不一致(我没有使用它)。如果改变你所有的while 循环,那么他们break 就成功了;这样可以避免混淆。注意这里只有一个global

import random

def display():
    for x in range(SIZE):
        if x == 0:
            print(" ", end="")
            for i in range(SIZE):
                print("   " + str(i), end="")
            print("\n  |-" + "--|-" * (SIZE - 1) + "--|")
            print("0 |", end="")
            for y in range(SIZE):
                print(" " + str(BOARD[x][y].status) + " |", end="")
            print("\n  |-" + "--|-" * (SIZE -1) + "--|")
        elif x == SIZE -1:
            print(str(SIZE-1) + " |", end="")
            for y in range(SIZE):
                print(" " + str(BOARD[x][y].status) + " |", end="")
            print("\n  |-" + "--|-" * (SIZE -1) + "--|")
        else:
            print(str(x) + " |", end="")
            for y in range(SIZE):
                print(" " + str(BOARD[x][y].status) + " |", end="")
            print("\n  |-" + "--|-" * (SIZE-1) + "--|")

class Square:
    def __init__(self, x, y):
        self.status = "-"
        self.row = x
        self.column = y
        self.mine = False
        self.neighbours = []
        self.danger = 0

    def status_get(self):
        return this.status

def first_move():
    # establish mine locations, ignoring stating dig
    print("""Where would you like to start?\n""")
    while True:
        a, b = input("Enter an x and y coodinate, comma separated, to dig the first square: ").split(",")
        x = int(a)
        y = int(b)
        if x < SIZE and y < SIZE:
            break
        print("Out of bounds, try again.")
    for m in range(MINES):
        place_mines(x, y)
    welfare(BOARD[x][y])

def place_mines(x, y):
    # Recursively place mines, ignoring starting square
    h = random.randint(0, SIZE - 1)
    w = random.randint(0, SIZE - 1)
    if h == x and w == y:
        place_mines(x, y)
    else:
        if not BOARD[h][w].mine:
            BOARD[h][w].mine = True
            for sqr in BOARD[h][w].neighbours:
                sqr.danger += 1
        else:
            place_mines(x, y)

def next_turn():
    # keeps promting to dig, flag, or end the game
    display()
    move = input("What would you like to do? ").lower()
    if move == "!quit":
        print("Thank you, come again.")
        quit(0)
    elif move == "d":
        dig()
    elif move == "f":
        flag()
    elif move == "r":
        unflag()
    elif move == "!help":
        print("!quit = Quit game.")
        print("d = Uncover a square.")
        print("f = Plant a flag marking a square as containing a mine.")
        print("r = Remove a flag.")
    else:
        print("You'll have to speak up... Try again.")

def unflag():
    # Unflags a previously flagged square
    while True:
        a, b = input("Supply an x and y coordinate to unflag: ").split(",")
        x = int(a)
        y = int(b)
        if x < SIZE and y < SIZE:
            break
        print("Out of bounds, try again.")
    if BOARD[x][y].status == "F":
        BOARD[x][y].status = "-"

def flag():
    # flag a square to indicate a mine
    while True:
        a, b = input("Supply an x and y coordinate to flag: ").split(",")
        x = int(a)
        y = int(b)
        if x < SIZE and y < SIZE:
            break
        print("Out of bounds, try again.") 
    BOARD[x][y].status = "F"
    global FLAGS
    if BOARD[x][y].mine and BOARD[x][y].status == "F":
        FLAGS += 1

def dig():
    # Uncover a square. If it's a bomb it's game over. Otherwise, reveal nearby squares
    while True:
        a, b = input("Supply an x and y coordinate to dig: ").split(",")
        x = int(a)
        y = int(b)
        if x < SIZE and y < SIZE:
            break
        print("Out of bounds, try again.")
    if BOARD[x][y].mine:
        print("BANG! You have died!")
        for x in range(SIZE):
            for y in range(SIZE):
                sqr = BOARD[x][y]
                if sqr.mine:
                    sqr.status = "@"
        display()
        quit(0)
    else:
        BOARD[x][y].status = "x"
        welfare(BOARD[x][y])


def welfare(sqr, history=[]):
    # update square state after each dig to reveal mine status
    if sqr.danger == 0:
        sqr.status = "x"
        for box in sqr.neighbours:
            if box not in history:
                history.append(box)
                welfare(box, history)
    else:
        if not sqr.mine:
            sqr.status = str(sqr.danger)
        #for box in sqr.neighbours:
        #    if not box.mine:
        #        if box not in history:
        #            history.append(box)
        #            welfare(box, history)

def win_state():
    # is it over, can I go home now?
    correct = 0
    if FLAGS == MINES:
        for x in range(SIZE):
            for y in range(SIZE):
                sqr = BOARD[x][y]
                if sqr.mine and sqr.status == "F":
                    correct += 1
                    if correct == MINES:
                        print("Congratulations!\n")
                        print("You found " + str(MINES) + " mines and didn't die.")
                        exit(0)
            



def startup():
    # set game parameters, give all the squares their neighbours
    print("It's Minesweeper, how wide do you want the board?")
    while True:
        SIZE = int(input("Give me a size, between 3 and 10 inclusive "))
        if SIZE in range(3, 11):
            break
        print("Did I stutter? Try again. ")

    while True:
        MINES = int(input("How many mines do you want? "))
        if MINES < SIZE ** 2:
            break
        print("Whoa! That's too many. Try Again. ")
    print("OKAY")
    # initialise an empty board
    BOARD = [[None for _ in range(SIZE)] for _ in range(SIZE)]
    
    # fill that board with square objects
    BOARD = []
    for s in range(SIZE):
        row = []
        for d in range(SIZE):
            row.append( Square(s, d) )
        BOARD.append(row)
    # link each square to it's neighbour
    
    for a in range(SIZE):
        for b in range(SIZE):
            sqr = BOARD[a][b]
            if a == 0:
                sqr.neighbours.append(BOARD[a + 1][b])
                if b != SIZE - 1:
                    sqr.neighbours.append(BOARD[a + 1][b + 1])
                    sqr.neighbours.append(BOARD[a][b + 1])
                if b != 0:
                    sqr.neighbours.append(BOARD[a][b - 1])
                    sqr.neighbours.append(BOARD[a + 1][b - 1])
            elif a == SIZE - 1:
                sqr.neighbours.append(BOARD[a - 1][b])
                if b != SIZE - 1:
                    sqr.neighbours.append(BOARD[a][b + 1])
                    sqr.neighbours.append(BOARD[a - 1][b + 1])
                if b != 0:
                    sqr.neighbours.append(BOARD[a - 1][b - 1])
                    sqr.neighbours.append(BOARD[a][b - 1])
            else:
                sqr.neighbours.append(BOARD[a + 1][b])
                sqr.neighbours.append(BOARD[a - 1][b])
                if b != SIZE - 1:
                    sqr.neighbours.append(BOARD[a - 1][b + 1])
                    sqr.neighbours.append(BOARD[a][b + 1])
                    sqr.neighbours.append(BOARD[a + 1][b + 1])
                if b != 0:
                    sqr.neighbours.append(BOARD[a - 1][b - 1])
                    sqr.neighbours.append(BOARD[a][b - 1])
                    sqr.neighbours.append(BOARD[a + 1][b - 1]) 
    return SIZE, MINES, BOARD
              
                
FLAGS = 0

SIZE, MINES, BOARD = startup()
first_move()
while True:
    next_turn()
    win_state()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 2013-04-14
    • 2021-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多