Algorithm 四向导航算法
考虑一个矩形画布,其中包含随机大小和位置的矩形。要在这些矩形之间导航,用户可以使用四个箭头:上、下、左、右 您是否熟悉任何能够产生相当直观的用户体验的导航算法Algorithm 四向导航算法,algorithm,keyboard,user-experience,Algorithm,Keyboard,User Experience,考虑一个矩形画布,其中包含随机大小和位置的矩形。要在这些矩形之间导航,用户可以使用四个箭头:上、下、左、右 您是否熟悉任何能够产生相当直观的用户体验的导航算法 我遇到了一些解决方案,但似乎没有一个是合适的。我知道没有一个解决方案是“理想的”。但是,我正在寻找的算法是仅使用箭头键在桌面图标之间导航的算法。如何按如下方式构建运动图: 对于任何方向,尝试转到给定方向上最近的矩形,其中心点为当前矩形边的中间 尝试消除循环,例如,从A移动“右”应尝试生成与从A移动“右上”不同的矩形。例如,在中,从绿色移
我遇到了一些解决方案,但似乎没有一个是合适的。我知道没有一个解决方案是“理想的”。但是,我正在寻找的算法是仅使用箭头键在桌面图标之间导航的算法。如何按如下方式构建运动图:
- 对于任何方向,尝试转到给定方向上最近的矩形,其中心点为当前矩形边的中间
- 尝试消除循环,例如,从A移动“右”应尝试生成与从A移动“右上”不同的矩形。例如,在中,从绿色移动的“右”应为橙色,即使粉色是最近的中点
- (感谢biziclop):如果图形中无法访问任何矩形,则重新映射其中一个相邻矩形以访问它,可能是错误最少的矩形。重复,直到所有矩形都可以到达(我认为算法将终止…)
然后存储图形并仅用于导航。你不想在会话中间改变方向。 这个问题可以被建模为<代码>图>代码>问题,<>代码>算法>导航> <代码> >最短路径路由< /C> > < /P> 这是模型。 每个矩形都是图形中的一个顶点。从每个顶点(也称为矩形)有四个选项-上、下、左、右。所以,你们可以到达四个不同的矩形,也就是说,这个顶点有四个邻居,你们可以把这些边添加到图中 我不确定这是否是问题的一部分--“使用一个特定的动作(例如向上)可以从一个矩形到达多个矩形”。如果没有,上述建模就足够了。如果是,则添加所有此类顶点作为该顶点的邻居。因此,您可能不会得到一个4-正则图。否则,您将把问题建模为4-正则图 现在,问题是如何定义“导航”算法。如果不想区分动作,即如果上、下、左和右都相等,则可以向所有边添加权重1 如果您决定为某个特定操作赋予比其他操作更高的优先级,例如
up
优于其他操作,则可以为向上移动产生的边赋予权重1,将其余边赋予权重2。其思想是通过指定不同的权重,可以区分将要移动的边
如果确定所有up
边不相等,即A和B之间的向上距离小于C和D之间的向上距离,则可以在图形构建过程中相应地为边指定权重
这是路由
现在,如何找到路径——您可以使用dijkstra的算法在给定的一对顶点之间找到最短路径。如果您对多条最短路径感兴趣,可以使用k-最短路径
算法查找一对节点之间的k
最短路径,然后选择最佳路径
请注意,最终生成的图不一定是有向图。如果喜欢有向图,则可以在构造边时为边指定方向。否则,您应该很好地使用无向图,因为您所关心的只是使用一条边从另一条边到达一个顶点。此外,如果可以从矩形B
使用up
到达矩形A
,则可以从矩形A
使用down
到达矩形B
。因此,如果你出于其他原因不需要方向,那么方向真的不重要。如果你不喜欢我刚才的假设,那么你需要构造一个有向图
希望这能有所帮助。对于一个拿着锤子的人来说,一切都像钉子,这是一个真理。最短路径算法在这里是一个明显的工具,因为最短距离看起来很直观 然而,我们正在设计一个UI,其中逻辑距离比物理距离重要得多 所以让我们试着换一种思维方式 一个限制条件是,反复按向上(右、下或左)箭头应该最终在所有矩形中循环。否则,可能会出现一些无法接触到的“孤儿”。使用基于物理(2d)距离的算法很难实现这一点,因为2d中最近的项目可能在与所使用的箭头对相对应的1d投影中位于错误方向。也就是说,点击向上箭头可以很容易地选择电流下方的方框。哎哟 因此,让我们采用一个非常简单的解决方案。只需在其质心的x坐标上对所有矩形进行排序。点击左右箭头按以下顺序在矩形中循环:从右到下一个最高x,从左到下一个最低x。在屏幕边缘包裹 对y坐标也要这样做。按此顺序使用向上和向下循环 成功的关键(双关语)是在屏幕上添加动态信息,同时循环向用户显示正在发生的事情的逻辑。这里有一个建议。其他的是可能的 在第一个垂直(向上或向下)键处,矩形上会出现一个浅半透明覆盖层。它们被淡红色或蓝色阴影覆盖,图案由质心的y坐标交替。在整个窗口中还存在匹配颜色的水平散列标记。使用两种颜色的唯一原因是提供直线和矩形之间对应关系的视觉指示器。当前选定的矩形是非半透明的,哈希标记比所有其他矩形都亮。当你
const double MAXDISTSQUARED = /* The maximum possible squared distance */;
const double Z = /* A +ve number. Z > 1 => distance more important than angle */
// Return a weight in the range [0, 1], with higher indicating a better fit.
double getWeight(enum direction d, int x1, int y1, int x2, int y2) {
if (d == LEFT && x1 < x2 ||
d == RIGHT && x1 > x2 ||
d == UP && y1 < y2 ||
d == DOWN && y1 > y2) return 0;
// Don't need to take sqrt(); in fact it's probably better not to
double distSquared = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double angle = abs(atan2(x1 - x2, y1 - y2)); // 0 => horiz; PI/2 => vert
if (d == UP || d == DOWN) angle = PI / 2 - angle;
return 1 - pow(distSquared / MAXDISTSQUARED, Z) * (2 * angle / PI);
}