给定一个数字,以螺旋模式获得网格位置

时间:2018-03-24 03:47:53

标签: javascript algorithm optimization

+---------------+---------------+---------------+---------------+---------------+
| id:  20       | id:  19       | id:  18       | id:  17       | id:  16       |
| pos: (-2, -2) | pos: (-1, -2) | pos: (0, -2)  | pos: (1, -2)  | pos: (2, -2)  |
+---------------+---------------+---------------+---------------+---------------+
| id:  21       | id:  6        | id:  5        | id:  4        | id:  15       |
| pos: (-2, -1) | pos: (-1, -1) | pos: (0, -1)  | pos: (1, -1)  | pos: (2, -1)  |
+---------------+---------------+---------------+---------------+---------------+
| id:  22       | id:  7        | id:  0        | id:  3        | id:  14       |
| pos: (-2, 0)  | pos: (-1, 0)  | pos: (0, 0)   | pos: (1, 0)   | pos: (2, 0)   |
+---------------+---------------+---------------+---------------+---------------+
| id:  23       | id:  8        | id:  1        | id:  2        | id:  13       |
| pos: (-2, 1)  | pos: (-1, 1)  | pos: (0, 1)   | pos: (1, 1)   | pos: (2, 1)   |
+---------------+---------------+---------------+---------------+---------------+
| id:  24       | id:  9        | id:  10       | id:  11       | id:  12       |
| pos: (-2, 2)  | pos: (-1, 2)  | pos: (0, 2)   | pos: (1, 2)   | pos: (2, 2)   |
+---------------+---------------+---------------+---------------+---------------+

鉴于以上网格,您如何根据ID获得排名?我的实施:

function getRing (id) {
 return Math.ceil((Math.sqrt(id + 1) - 1) / 2);
}

function getMinRingID (r) {
 if (r == 0) {
   return 0;
 }
 return Math.pow((2 * (r - 1) + 1), 2);
}

function getRingLegFromID (id) {
 if (id == 0) {
   return 0;
 }

 var r = getRing(id);
 var m = getMinRingID(r);
 if (id >= m && id < m + (2 * r)) {
   return 0;
 } else if (id >=  m + (2 * r) && id <  m + (4 * r)) {
   return 1;
 } else if (id >=  m + (4 * r) && id <  m + (6 * r)) {
   return 2;
 } else if (id >=  m + (6 * r)) {
   return 3;
 }
}

通过以上基础知识,您可以获得......

的位置
function getPos (id) {
 var ring = getRing(id);
 var min = getMinRingID(ring);
 var leg = getRingLegFromID(id);

 if (id === 0) {
   return [0, 0];
 }

 switch (leg) {
   case 0:
     return [-ring + ((id - min) + 1), ring];
     break;
   case 1:
     return [ring, ring - ((id - min) - ((2 * ring) - 1))];
     break;
   case 2:
     return [ring - ((id - min) - ((4 * ring) - 1)), -ring];
     break;
   case 3:
     return [-ring, -ring + ((id - min) - ((6 * ring) - 1))];
     break;
 }
}

我可以对此代码进行任何优化吗?是否有更好的方法从id获得位置?

1 个答案:

答案 0 :(得分:-1)

如果要重复调用该函数并且N在合理范围内(让我们说300),您可以对该上限N进行螺旋步行来计算index - &gt; position映射,将其缓存在字典中,然后查找。

对于螺旋步行,您可以执行与this类似的操作。

如果xy值大于300,您可以使用您的功能。