简化在 Python 战舰游戏中放置船只并进行单元测试的代码

问题描述 投票:0回答:2

我目前正在做一个用 Python 构建游戏 Battleship 的课程项目。这里的另一位用户慷慨地帮助我理解了我的板的编码,现在我已经到了随机输入船('S')到板上位置的步骤。对于这个项目,每艘船,'S' 仅限于板上的一个空间。我开发了代码:

randomRow = random.randint(0, grid_size - 1)
randomCol = random.randint(0, grid_size - 1)  
myBoard[randomRow][randomCol] = 'S'

并输入这 3 行五次以获得我的游戏所需的五艘船,但是我觉得必须有一种更简洁的方式来输入此信息,也许使用 while 循环?除此之外,我的老师还要求我们确认,如果放置了一艘船“S”,则不得在同一地点进入其他船。如果我输入上面的代码五次,我总是会得到五个不同的位置,但我猜测如果我使用 while 循环或其他东西来放置船只,我将需要一个额外的参数来确保每艘船都放置在不同的地方,我一直在想办法做到这一点。

最后,我们被要求为这一步编写两个单元测试。一个将检查是否放置了适当数量的船只 (5),另一个将检查其他空间是否为空白(在我的代码中,用 '.' 表示开放水域)。我对单元测试一无所知,想知道是否有人可以为初学者分享关于什么是单元测试、如何实施单元测试等方面的好资源。示例对我也很有帮助。

对于上下文,这里是我目前拥有的这个程序的完整代码:

import random

# Legend:
# 1. "." = water
# 2. "S" = ship position
# 3. "O" = water that was shot with bullet, a miss because it hit no ship
# 4. "X" = ship sunk!

#global variable for grid size
grid_size = 10
#global variable for grid
myBoard = [['.']*grid_size for i in range(grid_size)]
# display the grid (2d array)

def main():
    # Call drawBoard function with myBoard
    drawBoard(myBoard)
    user_guess(myBoard)

def drawBoard(myBoard):
    # Print header
    print(end="  ")
    for i in range(grid_size):
        print(i, end=" ")
    print()

    # Print rows
    for i in range(grid_size):
        print(i, end=" ")
        for j in range(grid_size):
            print(myBoard[i][j], end=" ") # change grid to myBoard
        print()
      
# Place ships
randomRow = random.randint(0, grid_size - 1)
randomCol = random.randint(0, grid_size - 1)  
myBoard[randomRow][randomCol] = 'S'

randomRow = random.randint(0, grid_size - 1)
randomCol = random.randint(0, grid_size - 1)  
myBoard[randomRow][randomCol] = 'S'

randomRow = random.randint(0, grid_size - 1)
randomCol = random.randint(0, grid_size - 1)  
myBoard[randomRow][randomCol] = 'S'

randomRow = random.randint(0, grid_size - 1)
randomCol = random.randint(0, grid_size - 1)  
myBoard[randomRow][randomCol] = 'S'

randomRow = random.randint(0, grid_size - 1)
randomCol = random.randint(0, grid_size - 1)  
myBoard[randomRow][randomCol] = 'S'

# Call main function
main()

在尝试弄清楚如何将我上面的代码与 while 循环结合起来时,我在 Youtube 上找到了一个示例,并尝试将其采用到我的程序中,如下所示:

def create_ships(myBoard):
    for ship in range(5):
        while myBoard[ship_row][ship_column] == "S":
            ship_row, ship_column = get_ship_location()
        myBoard[ship_row][ship_column] = "S"

但是不确定将与此功能相关的前三行代码放在哪里。我尝试将它放在函数中,但是当我运行代码时,我的飞船没有打印出来。我不知道如何将这两个元素结合起来。我应该在发货时附上一份声明吗< 5, do something? Any advice would be greatly appreciated. Thank you!

python-3.x unit-testing while-loop simplify
2个回答
1
投票

您当前的代码可以将两艘船放在同一位置,但几率很低。

如果该地点还没有一艘船,试试这个只放置一艘船:

for _ in range(5):
    while True:  # continuously loop...
        randomRow = random.randrange(grid_size)
        randomCol = random.randrange(grid_size)
        # ...until an open space is selected
        if myBoard[randomRow][randomCol] == '.':
            break
    myBoard[randomRow][randomCol] = 'S'

放置更多的船只,比如 99 艘,看看它是否正常工作,并且在 10x10 的网格中只留下一个空地。


0
投票

您对

create_ships
函数有了一个良好的开端,并且您正在使用 while 循环。就目前而言,您的代码可以将一艘船放在另一艘船之上。因为我们正在处理随机点,所以防止这种情况的最简单方法是检查是否已经有一艘船在被选中的随机点。如果是这样,请再试一次。通过使用您已有的代码并应用您建议的 while 循环来调整您的
create_ships
功能:

def create_ships():
    ships = 0
    while ships < 5:
        randomRow = random.randint(0, grid_size - 1)
        randomCol = random.randint(0, grid_size - 1)
        if myBoard[randomRow][randomCol] == '.':
            myBoard[randomRow][randomCol] = 'S'
            ships += 1

你只需要调用一次就可以创建5艘船。

关于单元测试,想法是调用代码中的函数并断言结果如您所愿。 Python 有一个内置的单元测试库,简称为

unittest
,它提供了你需要做的一切以及更多,但对于你的项目来说,简单地编写你自己的测试函数可能更容易。例如,您可以断言
create_ships
函数恰好创建了 5 艘船,并像在
drawBoard
函数中一样通过遍历您的棋盘来完成此操作,并在每次遇到“S”时进行计数。设置看起来类似于:

def test_create_ships():
    #Call the function that you're testing
    create_ships()
    num_ships = 0
    #Count the ships
    #Your code here...
    return num_ships == 5

...

assert test_create_ships()

因为这是一个学校项目,我会把实施留给你(以及其他单元测试),但你肯定会朝着正确的方向前进。祝你好运!

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.