ความสำคัญของการเริ่มต้นอาร์เรย์ทิศทางด้านล่างด้วยค่าที่กำหนดเมื่อพัฒนาโปรแกรมหมากรุกคืออะไร?


106

ฉันยังใหม่กับการเขียนโปรแกรมเชิงแข่งขันและฉันสังเกตเห็นบ่อยครั้งว่า coders ที่ยอดเยี่ยมหลายตัวมีสี่บรรทัดนี้ในโค้ด (โดยเฉพาะอย่างยิ่งในส่วนที่เกี่ยวข้องกับอาร์เรย์):

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
คุณไม่คิดที่จะพูดถึงว่ารหัสนี้มาจากเครื่องมือหมากรุกหรือไม่? คุณไม่คิดที่จะมองตัวเองว่ามีการใช้ค่าเหล่านี้อย่างไร?
โทรจัน

15
"coders ที่ยอดเยี่ยมหลายคนมีสี่บรรทัดนี้ [... ]" - ฉันกำลังคิดอยู่ที่นี่ แต่ถ้าพวกเขาเป็นนักเขียนโค้ดที่ยอดเยี่ยมรหัสของพวกเขาจะไม่ทำให้คุณสงสัยว่า "wtf คือโครงสร้างนั้นหรือ!"
utnapistim

6
@utnapistim เมื่อเขียนโค้ดส่วนใหญ่คุณพูดถูก แต่ที่นี่คุณพลาดประเด็น กรณีนี้เป็นข้อยกเว้นที่ชอบด้วยกฎหมายของกฎนั้น หากคุณกำลังเขียนโค้ดสำหรับการแข่งขันและอยู่ภายใต้ข้อ จำกัด ของเวลาความรวดเร็วและสกปรกมักจะดีกว่าการทำความสะอาดและบำรุงรักษา ในกรณีนี้สามารถอ่านได้ให้กับคุณในขณะนี้มันเป็นเรื่องที่ทุกคน โปรแกรมเขียนโค้ดที่ยอดเยี่ยมเขียนข้อความที่ไม่สามารถอ่านได้ที่ไม่สามารถเข้าถึงได้ในบริบทนี้แม้ว่าโค้ดปกติส่วนใหญ่จะอ่านได้และบำรุงรักษาได้ดี
Ben Lee

คำตอบ:


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
ขอบคุณมากสำหรับคำตอบ .. คุณช่วยลิงค์ให้ฉันหน่อยได้ไหมหรืออาจจะแสดงโค้ดให้ฉันดูดีกว่า .. (ฉันเป็นมือใหม่.. ถ้าคุณเข้าใจ :) ขอบคุณอีกครั้ง
ejjyrex

1
ขอปรบมือให้กับความพยายามของ Patashu ในคำตอบ แม้ว่าหลายคนจะเข้าใจคำอธิบายของเขา แต่ฉันก็ไม่สามารถเข้าใจได้ดี หากใครสามารถเพิ่มสิ่งที่ได้กล่าวไปแล้วฉันจะขอบคุณมาก
deepak

1
@deepak ลองนึกภาพตำแหน่งแทนด้วยx,yทูเพิลในพื้นที่ 2 มิติ สำหรับแต่ละคู่di[i], dj[i]เพิ่มเข้าไปx,yและคุณจะได้รับการx,yเปลี่ยนทิศทางไปทีละคู่ มันสมเหตุสมผลไหม
Patashu

64

สำหรับผู้ที่พบว่าคำอธิบายของ Patashu ยากที่จะปฏิบัติตามฉันจะพยายามชี้แจง

ลองนึกภาพคุณกำลังพยายามพิจารณาทุกการเคลื่อนไหวที่เป็นไปได้จากจุดที่กำหนดบนกระดานหมากรุก

หากคุณวนลูปเหนืออาร์เรย์ di และ dj การตีความค่า di เป็นออฟเซ็ต x และค่า dj เป็นออฟเซ็ต y คุณจะครอบคลุม 8 ทิศทางที่เป็นไปได้แต่ละทิศทาง

สมมติว่าบวก x อยู่ทางทิศตะวันออกและบวก y อยู่ทางใต้ (ตามคำตอบของ Patashu) คุณจะได้สิ่งต่อไปนี้

  | ดิ / 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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.