วิธีการแบ่งตารางฐานสิบหกอย่างเท่าเทียมกันในหมู่ผู้เล่น n?


15

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

ฉันรู้ว่ามันเป็นไปไม่ได้สำหรับผู้เล่นสองหรือสามคน (เช่นนี้คล้ายกับปัญหา "ระบายสีแผนที่") และฉันก็โอเคกับการแก้ปัญหาอื่น ๆ สำหรับพวกเขา (เช่นการสร้างแผนที่ที่แก้ปัญหาแทน) แต่สำหรับผู้เล่นสี่ถึงแปดคนฉันจะแก้ไขปัญหานี้ได้อย่างไร


Cellular automata เป็นวิธีที่ง่ายคล้ายกับสิ่งนี้: แผนที่ง่าย ๆ สี่รายได้และวิธีการแจกจ่าย
MichaelHouse

คำตอบ:


3

นี่คือสิ่งที่ฉันจะทำ:

  1. กำหนดเซลล์ทั้งหมดให้กับผู้เล่นแบบสุ่ม บนแผนที่ขนาดใหญ่นี่น่าจะเป็นจำนวนมากสำหรับผู้เล่นทุกคนบนแผนที่ขนาดเล็กคุณอาจต้องทำการแก้ไขบางอย่าง
  2. แยกส่วนที่มีขนาดใหญ่เกินไป สิ่งที่ง่ายที่สุดที่จะทำคือใช้ไทล์ทั้งหมดเป็นชิ้น ๆ แล้วสุ่มแต่ละไทล์อีกครั้ง
  3. ในกรณีที่จำนวนเซลล์ไม่สมดุลกัน (เช่นผู้เล่น A มี 24 เซลล์ผู้เล่น B มี 16 คน) กำหนดเซลล์อีกสองเซลล์จากผู้เล่นที่แสดงเกินจริงไปยังผู้เล่นที่มีบทบาทต่ำกว่า
  4. ตรวจสอบชิ้นส่วนอีกครั้ง หากขั้นตอนที่ 3 เปิดตัวชิ้นส่วนใหม่ให้กลับไปที่ขั้นตอนที่ 2 ถ้าไม่ใช่แผนที่ดี!

ป.ล. ฉันไม่คิดว่าปัญหานี้จะเกิดขึ้นไม่ได้เลยปัญหาการระบายสีแผนที่นั้นแตกต่างกันมาก (สำหรับสิ่งหนึ่งที่เป็นอีกวิธีคือรูปร่าง -> สีแทนที่จะเป็นสี -> การกำหนดไทล์)
Junuxx

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

1
@manabreak: ฉันทำบางสิ่งบางอย่างที่จะลอง ด้วยการเปลี่ยนแปลงเล็กน้อยไปยังขั้นตอนที่ 2 (กำหนดใหม่โดยการขี่จักรยานผ่านผู้เล่นทุกคนแทนที่จะกำหนดใหม่แบบสุ่ม) มันทำงานได้ค่อนข้างดี ฉันจะพยายามเขียนมันเมื่อฉันมีเวลา
Junuxx

1
นั่นดูเหมือนสิ่งที่ฉันกำลังมองหา :)
manabreak

1

สมมติว่าคุณมี hexmap ของnเซลล์ทั้งหมดและpผู้เล่นที่p <= nวิธีที่ดีที่สุดในการจัดการกับปัญหานี้คือการกระจายแบบ round-robinผ่านทางเซลลูลาร์ออโตมาตา (CA)

initialisation

สุ่ม (และ / หรือใช้ฮิวริสติกบางส่วนหรืออื่น ๆ เช่นระยะทางจากศูนย์กลางแผนที่) เลือกเซลล์เริ่มต้นสำหรับผู้เล่นแต่ละคน ตั้งแต่p <= nนี้ไม่ควรเป็นปัญหา

ออโตเซลลูล่าร์

คุณต้องการการเชื่อมต่อเต็มรูปแบบระหว่างเซลล์ฐานสิบหกของคุณ ฉันขอแนะนำอาร์เรย์ 6 เพื่อนบ้านต่อเซลล์:

class Cell
{
   //... other members...
   Cell[6] neighbours = new Cell[6];
}

การใช้อาร์เรย์ขนาดคงที่ช่วยให้แนวคิดของทิศทางภูมิประเทศระหว่างเซลล์มีอยู่ซึ่งรายการหรือเวกเตอร์จะไม่ปรากฏขึ้น ฉันแนะนำสิ่งนี้เพราะมันอาจทำให้การนำทางบางอย่างง่ายขึ้น

นอกจากนี้คุณยังสามารถจัดเก็บ hexmap ของคุณในอาร์เรย์ 2D โดยมีออฟเซ็ตต่อแถว อย่างไรก็ตามวิธีนี้อาจใช้งานง่ายกว่าการจัดเก็บอาเรย์เพื่อนบ้านต่อเซลล์เพียงเล็กน้อยเนื่องจากการชดเชยทางเรขาคณิตในแถวอื่น ๆ

ตรวจสอบให้แน่ใจว่าทุกเซลล์เชื่อมต่อกับทุกสิ่งที่เป็นเพื่อนบ้าน คุณสามารถทำสิ่งนี้ทีละแถวแต่ละเซลล์ในขณะที่คุณสร้าง hexmap เต็ม ป.ล. ถ้าคุณต้องการ hexmap ที่ไม่มีขอบเขตคุณจะสามารถลบแต่ละเซลล์และอ้างอิงไปยังเซลล์เหล่านั้นเพื่อสร้างช่องว่างด้านลบเพื่อให้คุณสามารถสร้างเค้าร่างแผนที่อินทรีย์

การกระจายแบบวนรอบ

pseudocode:

count number of neutral cells in entire map, minus those starting cells taken by players
while neutral cells remain (or while true)
   for each player
      if player has not yet reached expected territory size in cells
         for each cell already constituting this player's territory
           if territory can grow by one cell into a neutral neighbour
              grow into neighbour
              reduce neutral cell count for entire map by one
              if no more neutral cells remain in map
                 break out of outermost while loop immediately
              else
                 continue to next player immediately
begin game

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

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


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

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

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

@fnord ตรรกะของคุณเป็นความผิด ในประโยคสุดท้ายของคุณคุณยอมรับว่าอัลกอริทึมของฉันหยุดที่ขนาดเกาะnและหลังจากนั้นขัดแย้งกับตัวเองโดยบอกว่าคุณ "ไม่เห็นทาง" แต่ฉันทำ "พูดถึง [วิธีที่จะได้เกาะ] ในข้อความต่อมา" ฉันหรือไม่ได้ตอบคำถาม? อัลกอริทึมทั่วไปนี้อาจใช้ในการกระจายเซลล์ (โดย จำกัดnที่ 1) หรือเพื่อสร้างเกาะ (โดยการตั้งค่า n> 1) ดังนั้นคุณมีอัลกอริธึมเดียวไม่เพียง แต่ความสามารถในการกระจาย แต่รวมถึงกลุ่มด้วย สิ่งนี้ไม่ตอบคำถามของ OP อย่างไร มันคุ้มค่ากับการลงคะแนนอย่างไร
วิศวกร

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

0

อีกวิธีคือการเริ่มต้นด้วยการแจกแจงที่ 'ยุติธรรม' แต่ปกติแล้วใช้การประเมินที่คล้ายกับการจำลองการหลอมเพื่อแยกความสม่ำเสมอโดยไม่สูญเสียความยุติธรรม:

  • เริ่มต้นด้วยการกำหนดสีให้กับเซลล์ทั้งหมดของกริดของคุณในรูปแบบปกติ (เช่นมีรูปแบบ '123412341234' ซ้ำในแถวแรกตามด้วย '341234123412' ในถัดไปเป็นต้น) ซึ่งอาจนำไปสู่การกระจายไม่สม่ำเสมอของสีถ้าแผนที่ของคุณโดยเฉพาะอย่างยิ่งที่มีรูปร่างไม่ดี แต่ฉันทะนงว่าคุณกำลังเริ่มต้นด้วยแผนที่คงที่ดังนั้นคุณควรจะสามารถที่จะหาบางสีปกติ equidistributed ของมัน
  • จากนั้นทำซ้ำขั้นตอนต่อไปนี้สำหรับขั้นตอนมากที่สุดเท่าที่คุณรู้สึก (ไม่มีเกณฑ์ 'doneness' จริงดังนั้นการทดลองจะบอกคุณว่าขั้นตอนที่เหมาะสมจำนวนขั้นต่ำคืออะไร):
    • เลือกสององค์ประกอบของตารางโดยการสุ่ม
    • หากพวกเขามีสีเดียวกันลองอีกครั้ง (ไม่มีจุดอื่นตั้งแต่นั้นการแลกเปลี่ยนจะไม่ใช่แบบไม่มี op) คุณมีโอกาสเพียงแค่ 1/4 ในการกดปุ่มสีเดียวกันและโอกาส 1/16 ในการกดปุ่มสีเดียวกัน สองครั้งติดต่อกันดังนั้นคุณไม่ควรลองใหม่มากเกินไป)
    • สลับสีขององค์ประกอบทั้งสองอย่างชั่วคราว
    • ทดสอบขนาดของภูมิภาคที่เพิ่งสร้างใหม่ในตำแหน่งขององค์ประกอบหลังการสลับ:
      • ทำการเติมน้ำท่วมอย่างง่ายจากจุดใหม่ของแต่ละองค์ประกอบเพื่อกำหนดว่าภูมิภาคของสีนั้นจะมีการแลกเปลี่ยน
    • หากหนึ่งในสองภูมิภาคนี้มีขนาดใหญ่กว่าเกณฑ์ของคุณให้ยกเลิกการแลกเปลี่ยนชั่วคราว มิฉะนั้น 'จบ' การสลับสีของสององค์ประกอบ '

ปุ่มตรงนี้คือความจริงที่ว่าคุณสลับสองจุดหมายความว่าคุณจะไม่ปรับสมดุลสีและทดสอบแบบที่คุณทำก่อนที่จะทำการสับเปลี่ยนเพื่อให้แน่ใจว่าคุณไม่เคยสร้างพื้นที่ที่มีขนาดใหญ่เกินไป หากคุณมีวิธีการแสดงกริดของคุณคุณสามารถจินตนาการถึงกระบวนการนี้เพื่อดูว่ามัน 'สร้าง' ภูมิภาคของมันอย่างไรผ่านการสลับซ้ำ

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


วิธี Stochastic ไม่มีประสิทธิภาพ สำหรับวิธีการเช่นเดียวกับฉันที่พิจารณาขั้นตอนรันไทม์เข้าใกล้ O (n) สำหรับเซลล์แผนที่ n สำหรับอัลกอริทึมของคุณคือ O (n * m) โดยที่ m คือจำนวนเซลล์ที่ต้องการต่อเกาะ (จริง ๆ สำหรับเกาะที่มีศักยภาพแต่ละแห่ง) ดีที่สุดเสมอที่จะมุ่งสำหรับอัลกอริทึมที่มีรันไทม์ที่ประเมินได้อย่างง่ายดาย แทนที่จะแก้ไขแผนที่ที่สร้างขึ้นแบบส่งเดชควรสร้างแผนที่ที่ไม่เสียหายหรือไม่ได้ผลในตอนแรกในขั้นตอน n ดังนั้นจึงรักษากระบวนการที่มีประสิทธิภาพและควบคุมได้
วิศวกร
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.