Sahte-rastgele yerine, "zevkli" rastgele nasıl üretebilirim?


26

Sırayla farklı türde bulmacalar sunan bir oyun yapıyorum. Her bulmacayı yalancı ve numaradan seçiyorum. Her bulmacanın çeşitli varyasyonları vardır. Başka bir sözde rasgele sayı ile değişimi seçiyorum. Ve bunun gibi.

Mesele şu ki, bu neredeyse gerçek rastlantısallık üretirken, oyuncunun gerçekte istediği şey bu değil. Oyuncu genellikle neyi algıladıklarını ve rastgele olarak tanımladıklarını ister, ancak yalnızca bulmacaları tekrar etme eğiliminde değilse. Yani, gerçekten rastgele değil. Sadece tahmin edilemez.

Bazı düşünceler vererek, bunu yapmanın sahte yollarını hayal edebiliyorum. Örneğin, yeni bir seçenek seçerken en son N seçeneğini olasılıklar setinden geçici olarak elimine edin. Veya her seçeneğe eşit olasılık atamak, seçimde seçim şansını sıfıra indirmek ve ardından her seçimde yavaşça tüm olasılıkları artırmak.

Bunu yapmanın yerleşik bir yolu olduğunu varsayıyorum, ancak terminolojiyi bilmiyorum bu yüzden bulamıyorum. Bilen var mı? Veya kimse bunu hoş bir şekilde çözdü mü?


4
"AI Game Programming Wisdom 2" kitabında, hatırladığım kadarıyla tam olarak aradığınız şey olan filtrelenmiş rastgelelik üzerine bir bölüm var. Şu anda elimde değil, o yüzden sana tam bir cevap veremem.
Anton

Denemek ve açıklığa kavuşturmak için: 'yapbozları tekrar etme' derken, aynı tipte iki yapbozun yan yana gelmesini istemiyor musunuz? Yani başka bir deyişle, eğer sadece bir sudoku seçtiyseniz, başka bir sudoku bulmacası sunmayın, ancak Sudoku # 19 ise, bundan sonra Picross # 19'u önermek sorun değil (diğer bir deyişle, varyasyon sayısı önemli değil) ?
Steven Stadnicki


1
Tamam, AI Game Programming Wisdom 2 kopyası geldi. Filtrelenmiş rastlantısallık bölümünü okudum ve kaynak kodunu kontrol ettim. Bu muhtemelen en iyi yaklaşımdır. Bu sadece rastgele sayıları kullanmamı sağlıyor, ancak beklenmeyen kalıpların oluşmaması için sayıları filtreliyorum. Karıştırma çantasından daha kurşun geçirmez görünüyor.
Hilton Campbell

1
Yine başka bir güncelleme ... benim özel uygulamam için filtrelenmiş rastgelelik tam olarak yapmadı. Gerçekten oyuncunun tekrar etmeden önce tüm türleri ve alt tipleri oynamasını istiyorum, bu yüzden karışık bir çantayla gittim.
Hilton Campbell

Yanıtlar:


25

Sınırlı sayıda bulmacaya sahipseniz, şunları yapabilirsiniz:

  • Hepsi veya rastgele seçilmiş bir bulmaca listesi oluşturun;
  • Bu listeyi karıştır ( örneğin , Knuth Shuffle'a bakınız );
  • Oynatıcınız bu listede oynasın;
  • Liste boşaldığında, yenisiyle başlayın.

DÜZENLE

Bunu bilmiyordum, fakat SE'ye göz atmak, bunun aslında bir "karıştırma çantası" olarak bilindiğini anlamamı sağladı. Biraz daha Infos burada , burada ya orada .

EDIT 2

Klasik Knuth Shuffle şu tarafa gider:

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, yorumunda, bu tür bir şeyin bir görev değişikliği üzerinde tekrarı engellemediğine dikkat çekti. Bunu dikkate almanın bir yolu, son madde için özel bir durum eklemektir:

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
Bu işe yarayabilir ancak sona erdiğiniz aynı öğeyle başlamamak için her oyuncunun ardından görev değişikliği durumunda biraz dikkatli olmalısınız.
Steven Stadnicki

@Steven Indeed. Bu öğe yeni listeden çıkarılabilir. Aslında, yalnızca birkaç rastgele öğenin bir listesini oluşturmak ve bir sonraki listeyi yalnızca kalan öğelerle birlikte oluşturmak bir fikir olabilir. Yani, 100 öğeniz varsa, örneğin 10'lu karıştırılmış bir liste oluşturun. Bu listeyle işiniz bittiğinde, 90'ında daha önce seçilmeyen 10 öğeyle bir sonrakini oluşturun.
Laurent Couvidou

+1. Bu tekniğin "daha eğlenceli" olması için destek eklendi: Tetris, örneğin "rastgele" parçalar üretiyor. Her bir parçadan birinin bir kümesi karıştırılır ve yinelenir, bu da gerçek rastlantının kaçınılmaz olarak üreteceği kopyaların uzun dizilerini önler.
KutuluMike

1
@Hilton Bu türden "hoşlanmam, rastgele döngü bana istediğimi verirken" yaklaşımını beğenme eğilimindeyim. Ama yine de, bunun her zaman rastgele sonsuz döngüler veya performans düşüşleri çağrısı olduğunu düşünüyorum - ki bu hata ayıklamak korkunç. Önceki listenin son öğesini yeni listeden çıkarmak, aynı sonuç için yalnızca bir kez karıştırmanıza izin verir.
Laurent Couvidou

1
Haklısın ve ben de aynı çekinceleri yaşadım. Önceki son öğeyi hariç tutmak yerine, şimdi sadece bir kez karıştırdım ve önceki son öğe ilk önce şimdi ise, rastgele başka bir öğeyle değiştiriyorum.
Hilton Campbell

2

Lorancou'nun yaklaşımına ilişkin bir değişken: Her bir bulmaca türü için, (karıştırılmış) bir bulmaca numarası dizisi tutun; o zaman bu tür bir bulmacayı her çarptığınızda, listeden bir sonraki numarayı alın. Mesela Sudoku, Picross ve Kenken bulmacalarına ve her biri # #.6 yapbozlara sahip olduğunuzu varsayalım. Her bulmaca türü için bir tane olmak üzere üç adet karıştırılmış 1..6 sayı dizisi oluşturacaksınız:

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

Şimdi, bulmaca türlerini aynen lorancu'nun önerdiği gibi karıştırırsınız; diyelim ki [Picross, Sudoku, Kenken]. Daha sonra, belirli bir türden bir bulmacayı her çarptığınızda, bir sonraki sayıyı 'karıştırma listesinde' kullanın; Genel olarak bulmaca sunumunuz [Sudoku # 5, Picross # 6, Kenken # 3, Sudoku # 6, Picross # 2, Kenken # 2, ...] olacaktır.

Bulmacaları döngü boyunca her seferinde aynı düzende tutmak istemiyorsanız, o zaman 'rastgele seçtiniz, son birkaç seçmeyi gözardı etmek' seçeneğiniz en iyisidir. Bunu da biraz daha verimli hale getirmenin yolları var; Mesela, diyelim ki 20 şeye sahipsin ve son 5 şeyi görmezden gelmek istiyorsun. Daha sonra rastgele bir sayı 1..20 seçmek ve son 5 dışında bir numara elde edene kadar 'tekrar' yerine geçmek yerine, sadece bir sayı 1..15 seçin ve bulmaca türlerinizde o kadar fazla adım attığınızı seçin; seçildi (bunu, en son 5 bulmacayı tutan bit dizisini tutarak kolayca yapabilirsiniz).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.