รับวงแหวนของกระเบื้องในตารางหกเหลี่ยม


17

ขอบคุณบทความนี้: กระเบื้องหกเหลี่ยมและการค้นหาเพื่อนบ้านที่อยู่ติดกันฉันสามารถรวบรวมกระเบื้องที่อยู่ติดกับกระเบื้องที่กำหนดได้ แต่ฉันติดอยู่กับอัลกอริทึมที่ทำให้ฉัน "วงแหวน" ของกระเบื้องที่ระบุโดยออฟเซ็ตเท่านั้น อัลกอริทึมที่กำหนดในโพสต์สแต็คโอเวอร์โฟลว์ไม่สนใจลำดับที่รวบรวมไทล์

ฉันรู้ว่ามีการเพิ่ม 6 ออฟเซ็ตทุกแผ่น

  • ออฟเซ็ต 1 ให้คุณได้ 6 ไทล์
  • ออฟเซ็ต 2 ให้ 12
  • ออฟเซ็ต 3 ให้ 18 และอื่น ๆ

มีการเติบโตอย่างต่อเนื่องที่ 6 จากการชดเชยแต่ละครั้ง ดังนั้นฉันคิดว่าควรมีกฎที่ปรับให้เหมาะกับการชดเชยเหล่านี้ ฉันไม่สามารถหาอันนี้ได้อย่างแน่นอน ใคร?

คำตอบ:


23

แหวนหกเหลี่ยมที่มีรัศมีของ N ประกอบด้วยเส้นตรง 6 เส้นแต่ละเส้นมีความยาว N - ดูตัวอย่างที่หยาบมากของฉันด้านล่าง :) สำหรับ N = 2:

ป้อนคำอธิบายรูปภาพที่นี่

ลูกศรครอบคลุม 2 hexes แต่ละอัน

ฉันคิดว่าคุณมีฟังก์ชั่นบางอย่างที่ให้ไทล์เพื่อนบ้านในทิศทางที่เฉพาะเจาะจงเช่นทิศเหนือ (), ตะวันออกเฉียงใต้ () ฯลฯ ดังนั้นอัลกอริธึมของคุณใน pseudocode ควรเป็นดังนี้:

var point = startingPoint.north(N)
for i = 0..N-1:
    result.add(point)
    point = point.southeast(1);
for i = 0..N-1:
    result.add(point)
    point = point.south(1);
for i = 0..N-1:
    result.add(point)
    point = point.southwest(1);
for i = 0..N-1:
    result.add(point)
    point = point.northwest(1);
for i = 0..N-1:
    result.add(point)
    point = point.north(1);
for i = 0..N-1:
    result.add(point)
    point = point.northeast(1);

โปรดทราบว่าการดำเนินการนี้ควรใช้กับกรณีขอบด้วย N = 1, ส่งคืนไพ่ 6 ใบและ N = 0 ส่งคืนชุดว่าง

ฉันรู้ว่ารหัสนั้นไม่สมบูรณ์ :) มีความซ้ำซ้อนอยู่ที่นี่ ในโครงการของฉันที่ใช้แผนที่เรียงต่อเนื่องเป็นประจำ (หกเหลี่ยมหรืออื่น ๆ ) ฉันมักจะมี "ทิศทาง" Enum ซึ่งช่วยให้ฉันทำสิ่งนี้ได้อย่างราบรื่นมากขึ้น:

var point = startingPoint.inDir(N, Direction.North)
var dir = Direction.SouthEast.
for d = 0..Direction.count():
    for i = 0..N-1:
        result.add(point)
        point = point.inDir(1, dir);
    dir = nextDirection(dir);

สิ่งนี้ควรผลักฉันไปในทิศทางที่ถูกต้อง ขอบคุณ!
Sidar

2
โปรดทราบว่าตัวอย่างโค้ดจะเพิ่มคะแนนที่ซ้ำกันสำหรับห้ากลุ่มแรก อย่างไรก็ตามมันเป็นคำตอบที่ดี
MichaelHouse

@ Byte56 ใช่ฉันคิดว่า แต่อย่างน้อยฉันก็เห็นการเชื่อมต่อระหว่างการเปลี่ยนทิศทาง!
Sidar

1
@ Byte56 จริงเหรอ? ฮึ่ม ฉันพยายามหลีกเลี่ยงสิ่งนั้น ... 0..N-1 ให้ 0..1 สำหรับ N = 2 ดังนั้นนั่นคือ i = 0 และ i = 1 ซึ่งเป็น 2 ค่า 2 ค่าจากแต่ละครั้ง 6 ทิศทางเป็น 12 ไทล์ตามที่ควรจะเป็น ... ?
Liosan

Nope คุณถูก. เนื่องจากแต่ละวงกำลังเพิ่มจุดจากวงสุดท้ายที่ฉันถูกปิดโดยหนึ่งสำหรับลูปความผิดพลาดของฉัน มันเป็นอัลกอริทึมที่ฉลาด
MichaelHouse

2

ฉันได้พบบทความนี้เป็นข้อมูลอ้างอิงที่ดีมากสำหรับอัลกอริธึมกริดแบบหกเหลี่ยมและส่วนของ "Distances" เป็นวิธีการในการกำหนดจำนวนขั้นตอนระหว่างสองไทล์ หากคุณแปลงพิกัดตามแนวแกน (xy) เป็นพิกัดลูกบาศก์ (xyz) ระยะทางจะเท่ากับค่าออฟเซ็ตพิกัดที่ใหญ่ที่สุดระหว่างสองไทล์หรือสูงสุด (| dx |, | dy |, | dz |)

การค้นหาทั้งหมดของตารางทั้งหมดสำหรับกระเบื้องในระยะที่ต้องการคือ O(n2) ด้วยขนาดกริด แต่เป็นการใช้งานง่ายที่ทำงานได้ดีสำหรับกริดขนาดเล็ก

ป้อนคำอธิบายรูปภาพที่นี่

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