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



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

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

并输入这3行5次以获得游戏所需的5艘船,但我觉得必须有一种更清晰的方式来输入这些信息,也许是一个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、做点什么?任何建议都将非常感激。谢谢你!

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

尝试只在没有船的地方放置船:

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的网格中只留下一个开放空间。

就单元测试而言,如果您将此代码设置为传递要放置的船舶数量的函数,以及调用该函数并放置100艘船舶的测试函数,那么它可以验证每个网格位置都被访问并填充。

您对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

关于单元测试,其思想是调用代码中的函数并断言结果如您所期望的。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()

然后,假设您在将来的某个时候修改了create_ships函数。如果断言失败,你就知道你搞砸了一些事情,你可以回去更仔细地看一看。虽然这里不是这样,但单元测试应该是隔离的和幂等的(意思是无论你运行多少次,结果都不会改变)。

由于这是一个学校项目,我将把实现留给您(以及其他单元测试),但您肯定是在正确的方向上。好运!

相关内容

  • 没有找到相关文章

最新更新