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

C# 实现连续水平/垂直线段序列的相交判断

问题描述

现有N段固定单位长度的连续水平、垂直线段,以移动方向序列形式存储,可选方向为右、左、下、上四类。需要实现判断逻辑:若序列对应的折线路径存在自相交,则返回true,否则返回false。

  • 测试用例:当N=6,方向序列为{"up", "left", "down", "down", "right", "up"}时,预期返回true
  • 现有代码存在两处明显问题:一是坐标计算方法每次循环都重置坐标原点,无法正确累计路径;二是仅返回终点坐标,未存储全量线段信息,无法支撑相交判断。
实现思路
  • 第一步:修正坐标遍历逻辑,从原点(0,0)出发,按方向序列逐段移动,记录每一段线段的两个端点坐标,生成完整的线段列表。
  • 第二步:由于所有线段只有水平、垂直两种,相交判定可以简化,不需要使用复杂的通用线段相交算法:
    • 水平线段Y坐标固定,X值落在两个端点的X区间内
    • 垂直线段X坐标固定,Y值落在两个端点的Y区间内
    • 若两条线段同为水平/垂直:共线且坐标区间存在重叠即为相交
    • 若两条线段一水平一垂直:垂直线段的X落在水平线段的X区间内,同时水平线段的Y落在垂直线段的Y区间内即为相交
    • 注意:直接相邻的线段本身就是端点连接,属于路径正常结构,不需要判定,遍历线段对时跳过索引差小于2的组合即可。
  • 第三步:遍历所有非相邻线段对,只要有一对满足相交条件,直接返回true;所有线段对遍历完无相交则返回false。
可直接运行的实现代码
// 线段结构,存储两个端点坐标
readonly record struct LineSegment(int X1, int Y1, int X2, int Y2)
{
    public bool IsHorizontal => Y1 == Y2;
    public int XMin => Math.Min(X1, X2);
    public int XMax => Math.Max(X1, X2);
    public int YMin => Math.Min(Y1, Y2);
    public int YMax => Math.Max(Y1, Y2);
}

static (int, int) GetCoordinates(string[] sectionDirection, int numberOfSections)
{
    (int X, int Y) pos = (0, 0);
    foreach (string move in sectionDirection)
    {
        switch (move)
        {
            case "left":
                pos.X--;
                break;
            case "right":
                pos.X++;
                break;
            case "down":
                pos.Y--;
                break;
            case "up":
                pos.Y++;
                break;
        }
    }
    return (pos.X, pos.Y);
}

static bool CheckSectionsIntersect(string[] sectionDirection, int numberOfSections)
{
    List<LineSegment> segments = new List<LineSegment>();
    (int X, int Y) current = (0, 0);
    
    // 生成所有线段
    foreach (string move in sectionDirection)
    {
        (int X, int Y) next = current;
        switch (move)
        {
            case "left":
                next.X--;
                break;
            case "right":
                next.X++;
                break;
            case "down":
                next.Y--;
                break;
            case "up":
                next.Y++;
                break;
        }
        segments.Add(new LineSegment(current.X, current.Y, next.X, next.Y));
        current = next;
    }

    // 遍历所有非相邻线段对判断相交
    for (int i = 0; i < segments.Count; i++)
    {
        for (int j = i + 2; j < segments.Count; j++)
        {
            if (IsIntersect(segments[i], segments[j]))
            {
                return true;
            }
        }
    }
    return false;
}

// 水平/垂直线段相交判定
static bool IsIntersect(LineSegment a, LineSegment b)
{
    if (a.IsHorizontal && b.IsHorizontal)
    {
        // 两条都是水平,Y相同且X区间重叠
        if (a.Y1 != b.Y1) return false;
        return a.XMin <= b.XMax && b.XMin <= a.XMax;
    }
    else if (!a.IsHorizontal && !b.IsHorizontal)
    {
        // 两条都是垂直,X相同且Y区间重叠
        if (a.X1 != b.X1) return false;
        return a.YMin <= b.YMax && b.YMin <= a.YMax;
    }
    else
    {
        // 一水平一垂直,先区分哪个是水平哪个是垂直
        LineSegment horizontal = a.IsHorizontal ? a : b;
        LineSegment vertical = a.IsHorizontal ? b : a;
        
        // 垂直线的X在水平线段X区间内,水平线的Y在垂直线段Y区间内即为相交
        return vertical.X1 >= horizontal.XMin 
               && vertical.X1 <= horizontal.XMax 
               && horizontal.Y1 >= vertical.YMin 
               && horizontal.Y1 <= vertical.YMax;
    }
}
逻辑验证

针对给出的测试用例,路径最终会回到起点(0,0),最后一段线段和第一段线段在(0,0)处相交,函数会正确返回true,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:21:23