의사 난수 (pseudo-random)와 달리 "즐겁게"무작위를 생성하는 방법


26

여러 종류의 퍼즐을 순서대로 제시하는 게임을 만들고 있습니다. 나는 의사 난수로 각 퍼즐을 선택합니다. 각 퍼즐마다 여러 가지 변형이 있습니다. 다른 의사 난수로 변형을 선택합니다. 등등.

문제는 이것이 거의 임의의 확률을 생성하지만 플레이어가 실제로 원하는 것은 아닙니다. 플레이어는 일반적으로 자신이 인식하고 무작위로 식별하는 것을 원하지만 퍼즐을 반복하지 않는 경우에만 가능합니다. 따라서 무작위는 아닙니다. 그냥 예측할 수 없습니다.

생각을 해보면 해키 방법을 상상할 수 있습니다. 예를 들어, 새로운 선택을 선택할 때 일련의 가능성 중에서 가장 최근의 N 선택을 일시적으로 제거합니다. 또는 모든 선택에 동일한 확률을 할당하여 선택시 선택 확률을 0으로 줄인 다음 각 선택에 따라 모든 확률을 천천히 증가시킵니다.

이 작업을 수행하는 기존의 방법이 있다고 가정하지만 용어를 알지 못하므로 찾을 수 없습니다. 누구 알아? 아니면 누군가가 이것을 즐거운 방법으로 해결 했습니까?


4
"AI Game Programming Wisdom 2"책은 내가 기억하는 것에서 여러분이 찾고있는 것과 정확히 일치하는 필터링 된 무작위성에 관한 장을 가지고 있습니다. 나는 지금 그것을 가지고 있지 않으므로 실제로 당신에게 완전한 대답을 줄 수는 없습니다.
Anton

시도하고 명확히하기 위해 : 당신이 '반복 퍼즐 없음'이라고 말할 때 당신은 서로 같은 유형의 두 개의 퍼즐을 원하지 않는다는 것을 의미합니까? 다시 말해, 스도쿠를 골랐다면 다른 스도쿠 퍼즐은 제공하지 않지만 스도쿠 # 19 인 경우 Picross # 19를 제공해도됩니다 (즉, 변형 번호는 중요하지 않습니다). ?
Steven Stadnicki


1
AI Game Programming Wisdom 2가 방금 도착했습니다. 필터링 된 임의성에 대한 장을 읽고 소스 코드를 확인했습니다. 이것은 아마도 가장 좋은 방법 일 것입니다. 난수를 사용할 수 있지만 예기치 않은 패턴이 발생하지 않도록 숫자를 필터링하십시오. 셔플 백보다 방탄이 더 좋습니다.
힐튼 캠벨

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

@Steven 실제로. 이 항목은 새 목록에서 제외 될 수 있습니다. 실제로, 임의의 항목 몇 개만 목록을 작성하고 나머지 항목 만 사용하여 다음 목록을 작성하는 것이 좋습니다. 따라서 100 개의 아이템을 가지고 있다면, 예를 들어 셔플 된 10의리스트를 만드십시오.이리스트를 완료하면, 이전에 선택되지 않은 90 개에 10 개의 아이템으로 다음 아이템을 빌드하십시오.
Laurent Couvidou

+1. "더 재미있다"는이 기술에 대한 지원이 추가되었습니다. 예를 들어 테트리스가 "무작위"조각을 만드는 방식입니다. 각 조각 중 하나의 집합을 섞고 반복하여 진정한 임의성이 필연적으로 생성되는 긴 복제 시퀀스를 피합니다.
KutuluMike

1
@Hilton 나는 이런 종류의 "루프가 무작위로 내가 원하는 것을 줄 때까지"접근하는 것을 싫어하는 경향이있다. 그러나 여전히, 나는 이것이 무한한 무한 루프 또는 성능 저하에 대한 호출이라고 생각합니다. 이는 디버그하기가 끔찍합니다. 이전 목록의 마지막 항목을 새 목록에서 제외하면 동일한 결과를 위해 한 번만 셔플 할 수 있습니다.
Laurent Couvidou

1
네 말이 맞고 나는 같은 예약을했다. 이전 마지막 항목을 제외하지 않고 이제 한 번만 셔플 한 다음 이전 마지막 항목이 먼저 있으면 다른 항목과 무작위로 교환합니다.
힐튼 캠벨

2

lorancou의 접근 방식에 대한 변형 : 각 퍼즐 유형에 대해 (셔플) 퍼즐 번호 배열을 유지하십시오. 그런 다음 해당 유형의 퍼즐을 칠 때마다 다음 숫자를 목록에서 가져옵니다. 예를 들어 스도쿠, 피 크로스 및 켄켄 퍼즐이 있으며 각각 퍼즐 # 1..6이 있다고 가정 해 봅시다. 각 퍼즐 유형에 대해 하나씩 숫자 1..6의 셔플 배열 3 개를 만듭니다.

  • 스도쿠 : [5, 6, 1, 3, 4, 2]
  • 파이 크로스 : [6, 2, 4, 1, 3, 5]
  • 켄켄 : [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을 선택하는 대신 마지막 5 이외의 숫자를 얻을 때까지 '재 롤링'하는 대신 숫자 1..15를 선택하고 많은 단계를 거치면서 퍼즐 유형을 건너 뜁니다. 선택되었습니다 (마지막으로 선택한 5 개의 퍼즐을 보유한 비트 배열을 유지하면이 작업을 쉽게 수행 할 수 있습니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.