在开发国际象棋程序时,使用给定值初始化下面的方向数组有什么意义?


106

我是竞争编程的新手,我经常注意到,许多优秀的编码器的代码中都有以下四行(尤其是涉及数组的行):

int di[] = { 1, -1, 0, 0, 1, -1, 1, -1 };
int dj[] = { 0, 0, 1, -1, 1, -1, -1, 1 };
int diK[] = { -2, -2, -1, 1, 2, 2, 1, -1 };
int djK[] = { -1, 1, 2, 2, 1, -1, -2, -2 };

这到底意味着什么?技术的用途是什么?


5
我经常d={0,1,0,-1,0}这样做:物品对d[i], d[i+1]给我四个基本方向。
dasblinkenlight 2013年

14
这是一个令人惊讶的好问题。...可以对标题做些什么吗?
luser droog

7
因此,您没有想到要提到此代码来自国际象棋引擎吗?您也没有想到要看看自己如何使用这些值?
trojanfoe

15
“很多优秀的编码器都有这四行[...]”-我在这里挑剔,但是如果他们是优秀的编码器,那么他们的代码不会引起您怀疑“ wtf是那个构造吗?!”
utnapistim

6
@utnapistim编写绝大多数代码时,您是对的,但是在这里,您没有抓住重点。这种情况是该规则的合法例外。如果您正在为比赛编写代码并且在时间限制下,那么“肮脏”几乎总是比“干净可维护”更好。在这种情况下可读的你,现在真的所有的事项。优秀的编码人员在这种情况下,即使他们的大多数常规代码都是高度可读和可维护的,也能很好地编写出难以维护的混乱。
李·李

Answers:


84

这是一种将所有方向编码为数组的技术-每对di[i],dj[i]都是不同的方向。

如果我们想象我们在x,y位置上有一块,并且想要将其x和y值相加以将其移动到附近的位置,则1,0为东,-1,0为西,0,1是南,0,-1是北,依此类推。

(在这里我说过左上角是0,0,右下角是4,4,并显示了数组的每个索引将从中心点X在2,2处移动的方向。)

.....
.536.
.1X0.
.724.
.....

它的设置方式是,如果对索引执行^1^按位XOR)操作,则会得到相反的方向-0和1是相反的,2和3是相反的,依此类推。(另一种设置方法是从北开始顺时针旋转-然后^4使您获得相反的方向。)

现在您可以通过遍历您的didj数组来测试从给定点开始的所有方向,而无需在自己的行上写出每个方向(总共八个)!(别忘了做边界检查:))

diKdjK形成所有骑士指示,而不是所有相邻指示。在这里,^1将沿一个轴翻转,^4将给予相反的骑士跳跃。

.7.6.
0...5
..K..
1...4
.2.3.

3
什么是“骑士路线”?
大卫,

4
哦,那个骑士。
大卫,

1
非常感谢您的回答。请您链接我,或者向我显示一些代码以更好地说明它。.(我是新手。.如果您能理解:)再次感谢
ejjyrex

1
我赞扬Patashu做出回答的尝试。尽管似乎许多人都了解他的解释,但我仍无法很好地理解它。如果有人可以补充已经说过的话,我将不胜感激。
迪帕克

1
@deepak想象一个位置由x,y2D空间中的元组表示。对于每对di[i], dj[i]将其添加到的对象x,y,您将x,y在每个方向上逐一进行转置。那有意义吗?
Patashu

64

对于那些难以理解Patashu的解释的人,我将尝试进行澄清。

想象一下,您正在尝试考虑从棋盘上的给定点开始的所有可能动作。

如果遍历di和dj数组,将di值解释为x偏移量,将dj值解释为y偏移量,则将覆盖8个可能的方向。

假设正x是东方,而正y是南方(如Patashu的回答),您将得到以下结果:

  | di / x | dj / y | 方向
-+ ------ + ------ + -----------
0 | 1 | 0 | 东
1 | -1 | 0 | 西方
2 | 0 | 1 | 南
3 | 0 | -1 | 北
4 | 1 | 1 | 东南
5 | -1 | -1 | 西北
6 | 1 | -1 | 东北
7 | -1 | 1 | 西南

可以以相同的方式解释diK和djK数组,以建立Knight棋子的可能动作。如果您对国际象棋不熟悉,则骑士会以L形移动-在一个方向上移动两个正方形,然后以一个直角移动一个正方形(反之亦然)。

  | diK / x | djK / y | 方向
-+ ------- + ------- + ----------------
0 | -2 | -1 | 西2西,北1西
1 | -2 | 1 | 西2西,南1西
2 | -1 | 2 | 西1个,南2个
3 | 1 | 2 | 东部1个,南部2个
4 | 2 | 1 | 东部2个,南部1个
5 | 2 | -1 | 东部2个,北部1个
6 | 1 | -2 | 东1,北2
7 | -1 | -2 | 西1个,北2个

1

一小段代码,用于检查在所有方向上可能移动的数量,该代码使用已定义的数组。

int di[] = { 1, -1, 0, 0, 1, -1, 1, -1 };
int dj[] = { 0, 0, 1, -1, 1, -1, -1, 1 };
int movesPossible[8];
int move = 0;
int posx, posy; // position of the figure we are checking

for (int d=0; d<8; d++) {
  for (move = 1; board.getElt(posx+di[d]*move, posy+dj[d]*move)==EMPTY; move++) ;
  movesPossible[d] = move-1;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.