当前位置: 首页 > 知识库问答 >
问题:

查找坐标是否为顶点/边界坐标的有效方法?

楚弘益
2023-03-14

想象一个笛卡尔平面,每个细胞对象代表平面中的一个点(该平面将是迷宫)。在构建迷宫时,我想弄清楚一个单元格对象是一个顶点(四个角点)还是一个边界点(任何在迷宫边缘的单元格,顶点也是边界点)。

我需要知道,以便我可以添加相邻单元格作为特定单元格的邻居(我正在创建一个带有节点的图结构)。不同的边框对什么单元格是邻居有不同的要求(例如,右上的顶点不能有y+1或x+1的邻居,因为它在迷宫之外,而左下的顶点不能有y-1或x-1)。

我是通过一系列if语句来实现这一点的,我觉得这并不是一个很好的实践。所以我想问是否有更好的方法来知道一个点是什么类型的坐标?

我是这样做的:

private String typeOfBorderCell(Cell cell){
    if (!isBorderCell(cell)){
        throw new IllegalArgumentException("cell is not a border cell");
    }
    double x = cell.getCoordinate().getX();
    double y = cell.getCoordinate().getY();

    // Vertices
    if (x == 0 && y == 0){
        return "bottom-left";
    }

    else if (x == 0 && y == height - 1){
        return "top-left";
    }

    else if (x == width - 1 && y == 0){
        return "bottom-right";
    }

    else if (x == width - 1 && y == height - 1){
        return "top-right";
    }

    // Non-Vertices
    else if (x == 0 && (y > 0 && y < height - 1)){
        return "left";
    }

    // and so on for the other three non-vertex borders
}

高度/宽度是迷宫的大小,但我必须减去1,因为迷宫坐标从原点(0,0)开始,因此5x5迷宫的y最大值为4,其x最大值为4。

共有1个答案

洪照
2023-03-14

我发现枚举是一个相当优雅的选项,可以替代一长组if语句。下面是一个示例(使用Java8):

enum CellType {

    OTHER(1, (x, y) -> true),
    TOP(2, (x, y) -> y == HEIGHT - 1),
    BOTTOM(2, (x, y) -> y == 0),
    LEFT(2, (x, y) -> x == 0),
    RIGHT(2, (x, y) -> x == WIDTH - 1),
    TOP_LEFT(3, TOP, LEFT),
    BOTTOM_RIGHT(3, BOTTOM, RIGHT),
    TOP_RIGHT(3, TOP, RIGHT),
    BOTTOM_LEFT(3, BOTTOM, LEFT);

    private static final int HEIGHT = 5;
    private static final int WIDTH = 5;

    private final int precedence;
    private final BiPredicate<Integer, Integer> test;

    private CellType(int precedence, BiPredicate<Integer, Integer> test) {
        this.precedence = precedence;
        this.test = test;
    }

    private CellType(int precedence, CellType type1, CellType type2) {
        this(precedence, type1.test.and(type2.test));
    }

    public static CellType valueOf(int x, int y) {
        assert x >= 0 && x < WIDTH && y >= 0 && y < WIDTH;
        return Arrays.stream(values())
            .filter(ct -> ct.test.test(x, y))
            .max(Comparator.comparingInt(ct -> ct.precedence))
            .orElse(OTHER);
    }
}

您可以将此用于类似cellType.valueOf(0,4)的代码,该代码将返回cellType.top_left

我更喜欢这个习惯用法,而不是一组if语句,因为它把谓词放在一个地方,使它们易于识别和更改。

这也会导致您的“单元格类型”不是字符串,这是一个好主意,如果您以后想要添加逻辑到它。例如,您可以通过将处理单元格类型的逻辑添加到枚举本身来避免您在问题中提到的switch语句。此外,与字符串进行比较也很容易出错。您可能会在一个地方更改字符串,最终导致难以检测的错误。如果更改枚举,则会立即出现语法错误。

这里简单解释一下它的工作原理。双谓词是一个函数接口,它接受两个整数(x和y),并返回一个布尔值。每个cellType成员都有一个谓词,用于测试给定的x和y是否表示该类型的单元格。对于边缘单元格类型,使用lambda表达式提供条件。对于顶点,构造函数采用两种边缘单元格类型,并通过测试单元格是否满足两种边缘条件来构造一个新的谓词。例如,top_left测试单元格是否位于上边缘和左边缘。

valueof方法查找满足给定单元格的所有单元格类型,然后返回优先级最高的单元格类型。优先级确保返回顶点而不是边。如果没有匹配的单元格类型,则返回other(对于非边非垂直)。

 类似资料:
  • 我正在为我的计算机科学学位的顶点项目工作,我很难弄清楚如何做到标题所说的那样。只要假设摄像机在原点向下看--在gl坐标中的z(或在世界坐标中的正z),我的投影矩阵是基于16x9的纵横比和40度垂直视场。zfar为1000,znear为1。 我从两个不同的角度探讨了这个问题。我试着通过矩阵数学和三角法来计算它。然而,到目前为止,这两种方法都不适合我。 我的第一个本能,是取我的投影矩阵,求矩阵的逆,而

  • 我正在做一个蛇游戏,当苹果在屏幕上随机繁殖时,它不应该在蛇里面繁殖。我试着为苹果寻找一个新的地方,当它们被放在蛇里面时,我会: 这不是一个好的解决方案,所以我正在寻找一个新的解决方案,我可以创建无效的coordiantes,即蛇坐标和其余的有效坐标。所以我可以从有效坐标中随机化苹果的新位置。但我不知道该如何编码

  • 基础示例 <vuep template="#example"></vuep> <script v-pre type="text/x-template" id="example"> <template> <div class="amap-page-container"> <el-amap vid="amapDemo" :zoom="zoom" :center="cente

  • 我有一些关于点为双类型的多边形的问题...我要做的是,给定点,创建多边形,然后测试1个具体点是否在多边形内。 所以我知道在Java中有一个类,叫做多边形,用得像这样:(三角形) 但我的“多边形”必须是“双”类型,而不是“int”(简单示例) 在我的项目中,我真的不需要在小程序或类似物上绘制它,我只需要计算点是否在里面。 所以我的问题是: 有没有什么方法可以用双坐标来处理多边形,可以计算这个点(双坐

  • 本文向大家介绍Cocos2d-x学习笔记之世界坐标系、本地坐标系、opengl坐标系、屏幕坐标系,包括了Cocos2d-x学习笔记之世界坐标系、本地坐标系、opengl坐标系、屏幕坐标系的使用技巧和注意事项,需要的朋友参考一下  cocos2d-x的坐标系很重要,想要学好该引擎,深入理解它的坐标体系很重要。注释写的很清楚了,对照上运行结果一块来看代码吧!

  • 要移动页面的元素,我们应该先熟悉坐标。 大多数 JavaScript 方法处理的是以下两种坐标系中的一个: 相对于窗口 — 类似于 position:fixed,从窗口的顶部/左侧边缘计算得出。 我们将这些坐标表示为 clientX/clientY,当我们研究事件属性时,就会明白为什么使用这种名称来表示坐标。 相对于文档 — 与文档根(document root)中的 position:absol