ฉันจะสุ่มแบบ "สนุกสนาน" ได้อย่างไรเมื่อเทียบกับการสุ่มหลอก?


26

ฉันกำลังสร้างเกมที่แสดงปริศนาต่าง ๆ ตามลำดับ ฉันเลือกตัวต่อแต่ละตัวพร้อมหมายเลขหลอกเทียม สำหรับแต่ละตัวต่อจะมีหลากหลายรูปแบบ ฉันเลือกรูปแบบที่มีหมายเลขสุ่มเทียมอื่น และอื่น ๆ

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

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

ฉันคิดว่ามีวิธีการที่กำหนดไว้แล้ว แต่ฉันก็ไม่รู้คำศัพท์ดังนั้นฉันไม่สามารถหามันได้ ใครรู้บ้าง หรือมีใครแก้ปัญหานี้ด้วยวิธีที่ถูกใจ?


4
หนังสือ "AI Game Programming Wisdom 2" มีบทหนึ่งเกี่ยวกับการสุ่มแบบกรองซึ่งจากสิ่งที่ฉันจำได้มันเป็นสิ่งที่คุณกำลังมองหา ฉันยังไม่มีในขณะนี้ดังนั้นฉันไม่สามารถให้คำตอบแบบเต็มกับคุณได้
Anton

หากต้องการลองและอธิบายให้ชัดเจน: เมื่อคุณพูดว่า 'ไม่ทำซ้ำตัวต่อ' คุณหมายถึงคุณไม่ต้องการตัวต่อสองตัวที่มีประเภทเดียวกันติดกันหรือไม่? ถ้าคุณเลือกซูโดกุอย่าเสนอตัวต่อซูโดกุอีกต่อไป แต่ถ้าเป็นซูโดกุ # 19 คุณก็สามารถเสนอ Picross # 19 ต่อไปได้ (ในคำอื่น ๆ หมายเลขชุดรูปแบบไม่สำคัญ) ?
Steven Stadnicki

2
คำถามที่เกี่ยวข้องมาก: stackoverflow.com/questions/910215/…
Chris Burt-Brown

1
ตกลงสำเนาของเกม AI ภูมิปัญญาการเขียนโปรแกรม 2 เพิ่งมาถึง ฉันอ่านบทเกี่ยวกับการกรองแบบสุ่มและตรวจสอบรหัสต้นฉบับ นี่อาจเป็นวิธีที่ดีที่สุด มันช่วยให้ฉันใช้ตัวเลขสุ่ม แต่จากนั้นกรองตัวเลขเพื่อไม่ให้เกิดรูปแบบที่ไม่คาดคิด ดูเหมือนว่าหลักฐานกระสุนมากกว่าถุงสลับ
Hilton Campbell

1
การอัพเดทอื่น ... สำหรับแอปพลิเคชันเฉพาะของฉันการกรองแบบสุ่มไม่ได้ทำอย่างนั้น ฉันต้องการให้ผู้เล่นเล่นผ่านทุกประเภทและประเภทย่อยก่อนที่จะทำซ้ำดังนั้นฉันจึงไปกับกระเป๋าสุ่ม
Hilton Campbell

คำตอบ:


25

หากคุณมีปริศนาจำนวน จำกัด คุณสามารถ:

  • สร้างรายการของปริศนาไม่ว่าจะเป็นทั้งหมดหรือบางส่วนที่สุ่มเลือก
  • สลับรายการนี้ (ดูKnuth Shuffleเป็นต้น);
  • ให้ผู้เล่นของคุณเล่นผ่านรายการนี้
  • เมื่อรายการว่างเปล่าให้เริ่มด้วยรายการใหม่

แก้ไข

ฉันไม่รู้สิ่งนี้ แต่การท่อง SE ทำให้ฉันรู้ว่านี่เป็นที่รู้จักกันในชื่อ "ถุงสุ่ม" บางข่าวสารเพิ่มเติมที่นี่ , ที่นี่หรือมี

แก้ไข 2

Knuth Shuffle แบบคลาสสิกไปในลักษณะนี้:

To shuffle an array a of n elements (indices 0..n-1):
    for i from n  1 down to 1 do
        j  random integer with 0  j  i
        exchange a[j] and a[i]

Steven Stadnicki ชี้ให้เห็นอย่างถูกต้องในความคิดเห็นของเขาว่าสิ่งนี้ไม่ได้ป้องกันการทำซ้ำในการสับเปลี่ยน วิธีในการพิจารณาเรื่องนี้คือการเพิ่มเคสพิเศษสำหรับไอเท็มสุดท้าย:

To reshuffle an array a of n elements and prevent repetitions (indices 0..n-1):
    return if n <= 2

    // Classic Knuth Shuffle for all items *except* the last one
    for i from n  2 down to 1 do
        j  random integer with 0  j  i
        exchange a[j] and a[i]

    // Special case for the last item
    // Exchange it with an item which is *not* the first one
    r  random integer with 1  r  n - 1
    exchange a[r] and a[n - 1]

1
สิ่งนี้สามารถใช้งานได้ แต่คุณต้องระวังนิดหน่อยถ้าคุณทำการสับเปลี่ยนหลังจากการเล่นทุกครั้งไม่ให้เริ่มด้วยไอเท็มเดียวกันกับที่คุณเล่นจบ
Steven Stadnicki

@ สตีเว่นแน่นอน รายการนี้อาจถูกแยกออกจากรายการใหม่ ที่จริงแล้วมันอาจเป็นความคิดที่จะสร้างรายการของไอเท็มสุ่มสองสามอย่างเท่านั้นและสร้างรายการถัดไปด้วยไอเท็มที่เหลือเท่านั้น ดังนั้นถ้าคุณมี 100 รายการสร้างเช่นรายการสับ 10 เมื่อทำกับรายการนี้สร้างรายการถัดไปด้วย 10 รายการใน 90 ที่ไม่ได้เลือกก่อนหน้านี้
Laurent Couvidou

+1 เพิ่มการสนับสนุนสำหรับเทคนิคนี้ว่า "สนุกกว่า": นี่คือวิธีที่ Tetris ยกตัวอย่างเช่นสร้าง "สุ่ม" ชิ้น ชุดของชิ้นส่วนแต่ละชิ้นจะถูกสับและวนซ้ำไปมาซึ่งจะหลีกเลี่ยงการเรียงลำดับที่ซ้ำซ้อนกันนานซึ่งการสุ่มที่แท้จริงจะหลีกเลี่ยงไม่ได้
KutuluMike

1
@ ฮิลตันฉันมักจะไม่ชอบ "วิธีนี้ในขณะที่วนซ้ำจนกว่าฉันจะให้สิ่งที่ฉันต้องการ" วิธีการ ... ไม่น่าเป็นไปได้มากว่ามันจะทำให้เกิดปัญหาใด ๆ แต่ถึงกระนั้นฉันมักจะรู้สึกเช่นนี้เป็นสายสำหรับการสุ่มลูปไม่มีที่สิ้นสุดหรือลดลงประสิทธิภาพ - ซึ่งน่ากลัวในการแก้ปัญหา การยกเว้นรายการสุดท้ายของรายการก่อนหน้าจากรายการใหม่ช่วยให้คุณสามารถสลับได้เพียงครั้งเดียวเพื่อผลลัพธ์เดียวกัน
Laurent Couvidou

1
คุณพูดถูกและฉันก็มีการจองเหมือนกัน แทนที่จะแยกไอเท็มสุดท้ายก่อนหน้าตอนนี้ฉันมีการสับเปลี่ยนเพียงครั้งเดียวแล้วถ้าไอเท็มสุดท้ายก่อนหน้านี้เป็นอันดับแรกฉันสลับมันกับรายการอื่นแบบสุ่ม
Hilton Campbell

2

ตัวแปรในแนวทางของ lorancou: สำหรับปริศนาแต่ละประเภทเก็บอาร์เรย์ของหมายเลขปริศนา (สับ) จากนั้นทุกครั้งที่คุณต่อจิ๊กซอว์ของประเภทนั้นให้เอาหมายเลขถัดจากรายการ ตัวอย่างเช่นสมมติว่าคุณมีปริศนา Sudoku, Picross และ Kenken แต่ละตัวมีปริศนา # 1..6 คุณต้องการสร้างอาร์เรย์แบบสับสามแถวของตัวเลข 1..6 หนึ่งชุดสำหรับแต่ละปริศนา:

  • Sudoku: [5, 6, 1, 3, 4, 2]
  • Picross: [6, 2, 4, 1, 3, 5]
  • KenKen: [3, 2, 5, 6, 4, 1]

ตอนนี้คุณจะสลับประเภทปริศนาเหมือน lorancu แนะนำ; สมมติว่ามันเกิดขึ้น [Picross, Sudoku, Kenken] จากนั้นทุกครั้งที่คุณตีตัวต่อของประเภทที่กำหนดให้ใช้หมายเลขถัดไปใน 'รายการสุ่ม' โดยรวมการนำเสนอปริศนาของคุณจะเป็น [Sudoku # 5, Picross # 6, Kenken # 3, Sudoku # 6, Picross # 2, Kenken # 2, ... ]

หากคุณไม่ต้องการให้ปริศนาเรียงตามลำดับโดยรวมในแต่ละครั้งผ่านลูปฉันคิดว่า 'เลือกแบบสุ่มโดยไม่สนใจตัวเลือกไม่กี่ตัวเลือกสุดท้าย' ที่ดีที่สุด มีวิธีที่คุณสามารถทำให้สิ่งนี้มีประสิทธิภาพมากขึ้นเช่นกัน ตัวอย่างเช่นสมมติว่าคุณมี 20 สิ่งและคุณต้องการเพิกเฉยต่อการเลือก 5 รายการสุดท้าย จากนั้นแทนที่จะสุ่มเลือกหมายเลข 1..20 และ 'rerolling' จนกว่าคุณจะได้รับนอก 5 ครั้งล่าสุดแทนที่จะเลือกหมายเลข 1..15 และเดินผ่านประเภทปริศนาของคุณที่มีหลายขั้นตอนเพียงข้ามปริศนาประเภทใดก็ได้ที่ ถูกเลือก (คุณสามารถทำสิ่งนี้ได้อย่างง่ายดายโดยเก็บอาร์เรย์บิตที่เก็บปริศนาที่เลือก 5 ตัวล่าสุดไว้)

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