Яке значення ініціалізації масивів напрямків нижче із заданими значеннями при розробці шахової програми?


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

14
Це напрочуд гарне запитання. ... Чи можна щось зробити з назвою?
luser droog

7
Тож ви не думали згадувати, що цей код походить від шахового двигуна? Крім того, ви не думали самі виглядати, як ці значення використовуються?
trojanfoe

15
"у багатьох великих кодерів є ці чотири рядки [...]" - я тут випиваю, але якби вони були чудовими кодерами, їхній код не змусив би вас замислитись: "wtf це така конструкція ?!"
utnapistim

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 - протилежності тощо. (Ще один спосіб встановити це - рухатися за годинниковою стрілкою, починаючи з півночі - тоді ^4ви отримуєте протилежний напрямок.)

Тепер ви можете протестувати всі напрямки з певної точки, перебираючи їх diі djмасиви, замість того, щоб виписувати кожен напрямок у своєму власному рядку (всього для восьми!) (Просто не забудьте зробити перевірку меж :))

diKі djKсформувати всі напрямки лицарів замість усіх сусідніх напрямків. Тут, ^1перекинувшись по одній осі, ^4дасть протилежний рицарський стрибок.

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

3
що таке "лицарські вказівки"?
Девід

4
О, такий лицар.
Девід

1
Дякую вам за вашу відповідь. Чи можете ви, будь ласка, зв’язати мене чи, можливо, показати мені якийсь код, щоб краще проілюструвати це .. (Я трохи новачок .. якщо ви могли зрозуміти :) Ще раз
дякую

1
Я аплодую спробі Паташу відповіді. Хоча здається, що багато хто зрозумів його пояснення, я не зміг його добре зрозуміти. Якщо хтось може додати до вже сказаного, я буду дуже вдячний.
деепак

1
@deepak Уявіть, що позиція представлена x,yкортежем у двовимірному просторі. Для кожної пари di[i], dj[i]додайте його, x,yі ви x,yпереместитеся в кожному напрямку по одному. Чи має це сенс?
Паташу

64

Для тих, хто вважає, що пояснення Паташу важко дотримуватися, я спробую уточнити.

Уявіть, що ви намагаєтесь розглянути кожен можливий хід від заданої точки на шаховій дошці.

Якщо ви переходите до масивів di та dj, інтерпретуючи значення di як x offset, а значення dj як y offset, ви покриваєте кожен з можливих 8 напрямків.

Якщо припустити, що позитивний x - схід, а позитивний y - південь (як у відповіді Паташу), ви отримуєте наступне;

  | ді / х | 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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.