You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中高效检查二维数组是否含指定元素的方法(战舰游戏场景)

优化战舰游戏船只沉没判定的效率

你的当前实现每次检查都要遍历整个二维棋盘,对于5艘船来说确实会产生大量冗余遍历,下面给你几个更高效的实现思路:

方法1:维护每艘船的击中计数(最优方案)

直接给每艘船定义类来跟踪自身长度和被击中次数,完全不需要遍历棋盘:

public class Ship
{
    // 对应棋盘上标识该船的字符串,比如"Carrier"
    public string Identifier { get; init; }
    public int TotalLength { get; init; }
    public int HitsReceived { get; private set; } = 0;

    // 记录击中,调用此方法更新状态
    public void TakeHit() => HitsReceived++;

    // 直接判断是否沉没
    public bool IsSunk() => HitsReceived >= TotalLength;
}

使用示例

初始化船只时:

// 按战舰游戏标准配置初始化5艘船
var ships = new List<Ship>
{
    new Ship { Identifier = "Carrier", TotalLength = 5 },
    new Ship { Identifier = "Battleship", TotalLength = 4 },
    new Ship { Identifier = "Cruiser", TotalLength = 3 },
    new Ship { Identifier = "Submarine", TotalLength = 3 },
    new Ship { Identifier = "Destroyer", TotalLength = 2 }
};

当玩家击中棋盘上的某艘船时,找到对应的Ship实例并调用TakeHit(),之后直接用IsSunk()判断是否沉没:

// 假设击中了Carrier
var carrier = ships.First(s => s.Identifier == "Carrier");
carrier.TakeHit();
bool isCarrierSunk = carrier.IsSunk();

方法2:预存每艘船的坐标位置

如果不想修改现有结构,可提前记录每艘船占据的所有坐标,检查时仅遍历该船的坐标而非整个棋盘:

初始化坐标字典

// 键为船的标识,值为该船占据的所有坐标
var shipCoordinates = new Dictionary<string, List<(int X, int Y)>>
{
    ["Carrier"] = new List<(int, int)> { (0,0), (0,1), (0,2), (0,3), (0,4) },
    // 其他船的坐标同理添加
};

优化后的检查方法

public static bool CheckShipSunk(string[,] board, string shipId, Dictionary<string, List<(int X, int Y)>> shipCoords)
{
    if (!shipCoords.TryGetValue(shipId, out var coords))
        return false; // 不存在该船,按需求返回状态

    // 仅遍历当前船的坐标,最多5次循环
    foreach (var (x, y) in coords)
    {
        // 假设未击中的位置存储船的标识,击中后改为"X"或其他标记
        if (board[x, y] == shipId)
            return false; // 仍有未击中部分,未沉没
    }
    return true;
}

方法3:跟踪剩余未击中坐标

基于方法2进一步优化,用集合存储每艘船剩余的未击中坐标,击中时移除对应坐标,判断沉没只需看集合是否为空:

// 初始化剩余坐标集合
var remainingShipCoords = new Dictionary<string, HashSet<(int X, int Y)>>
{
    ["Carrier"] = new HashSet<(int, int)> { (0,0), (0,1), (0,2), (0,3), (0,4) },
    // 其他船同理
};

// 击中时更新状态
public static void RegisterHit(string shipId, (int X, int Y) hitPos, Dictionary<string, HashSet<(int X, int Y)>> remainingCoords)
{
    if (remainingCoords.TryGetValue(shipId, out var coords))
    {
        coords.Remove(hitPos);
    }
}

// 检查沉没
public static bool CheckShipSunk(string shipId, Dictionary<string, HashSet<(int X, int Y)>> remainingCoords)
{
    return remainingCoords.TryGetValue(shipId, out var coords) && coords.Count == 0;
}

以上三种方法都能大幅降低性能开销,尤其是方法1,代码简洁且完全避免了遍历操作,最适合你的场景。

内容的提问来源于stack exchange,提问作者PrestonJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:45:46