我想写一个控制台海战,现在我只显示玩家字段。
using System;
class Program
{
static int fieldSize = 10;
static char[,] PlayerField = new char[fieldSize, fieldSize];
static char[,] OpponentField = new char[fieldSize, fieldSize];
static Random rnd = new Random();
static void Main(string[] args)
{
InitializateField(PlayerField);
InitializateField(OpponentField);
PrintField(PlayerField, "Поле игрока:");
}
static void InitializateField(char [,] field)
{
for (int i = 0; i < fieldSize; ++i)
{
for (int j = 0; j < fieldSize; ++j)
{
field[i,j] = '~';
}
}
}
static void PrintField(char[,] field, string nameOfField)
{
Console.WriteLine(nameOfField);
Console.Write(" ");
for (int i = 0; i < fieldSize; ++i)
Console.Write($"{i + 1} ");
Console.WriteLine();
for (int i = 0; i < fieldSize; ++i)
{
Console.Write($"{(char)('A' + i)} ");
for (int j = 0; j < fieldSize; ++j)
{
Console.Write($"{field[i,j]} ");
}
Console.WriteLine();
}
}
}
我真的不明白如何在场上安排船只,我所能做的就是自己随机安排船只 10 次,然后在 (0, 9) 范围内调用随机,对于每个值都会有case
它的值自己手动放置。那么如何理解在战场上放置船只的算法呢?
以下是放置船只的方法:
static void PlaceShips(char[,] field)
{
PlaceShip(field, 4);
for (int i = 0; i < 2; i++) PlaceShip(field, 3);
for (int i = 0; i < 3; i++) PlaceShip(field, 2);
for (int i = 0; i < 4; i++) PlaceShip(field, 1);
}
static void PlaceShip(char[,] field, int size)
{
bool placed = false;
while (!placed)
{
// Выбираем случайное направление: 0 - горизонтально, 1 - вертикально
int direction = rnd.Next(2);
// Случайные координаты для начальной точки корабля
int row = rnd.Next(fieldSize);
int col = rnd.Next(fieldSize);
if (CanPlaceShip(field, row, col, size, direction))
{
// Размещаем корабль
for (int i = 0; i < size; i++)
{
if (direction == 0)
field[row, col + i] = 'S'; // горизонтально
else
field[row + i, col] = 'S'; // вертикально
}
placed = true;
}
}
}
// Проверка, можно ли разместить корабль
static bool CanPlaceShip(char[,] field, int row, int col, int size, int direction)
{
// Проверяем, не выходит ли корабль за границы
if (direction == 0 && col + size > fieldSize) return false; // горизонтально
if (direction == 1 && row + size > fieldSize) return false; // вертикально
// Проверяем, что на пути корабля нет других кораблей
for (int i = 0; i < size; i++)
{
int r = row + (direction == 1 ? i : 0);
int c = col + (direction == 0 ? i : 0);
if (field[r, c] == 'S' || !IsSurroundingAreaClear(field, r, c))
{
return false; // Есть пересечения
}
}
return true;
}
// Проверка, что вокруг клетки корабля нет других кораблей
static bool IsSurroundingAreaClear(char[,] field, int row, int col)
{
for (int i = row - 1; i <= row + 1; i++)
{
for (int j = col - 1; j <= col + 1; j++)
{
if (i >= 0 && i < fieldSize && j >= 0 && j < fieldSize)
{
if (field[i, j] == 'S')
return false;
}
}
}
return true;
}
但我认为解析起来会非常困难,我该如何解析这些方法以便了解它是如何生成船舶的?
我查看了你的代码,查看了@EvgeniyZ 的代码并在两者之间写了一些东西。
首先引起我注意的是检查安装这艘船的可能性。如果相邻单元格的检查会相交,为什么还要通过坐标检查 9 个单元格?一次性检查整个矩形不是更容易吗?
例如,这个是 4 层甲板的?
也就是3到6,这不符合逻辑吗?
好吧,方法诞生了:
现在是船舶发电机
我们本质上有一个基于船舶尺寸的生成顺序
[4, 3, 3, 2, 2, 2, 1, 1, 1, 1]
。这样的序列是由两个嵌套循环通过算法生成的。其中,最外层是从 4 到 1 的尺寸列表,内层是它们的数量,由公式 计算得出4 - размер + 1
。然后,就像 @EvgeniyZ 所做的那样,我们尝试将船固定在随机坐标和随机方向上,直到它粘住为止。
另一种方法诞生了:
这里几乎没有什么条件,只有一件事。其他一切都是平庸的数学。
vertical
随机数0或1,如果船是垂直的,则为1。horizontal
- 1(如果水平)。使用这种方法来确定船舶的方向,可以轻松地以数学方式计算其边界的坐标和单元的位置。
好吧,有一些创建矩阵并打印它的实用方法:
我们走吧:
控制台输出: