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

C语言实现正方形与三角形格点最近邻计算的技术问询

三角形格点最近邻计算的C语言实现思路

你已经完成正方形格点的最近邻计算,三角形格点的6个最近邻不需要引入角度,核心思路是先把一维格点标号转换成二维坐标,再根据三角形格点的偏移布局规则找到邻点坐标,最后转回一维标号,同时处理边界(周期性或非周期性均可)。

一、明确三角形格点的布局规则

最常用的是「偏移行」布局:

  • 假设格点是L×L的二维网格,行号从0到L-1,列号从0到L-1
  • 偶数行(r为0、2、4...)的格点与奇数行(r为1、3、5...)的格点横向偏移半个格距,这样每个内部点会有6个最近邻

二、一维标号与二维坐标的转换

你的正方形格点标号从1开始,对应转换公式:

// 一维标号i转二维坐标(r, c)
int r = (i - 1) / L;
int c = (i - 1) % L;

// 二维坐标(r, c)转一维标号i
int i = r * L + c + 1;

三、6个最近邻的坐标规则

针对偏移行布局,分奇偶行处理:
对于坐标(r, c),6个邻居的坐标如下:

  • 同一行左邻:(r, c-1)
  • 同一行右邻:(r, c+1)
  • 上一行邻居:
    • 若r是偶数:(r-1, c)、(r-1, c-1)
    • 若r是奇数:(r-1, c)、(r-1, c+1)
  • 下一行邻居:
    • 若r是偶数:(r+1, c)、(r+1, c-1)
    • 若r是奇数:(r+1, c)、(r+1, c+1)

四、边界处理(以周期性边界为例)

如果是周期性边界(类似你正方形代码里的循环边界),用取模运算把超出范围的坐标拉回网格内:

  • 列坐标:c = (c + L) % L;(处理c<0或c>=L的情况)
  • 行坐标:r = (r + L) % L;(处理r<0或r>=L的情况)
    如果是非周期性边界,直接判断坐标是否在0~L-1范围内,超出则标记为无邻居即可。

五、C语言实现示例

先优化你原来的正方形代码(去掉全局变量,用数学计算替代循环处理边界),再实现三角形格点的邻居计算:

#include <stdio.h>
#include <stdlib.h>

#define L 5 // L×L格点规模

// 正方形格点最近邻计算(优化版)
void square_neighbours(int i) {
    int r = (i - 1) / L;
    int c = (i - 1) % L;

    // 右邻居
    int nr_c = (c + 1) % L;
    int nr = r * L + nr_c + 1;
    printf("右邻点: %d\n", nr);

    // 左邻居
    int nl_c = (c - 1 + L) % L;
    int nl = r * L + nl_c + 1;
    printf("左邻点: %d\n", nl);

    // 上邻居
    int nu_r = (r - 1 + L) % L;
    int nu = nu_r * L + c + 1;
    printf("上邻点: %d\n", nu);

    // 下邻居
    int nd_r = (r + 1) % L;
    int nd = nd_r * L + c + 1;
    printf("下邻点: %d\n", nd);
}

// 三角形格点最近邻计算(周期性边界)
void triangle_neighbours(int i) {
    int r = (i - 1) / L;
    int c = (i - 1) % L;
    int neighbours[6];
    int idx = 0;

    // 同一行左右邻居
    int c_left = (c - 1 + L) % L;
    neighbours[idx++] = r * L + c_left + 1;
    int c_right = (c + 1) % L;
    neighbours[idx++] = r * L + c_right + 1;

    // 上一行邻居
    int r_up = (r - 1 + L) % L;
    if (r % 2 == 0) { // 偶数行上邻
        neighbours[idx++] = r_up * L + c + 1;
        int c_up_left = (c - 1 + L) % L;
        neighbours[idx++] = r_up * L + c_up_left + 1;
    } else { // 奇数行上邻
        neighbours[idx++] = r_up * L + c + 1;
        int c_up_right = (c + 1) % L;
        neighbours[idx++] = r_up * L + c_up_right + 1;
    }

    // 下一行邻居
    int r_down = (r + 1) % L;
    if (r % 2 == 0) { // 偶数行下邻
        neighbours[idx++] = r_down * L + c + 1;
        int c_down_left = (c - 1 + L) % L;
        neighbours[idx++] = r_down * L + c_down_left + 1;
    } else { // 奇数行下邻
        neighbours[idx++] = r_down * L + c + 1;
        int c_down_right = (c + 1) % L;
        neighbours[idx++] = r_down * L + c_down_right + 1;
    }

    // 输出结果
    printf("三角形格点的6个最近邻:\n");
    for (int k = 0; k < idx; k++) {
        printf("%d ", neighbours[k]);
    }
    printf("\n");
}

int main(void) {
    int site;
    printf("L×L格点,L=%d,总点数=%d\n", L, L*L);
    printf("请输入格点标号(1~%d): ", L*L);
    scanf("%d", &site);

    if (site < 1 || site > L*L) {
        printf("输入的标号超出范围!\n");
        return 1;
    }

    printf("\n---正方形格点最近邻---\n");
    square_neighbours(site);

    printf("\n---三角形格点最近邻---\n");
    triangle_neighbours(site);

    return 0;
}

关键说明

  • 全程无需角度计算:所有逻辑都是基于二维坐标的整数运算,完全不需要三角函数
  • 布局可灵活调整:如果你的三角形格点是奇数行偏移,只需要修改奇偶行的邻居规则即可
  • 边界模式可切换:代码默认用周期性边界,若需要非周期性边界,去掉坐标取模,直接判断坐标是否在0~L-1范围内即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:01:22