チェスプログラムを開発するときに、以下の方向配列を指定された値で初期化することの重要性は何ですか?


106

私は競合プログラミングに不慣れですが、多くの優れたプログラマーがコードに次の4行(特に配列を含むもの)を持っていることに気づきました。

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]、4つの基本的な方向を示します。
dasblinkenlight 2013年

14
これは驚くほど良い質問です。...タイトルについて何かできることはありますか?
luser droog 2013

7
それで、あなたはこのコードがチェスエンジンから来ることを言及することを考えなかったのですか?また、これらの値がどのように使用されているか自分で考えようとは思わなかったのですか?
trojanfoe 2013年

15
「多くの優れたコーダーがこれらの4行を持っています[...]」-私はここで抜き取りしていますが、彼らが優れたコーダーであったとしても、彼らのコードは「wtfはその構造ですか?」
utnapistim 2013年

6
@utnapistimコードの大部分を書くとき、あなたは正しいですが、ここでは、ポイントを逃しています。このケースは、そのルールの正当な例外です。競争のためのコードを記述していて、時間の制約がある場合、ほとんどの場合、クリーンでメンテナンス可能なものよりも、クイックアンドダーティーの方が優れています。この場合、あなたに読める、今は本当にあるすべてのことの問題。優れたコーダーは、通常のコードのほとんどが非常に読みやすく保守可能である場合でも、このコンテキストでは保守不能で読み取り不能な混乱非常にうまく記述します。
ベン・リー

回答:


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は反対です。(もう1つの設定方法は、北から時計回りに進み^4、反対方向に進みます。)

これで、didj配列をループすることで、特定のポイントからすべての方向をテストできます。各方向を独自の行に書き込む必要はありません(合計8つです!)(境界チェックを行うことを忘れないでください:))。

diK隣接するすべての方向ではなく、djKすべての騎士の方向を形成します。ここで^1は、1つの軸に沿って反転し^4、反対の騎士の飛躍をもたらします。

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

3
「騎士の道順」とは何ですか?
デビッド

4
ああ、そのような騎士。
デビッド

1
答えてくれてありがとう..リンクしてくれますか、それをよりよく説明するためにいくつかのコードを見せてもらえますか。(私は少し初心者です。理解できれば:)ありがとうございます
ejjyrex

1
私はパタシュの回答に対する試みを称賛します。多くの人が彼の説明を理解しているようですが、私はそれをよく理解することができませんでした。誰かがすでに言われたことを付け加えることができれば、私は非常に感謝します。
ディーパック2013年

1
@deepak位置がx,y2D空間のタプルで表されていると想像してください。ペアごとにdi[i], dj[i]追加するx,yx,y、各方向に1つずつ転置されます。それは理にかなっていますか?
Patashu 2013年

64

パタシュの説明を理解するのが難しいと思う人のために、私は明確にしようとします。

あなたがチェス盤の与えられたポイントから可能なすべての動きを考えようとしていると想像してください。

di配列とdj配列をループして、di値をxオフセットとして、dj値をyオフセットとして解釈すると、可能な8方向のそれぞれをカバーします。

正のxが東で正のyが南であると仮定すると(パタシュの回答のように)、次のようになります。

  | 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パターンで移動します。1つの方向に2つの正方形、次にそれに対して直角に1つの正方形(またはその逆)です。

  | 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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.