Ý nghĩa của việc khởi tạo mảng định hướng dưới đây với các giá trị đã cho khi xây dựng chương trình cờ vua?


106

Tôi mới làm quen với lập trình cạnh tranh và tôi thường xuyên nhận thấy, nhiều lập trình viên giỏi có bốn dòng sau trong mã của họ (đặc biệt là trong những dòng liên quan đến mảng):

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 };

Điều này thực sự có ý nghĩa gì và kỹ thuật được sử dụng để làm gì?


5
Tôi thường sử dụng d={0,1,0,-1,0}cho điều này: các cặp mục d[i], d[i+1]cho tôi bốn hướng cơ bản.
dasblinkenlight

14
Đây là một câu hỏi hay một cách đáng ngạc nhiên. ... Có thể làm gì đó về tiêu đề?
luser droog

7
Vì vậy, bạn không nghĩ đến việc đề cập rằng mã này đến từ một công cụ cờ vua? Ngoài ra, bạn không nghĩ rằng hãy nhìn lại bản thân xem những giá trị này đã được sử dụng như thế nào?
trojanfoe

15
"nhiều lập trình viên giỏi có bốn dòng này [...]" - Tôi đang phân tích ở đây, nhưng nếu họ là những lập trình viên giỏi, mã của họ sẽ không khiến bạn thắc mắc "wtf có phải là cấu trúc đó không ?!"
utnapistim

6
@utnapistim Khi viết phần lớn mã, bạn đúng, nhưng ở đây, bạn đang thiếu điểm. Trường hợp này là một ngoại lệ hợp pháp cho quy tắc đó. Nếu bạn đang viết mã cho một cuộc thi và bị hạn chế về thời gian, nhanh và bẩn hầu như luôn tốt hơn là sạch và có thể bảo trì. Trong trường hợp này có thể đọc được đối với bạn, bây giờ thực sự tất cả những gì quan trọng. Một lập trình viên giỏi rất giỏi viết một mớ hỗn độn không thể đọc được trong bối cảnh này , ngay cả khi hầu hết mã thông thường của họ rất dễ đọc và có thể bảo trì.
Ben Lee

Câu trả lời:


84

Đây là một kỹ thuật để mã hóa tất cả các hướng dưới dạng mảng - mỗi cặp di[i],dj[i]là một hướng khác nhau.

Nếu chúng ta tưởng tượng rằng chúng ta có một mảnh ở vị trí x, y và chúng ta muốn thêm vào giá trị x và y của nó để di chuyển nó đến một vị trí gần đó, 1,0 là phía đông, -1,0 là phía tây, 0,1 là phía nam, 0, -1 là phía bắc, v.v.

(Ở đây tôi đã nói trên cùng bên trái là 0,0 và dưới cùng bên phải là 4,4 và cho thấy mỗi chỉ mục của mảng sẽ thực hiện di chuyển gì từ điểm trung tâm, X, tại 2,2.)

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

Cách nó được thiết lập, nếu bạn làm ^1 ( ^là XOR bit) trên chỉ mục, bạn sẽ nhận được hướng ngược lại - 0 và 1 là đối lập, 2 và 3 là đối lập, v.v. (Một cách khác để thiết lập nó là đi theo chiều kim đồng hồ bắt đầu từ phía bắc - sau đó đưa ^4bạn theo hướng ngược lại.)

Bây giờ bạn có thể kiểm tra tất cả các hướng từ một điểm nhất định bằng cách lặp lại didj mảng mảng , thay vì cần phải viết ra từng hướng trên dòng riêng của nó (tổng cộng là tám hướng!) (Đừng quên kiểm tra giới hạn :))

diKdjKtạo thành tất cả các hướng hiệp sĩ thay vì tất cả các hướng liền kề. Ở đây, ^1sẽ lật dọc theo một trục, ^4sẽ cung cấp cho hiệp sĩ đối diện bước nhảy.

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

3
'hướng dẫn hiệp sĩ' là gì?
David

4
Ồ, loại hiệp sĩ đó.
David

1
Cảm ơn bạn rất nhiều cho câu trả lời của bạn .. bạn có thể xin vui lòng liên kết tôi hoặc có lẽ chỉ cho tôi một số mã để minh họa tốt hơn nó .. (Tôi là một người mới làm quen chút ..if u có thể hiểu được :) Cảm ơn một lần nữa
ejjyrex

1
Tôi hoan nghênh nỗ lực của Patashu trong một câu trả lời. Trong khi có vẻ như nhiều người đã hiểu lời giải thích của anh ấy, tôi vẫn chưa thể hiểu rõ về nó. Nếu ai đó có thể thêm vào những gì đã nói, tôi rất biết ơn.
deepak

1
@deepak Hãy tưởng tượng một vị trí được biểu diễn bằng một x,ybộ giá trị trong không gian 2D. Đối với mỗi cặp, hãy di[i], dj[i]thêm nó vào x,yvà bạn sẽ được x,ychuyển đổi theo từng hướng một. Điều đó có ý nghĩa?
Patashu

64

Đối với những người nhận thấy lời giải thích của Patashu khó theo dõi, tôi sẽ cố gắng làm rõ.

Hãy tưởng tượng bạn đang cố gắng xem xét mọi nước đi có thể có từ một điểm nhất định trên bàn cờ vua.

Nếu bạn lặp lại các mảng di và dj, diễn giải các giá trị di là các hiệu số x và các giá trị dj là các hiệu số y, bạn sẽ bao gồm từng hướng trong số 8 hướng có thể.

Giả sử x dương ở phía đông và dương y ở phía nam (như trong câu trả lời của Patashu), bạn sẽ nhận được như sau;

  | di / x | dj / y | Phương hướng
- + ------ + ------ + -----------
0 | 1 | 0 | phía đông
1 | -1 | 0 | hướng Tây
2 | 0 | 1 | miền Nam
3 | 0 | -1 | Bắc
4 | 1 | 1 | Đông Nam
5 | -1 | -1 | Tây Bắc
6 | 1 | -1 | đông bắc
7 | -1 | 1 | tây nam

Các mảng diK và djK có thể được hiểu theo cùng một cách để thiết lập các nước đi có thể có cho quân cờ. Nếu bạn không quen thuộc với cờ vua, Hiệp sĩ di chuyển theo hình chữ L - hai hình vuông theo một hướng và sau đó là một hình vuông ở góc vuông với hướng đó (hoặc ngược lại).

  | diK / x | djK / y | Phương hướng
- + ------- + ------- + ----------------
0 | -2 | -1 | 2 tây, 1 bắc
1 | -2 | 1 | 2 tây, 1 nam
2 | -1 | 2 | 1 tây, 2 nam
3 | 1 | 2 | 1 đông, 2 nam
4 | 2 | 1 | 2 đông, 1 nam
5 | 2 | -1 | 2 phía đông, 1 phía bắc
6 | 1 | -2 | 1 đông, 2 bắc
7 | -1 | -2 | 1 tây, 2 bắc

1

Một đoạn mã nhỏ để kiểm tra lượng di chuyển có thể theo mọi hướng, sử dụng các mảng đã xác định.

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.