ตรวจสอบว่าชุดของกระเบื้องในตารางเป็นรูปร่างที่ล้อมรอบ


10

รับชุดไพ่ในตารางฉันต้องการตรวจสอบ:

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

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

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

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

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

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

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

ด้านบนฉันวาดภาพสิ่งที่ฉันคาดหวังว่าผลลัพธ์ที่เป็นไปได้ 4 ข้อของการทดสอบนี้คือ

  1. โซ่ไม่ได้ทำรูปที่ถูกปิดล้อม

  2. โซ่ทำรูปที่ปิดล้อม

  3. หากคุณนับด้านข้างของกระดานเป็นขอบ (หรือมากกว่าหนึ่งขอบ) ของรูปภาพโซ่จะสร้างรูปที่ล้อมรอบ

  4. ห่วงโซ่จะสร้างรูปที่ถูกปิดล้อม แต่มีจุดข้อมูลเพิ่มเติม (ผู้ใช้เลือกอย่างถูกต้องเป็นส่วนหนึ่งของห่วงโซ่) ซึ่งไม่ได้เป็นส่วนหนึ่งของรูปที่สร้างขึ้น

กรณีที่ 4 นั้นยากที่สุดเพราะคุณต้องแยกลิงก์โซ่ "พิเศษ" เพื่อค้นหารูปที่แนบมาและชิ้นส่วนที่อยู่ข้างใน (แต่ไม่ต้องอยู่รอบ ๆ พื้นที่

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


1
สิ่งที่เกี่ยวกับตัดเส้นทางเหมือนรูป-8 หรือรูปดาวห้าแฉก ? คุณจะถือว่าไม่เป็นศูนย์หรือแม้กระทั่งแปลกกฎเติม ?
Anko

กรณีที่ 4 อาจรวมกับกรณีที่ 3: ล้อมรอบโดยใช้ด้านข้างของบอร์ดพร้อมข้อมูลเพิ่มเติม
ChargingPun

หากคุณมีเส้นแนวตั้งวิ่งลงมาจากกึ่งกลางของบอร์ดจากขอบบนถึงล่างด้านใดของบอร์ด 'ล้อมรอบ'?
Steven Stadnicki

ฉันคิดว่าเราควรสมมติว่าพื้นที่ที่เล็กที่สุดถูกปิดไว้สำหรับตอนนี้ เว้นแต่ OP ระบุไว้เป็นอย่างอื่น
Tom 'Blue' Piddock

คำตอบ:


3

1. ตรวจจับการวนของไทล์

ดูเหมือนว่าปัญหาคล้ายกับการตรวจสอบวงจร (วง) ในกราฟให้ดูที่นี่หรือที่นี่

  • ชุดของโหนดVของกราฟG=(V, E)นั้นคือไพ่
  • ขอบe = (v1, v2)มีอยู่ระหว่างสองโหนดที่แตกต่างกันถ้ากระเบื้องเป็นเพื่อนบ้านโดยตรงหรือแนวทแยง

2. การจัดการกรณีชายแดนหน้าจอ

เส้นขอบของหน้าจอประกอบด้วยแผ่นจินตภาพซึ่งจะเป็นขอบแผ่นเดียวรอบ ๆ หน้าจอของแผ่นกระเบื้องที่มองเห็นได้

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

  • มีขอบอีกอันหนึ่งอยู่ระหว่างโหนดสองโหนดที่แตกต่างกันหากไทล์ทั้งสองอยู่ในตำแหน่งที่ใกล้กับขอบของหน้าจอ

ดังนั้นไทล์ที่ (0,0) และ (1,0) จะเป็นส่วนหนึ่งของวงปิดพร้อมกับ "ไทล์ขอบ" (-1,0), (-1, -1), (0, -1) , (1, -1)

3. ส่วนด้านในของพื้นที่ลูป

ฉันจะไปในทิศทางที่คุ้นเคยกับสิ่งที่ผู้ใช้Arthur Wulf Whiteแนะนำ:

จำกัด ชุดของไพ่ที่เราต้องตรวจสอบโดยกล่อง bounding ของไพ่วนรอบ

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

การขยายกล่องล้อมรอบด้วยกระเบื้องเดียวในแต่ละทิศทางจะเป็นความคิดที่ดีเช่นกันextbbดังนั้นเราจึงจบลงที่จุดเชื่อมต่อภายนอกหนึ่งชุดในกรณีที่เราเริ่มต้นน้ำท่วมเติมด้วยกระเบื้องภายนอก

ffbbเมื่อเรามีพื้นที่น้ำท่วมเติมเราจะคำนวณกรอบของมันเช่นกัน ในกรณีที่เราเริ่มต้นด้วยกระเบื้องด้านนอกมันควรจะเหมือนกับกล่องขอบลูปแบบขยาย

ffbb == extbb

ในกรณีที่เราเริ่มต้นด้วยกระเบื้องภายในมันควรจะให้กล่องขนาดเล็กลงอย่างชัดเจนเนื่องจากแผ่นวนรอบต้องถูกประกบอยู่ระหว่างกล่องขอบทั้งสอง

ffbb < extbb

ไทล์เริ่มต้นเริ่มต้นสำหรับการเติมน้ำท่วมอาจเป็นไทล์ใด ๆ ภายในextbbซึ่งเป็นไทล์ฟรี บางทีการเลือกแบบสุ่มเป็นวิธีที่ดีที่สุด

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

หมายเหตุสุดท้าย

Normaly ฉันจะบอกว่าการเดินง่าย ๆ เริ่มต้นจากไทล์บางส่วนและการเก็บรายการของไทล์ที่เยี่ยมชมนั้นเพียงพอที่จะตรวจจับรอบ แต่เงื่อนไขขอบเขตของหน้าจอนั้นอาจให้กราฟที่ซับซ้อนกว่าดังนั้นคุณควรอยู่ในด้านที่ปลอดภัยด้วยอัลกอริทึมกราฟ .

ด้านล่างนี้เป็นตัวอย่างที่ไม่ได้เชื่อมต่อการตกแต่งภายในในทางกลับกันการตรวจจับรอบควรหาสองลูปในกรณีนั้นหนึ่งควรได้รับการทิ้ง

บางกรณี


1

คุณสามารถแก้ไขได้โดย:

  1. การค้นหากล่องขอบของรูปร่างนั้น
  2. การเพิ่มขนาดของมันทีละ 1 ในแต่ละทิศทาง
  3. วนรอบกรอบของกล่องขอบเขตใหม่ที่ขยายใหญ่ขึ้นเล็กน้อยและใช้การเติมน้ำท่วม
  4. หากมีแผ่นกระเบื้องใด ๆ ที่คุณไม่ได้ทำเครื่องหมายด้วยการเติมน้ำท่วมที่ไม่ได้อยู่ในห่วงโซ่นั้นพวกเขาจะถูกล้อมรอบ ฉันคิดว่าตามคำนิยามของคุณหากมีกระเบื้องล้อมรอบกว่ารูปร่างเป็นรูปปิด

ที่จะทำอย่างใดอย่างหนึ่งย้ำกว่ากระเบื้องทั้งหมดในห่วงโซ่และพบของพวกเขาminX, minY, maxXและmaxYและที่เป็นกรอบของ AABB

สองเป็นเรื่องเล็กน้อย

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

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


0

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

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

ตอนนี้เราสำหรับแต่ละแถวทำต่อไปนี้:

  1. เริ่มที่ขอบซ้ายและติดตามบูลีนสำหรับแต่ละไทล์ซึ่งบอกว่าเราเข้าหรือออก เริ่ม.
  2. หากไทล์ปัจจุบันเป็นส่วนหนึ่งของห่วงโซ่ให้ดูทั้งตัวตายตัวแทนและตัวต่อ (ซึ่งจะต้องอยู่ติดกัน) หากอย่างใดอย่างหนึ่งอยู่เหนือ (เช่นเหนือ, ตะวันออกเฉียงเหนือ, หรือตะวันตกเฉียงเหนือของกระเบื้องปัจจุบัน) ตั้งค่าสถานะของกระเบื้องปัจจุบันไปทางตรงกันข้ามของกระเบื้องไปทางซ้าย มิฉะนั้นให้ตั้งค่าเป็นแบบเดียวกันกับไทล์ทางซ้าย ไปที่ 4
  3. หากไทล์ปัจจุบันไม่ได้เป็นส่วนหนึ่งของห่วงโซ่ให้ตั้งค่าไทล์เป็นสถานะของชื่อทางด้านซ้าย ไปที่ 4
  4. ไทล์ทางด้านขวาตอนนี้เป็นไทล์ปัจจุบัน ไปที่ 2

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

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

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

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