예측 가능한 랜덤 생성기 필요


151

나는 웹 게임 개발자이고 난수에 문제가 있습니다. 플레이어가 20 % 확률로 칼로 치명타를가한다고 가정 해 봅시다. 즉, 5 개의 조회수 중 1 개가 중요해야합니다. 문제는 실제 결과가 매우 나쁘다는 것입니다. 때때로 플레이어는 5 타격에서 3 개의 치명타를가집니다. 전투는 다소 짧으므로 (3-10 타) 무작위 배분을 잘하는 것이 중요합니다.

현재 PHP를 사용 mt_rand()하고 있지만 코드를 C ++로 옮기는 중이므로 게임의 새 엔진에서이 문제를 해결하고 싶습니다.

솔루션이 균일 한 무작위 생성기인지 또는 적절한 분포를 강제하기 위해 이전의 임의 상태를 기억 해야할지 모르겠습니다.


58
실제 난수를 가정 할 때 정확히 3 번의 치명타가 발생할 확률은 약 0.5 %이고 2 번의 치명적이지 않은 치명타가 발생하고 3.5 건의 치명타가 15 번 발생할 수 있습니다.
Nixuz

10
+1 이상 난수의 특징 중 하나는 특이 치를 얻는다는 것입니다.
ConcernedOfTunbridgeWells

44
@Nixus : 아니요, 3 번의 치명타 및 2 번의 치명타가 발생할 확률은 약 5 %입니다. (5! / (3! * 2!)) = 10을 곱하는 것을 잊고 있습니다. 5 번의 타격에서 3 번의 치명타가 발생할 가능성은 통계적으로 거의 없습니다.
erikkallen 12

7
처음에는 이것이 바보 같은 질문이라고 생각했습니다 ... 다시 한번, 나는 너무 겸손합니다.
SergioL

답변:


39

일부 게임의 작은 실행에서 실제 임의성이 바람직하지 않다는 이전 답변에 동의합니다. 일부 사용에는 너무 불공평합니다.

Ruby의 구현과 같은 간단한 Shuffle Bag을 작성하고 몇 가지 테스트를 수행했습니다. 구현은 다음을 수행했습니다.

  • 여전히 공정한 것처럼 보이거나 최소 롤 임계 값에 도달하지 않은 경우 정규 확률을 기반으로 공정한 적중을 반환합니다.
  • 과거의 롤에서 관측 된 확률이 불공평 해 보이면 "공정화"적중을 반환합니다.

경계 확률에 따라 불공평 한 것으로 간주됩니다. 예를 들어 확률이 20 % 인 경우 10 %를 하한으로, 40 %를 상한으로 설정할 수 있습니다.

이러한 경계를 사용 하여 실제 유사 난수 구현이 해당 범위를 벗어난 결과를 생성 한 시간의 14.2 % 인 10 회의 실행 횟수를 발견했습니다 . 시간의 약 11 %, 0 회의 치명타가 10 회 시도되었습니다. 시간의 3.3 %, 5 회 이상의 치명타가 10 점에서 착륙했습니다. 당연히이 알고리즘 (최소 롤 수 5)을 사용하여 "Fairish"런의 훨씬 적은 양 (0.03 %)이 범위를 벗어났습니다. . 아래 구현이 적합하지 않더라도 (더 많은 영리한 일을 할 수는 있지만) 사용자가 실제 의사 난수 솔루션으로 불공평하다고 느끼는 경우가 종종 있습니다.

다음은 FairishBag루비로 작성된 나의 고기입니다 . 전체 구현 및 빠른 Monte Carlo 시뮬레이션 은 여기에서 사용할 수 있습니다 (gist) .

def fire!
  hit = if @rolls >= @min_rolls && observed_probability > @unfair_high
    false
  elsif @rolls >= @min_rolls && observed_probability < @unfair_low
    true
  else
    rand <= @probability
  end
  @hits += 1 if hit
  @rolls += 1
  return hit
end

def observed_probability
  @hits.to_f / @rolls
end

업데이트 : 이 방법을 사용하면 위의 범위를 사용하여 치명타를 입을 확률이 약 22 % 증가합니다. "실제"확률을 조금 낮게 설정하여이를 상쇄 할 수 있습니다. 공정한 수정으로 17.5 %의 확률은 약 20 %의 관측 된 장기 확률을 산출하고 단기 실행을 공정하게 유지합니다.


이것이 내 요구에 맞는 최상의 솔루션이라고 생각합니다. 최선의 대답으로 언급 된 셔플 백은 나쁘지 않지만 많은 계산이 필요하며 대상으로 이끄는 가장 간단한 솔루션을 좋아합니다.
사상가

Steve Rabin은 게임의 무작위성에 관한 흥미로운 기사를 썼습니다. 요컨대, 진정한 "무작위"행동은 대부분의 사람들에게 무작위로 "느낌"을 느끼지 않으며 연구는 이것을 뒷받침 해 왔습니다. 그의 기사는 AI 의사 결정 및 게임 로직에 대한 필터링 된 무작위성 (Filtered Randomness for AI Decisions)과 "AI 게임 프로그래밍 지혜 2"(2003)에 실렸다. 당신은 그것을 확인해야합니다, 아마 당신에게 유용 할 것입니다.
Jeff Tucker

@IanTerrell 테스트의 표본 크기가 얼마나 큰지, 즉 그 확률을 결정하기 위해 얼마나 많은 전투를하는지 설명하는 것이 좋습니다.

@ user677656 : 그것은 요지에 있지만, 100k입니다
Ian Terrell

223

즉, 5 개의 조회수 중 1 개가 중요해야합니다. 문제는 실제 결과가 매우 나쁘다는 것입니다. 때때로 플레이어는 5 타격에서 3 개의 치명타를 받고 때로는 15 타점에서 치명타를받지 않습니다.

필요한 것은 셔플 백 입니다. 그것은 게임에 대해 진정한 무작위가 너무 무작위라는 문제를 해결합니다.

알고리즘은 다음과 같습니다. 가방에 치명타 1 개와 치명타 4 개를 놓습니다. 그런 다음 가방에서 주문을 무작위로 분류하고 한 번에 하나씩 꺼내십시오. 백이 비면 동일한 값으로 다시 채우고 무작위로 만듭니다. 이렇게하면 5 번의 적중 당 평균 1 번의 치명타 및 최대 2 번의 치명타 및 8 회의 치명타가 연속으로 발생합니다. 더 많은 무작위성을 위해 가방에있는 품목 수를 늘리십시오.

다음은 구현 (Java로)과 얼마 전에 작성한 테스트 사례의 예 입니다.


21
+ 1 비판없이 좋은 아이디어입니다. 더 높은 수준의 무작위성을 위해 가방의 크기를 조정하고 플레이어 간 치명적인 차이를 처리합니다 (변수
ofc 인

16
가방 크기는 10입니다. 1 타격에 30 % 확률로 1 초를 넣으십시오. 중요한 기회가 바뀌면 가방을 버리고 새 가방을 시작할 수 있습니다. 그러한 체계는 귀하 (또는 상대방)가 치명타 확률과 가방의 크기를 알고있는 경우 특정 롤 수에 대해 다른 치명타를 얻지 못할 수도 있음을 알 수 있습니다. 이것은 전술에 영향을 줄 수 있습니다.
Steve Jessop

3
그래 ... 이런 식으로 카드 계산과 비슷한 릭을 실행합니다. 나는 보병 위험하거나 큰 죽이기 위해에 가십니까 ... 잠재적 인 결과의 작은 고정 세트는 손실의 위험을 감소시키고 "gamed"되는 기회를 증가시킬 수있다
마태 복음 회칠

8
나는 셔플 백 아이디어를 좋아하지만 치명타 확률이 20 % (10 명중에 아무도 할 수 없음)가 더 이상 확률이 아니기 때문에 이것이 게임 "정신"과 일치하지 않는다고 생각합니다. 5 타격마다 정확히 1 타격이됩니다. 또한 치명타 확률이 변경되면 가방을 다시 굴리면 게임에서 글리치가 발생합니다. 내 치명타가 완료되면, 나는 다음 비평가를 일찍 받기 위해 나 자신에게 주문을 던질 것이다 : p
Michaël Carpentier

2
@Jonathan : 가방을 큰 크기로 만들면 실제로 전체 가방 아이디어를 취소합니다. 허용 가능한 양의 던져 내에서 무언가가 발생하는지 확인하십시오. 백 50000을 크게 만드는 것은 난수 생성기를 사용하는 것과 거의 같습니다.
dstibbe

113

임의의 의미가 무엇인지 오해했습니다.

이 중 어느 것이 더 무작위입니까?

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

두 번째 줄거리는 더 고르게 분포 된 것처럼 보이지만 실제로는 첫 번째 줄거리가 더 무작위 입니다. 인간의 마음은 종종 무작위로 패턴을 보게되므로 첫 번째 줄거리의 덩어리를 패턴으로 볼 수는 있지만, 무작위로 선택된 표본의 일부는 아닙니다.


25
좋은 Numb3rs 설명!
RMAAlmeida

9
엄밀히 말하면 임의성을 측정 할 수 없습니다. 내 추측은 알고리즘 적으로 생성되었지만 두 배포판은 나에게 상당히 임의적으로 보입니다. 첫 번째 플롯에서 여러 테스트를 수행하고 균일 분포에 따라 포인트를 배치하는 프로세스에서 발생했을 가능성이 있지만 더 랜덤하다는 결론을 내릴 수는 없습니다. 반례로 선형 합동 발생기를 사용하여 첫 번째와 같은 플롯을 만든 다음 제너 다이오드의 증폭 된 노이즈를 사용하여 두 번째와 같은 플롯을 만들 수 있습니다. 무작위가 아닌 상관없는 단어를 사용해보십시오.
Dietrich Epp

8
해당 분포가 무작위 일 확률을 측정 할 수 있습니다.
ceejayoz


2
공정하게 말해서 OP는 올바른 용어를 사용하지 않을 수 있지만 난수 생성기는 사용자에게 더 "공평한" 느낌을 주기 때문에 두 번째 그래프와 같은 것을 원할 때 첫 번째 그래프와 비슷한 것을 제공한다는 것을 이해합니다 .
Kip

88

당신이 요구하는 행동을 감안할 때, 당신은 잘못된 변수를 무작위로 만들고 있다고 생각합니다.

적중이 치명적 인지 여부를 무작위 화하기보다는 다음 치명타가 발생할 때까지 회전 횟수를 무작위 화하십시오. 예를 들어, 플레이어가 크리티컬을 얻을 때마다 2와 9 사이의 숫자를 선택한 다음, 많은 라운드가 지나면 다음 크리티컬을 제공하십시오. 주사위 방법을 사용하여 정규 분포에 가까워 질 수도 있습니다. 예를 들어, 2D4 턴에서 다음 결정을 내릴 수 있습니다.

이 기술은 오버 월드에서도 무작위로 발생하는 RPG에서 사용된다고 생각합니다. 걸음 카운터를 무작위로 지정하면 여러 단계 후에 다시 적중됩니다. 한 번에 두 번의 만남에 거의 맞지 않기 때문에 훨씬 더 공평하게 느껴집니다. 한 번이라도 발생하면 플레이어는 짜증을냅니다.


나는 이것이 훌륭한 해결책이라고 생각하지만 약 80 %의 확률은 어떻습니까?
Thinker 2016 년

나는 때때로 다차원 랜덤 제너레이터를 사용하는 것을 좋아합니다. 발동 확률 + 발동 확률 + 치명타 확률. 그냥 D & D에서 여러 가지 다른 주사위를 압연 같은
마태 복음 회칠 한

나는이 아이디어가 마음에 들어, 당신은 매우 오랜 시간 동안 파이널 판타지에서 사용 된 스텝 카운터에 대해 완전히 정확합니다.
Ed James

이것의 한 가지 문제점은 치명타 확률이 적중 횟수가 거의 일정한 경우에만 작동한다는 것입니다. 배틀 중간에 플레이어가 치명타 확률을 두 배로 올리는 주문을 발동한다고 가정 해보십시오. 그렇다면 회전 수를 어떻게 조정합니까?
Alex319

+1 매우 좋고, 20 %보다 적은 라운드 투 히트 확률을 매우 쉽게 처리합니다.
앨리스 퍼셀

53

먼저 "적절한"분포를 정의하십시오. 임의의 숫자는 무작위입니다-당신이 보는 결과는 (의사) 임의성과 완전히 일치합니다.

이것을 확장하면서, 나는 당신이 원하는 것이 "공정함"느낌이라고 가정하므로, 사용자는 성공하지 않고 100 턴을 갈 수 없습니다. 그렇다면 마지막 성공 이후의 실패 횟수를 추적하고 생성 된 결과에 가중치를 부여합니다. 5 개의 롤 중 1 개를 "성공"한다고 가정 해 봅시다. 따라서 무작위로 1에서 5까지의 숫자를 생성하고 5이면 숫자가 좋습니다.

그렇지 않은 경우 실패를 기록하고 다음에 1에서 5까지의 숫자를 생성하지만 floor (numFailures / 2)를 추가하십시오. 이번에도 다시 5 분의 1의 기회가 있습니다. 그들이 실패하면, 다음 번 승리 간격은 4 5입니다; 5 분의 2의 성공 확률. 이러한 선택을 통해 8 번의 실패 후에 성공할 것입니다.


그 노트에서 ... 난수의 범위가 분포에 영향을 줄 것입니다 ... 예 : 랜덤 선택 r = new Random (); r.Next (1,5) vs. r.Next (1,1000000) % 200000
Eoin Campbell

23
OP에게 무작위로 오해한다고 말하지 않고 요청 뒤에 문제가 있음을 +1하십시오.
Boris Callens

4
이렇게하면 전체 성공 비율이 5 분의 1보다 큽니다. 예를 들어 1..100 범위에서 무작위로 20 개의 다른 숫자를 선택하고이를 미리 결정할 수 있습니다. 그들의 비판이됩니다. 하지만 더 많은 부기입니다.
Steve Jessop

"5에서 1보다 클 것"-장기적으로 예상됩니다.
Steve Jessop

시작 확률을 약간 줄이면 전체 비율이 1/5로 줄어 듭니다. 나는 당신이 그것을 얼마나 줄여야하는지 해결하지 못했지만 모든 것이 연속적이므로 정답이 있어야합니다.
Steve Jessop

35

mt_rand ()를 이런 식으로 바꾸는 것은 어떻습니까?

XKCD 만화 (RFC 1149.5는 표준 IEEE 검사 난수로 4를 지정합니다.)

(RFC 1149.5는 표준 IEEE 검증 난수로 4를 지정합니다.)

에서 XKCD .


좋은 방법이지만 OP의 난수 분포 문제를 해결할 수 있습니까? ;-)
Arjan Einbu

실제로는 아닙니다. 그는이 기능을 사용할 수있는 비 랜덤 RNG를 요청하고 있습니다. 그러나 그가 정말로 원하는 것은 현재 최고 답변 ( stackoverflow.com/questions/910215/910224#910224 )에 의해 더 잘 설명되어 있습니다
Colin Pickard

28
이것은 OP가
원했던

RFC1149에는 섹션 5가없고 (또는 1149.5가 없기 때문에) -1; 공정한 무작위성 +1
greyfade

34

이 기사가 도움이 되길 바랍니다. http://web.archive.org/web/20090103063439/http://www.gamedev.net:80/reference/design/features/randomness/

이 '무작위 숫자'생성 방법은 rpg / mmorpg 게임에서 일반적입니다.

그것이 해결하는 문제는 다음과 같습니다 (발췌).

칼날 거미가 목에 있습니다. 맞고 그리워합니다. 다시 맞고 다시 그리워. 그리고 당신이 떠날 것이 아무것도 없을 때까지 반복해서. 당신은 죽었고 시체를 찬양하는 2 톤의 거미류가 있습니다. 불가능한? 아니요. 불가능합니까? 예. 그러나 충분한 선수와 충분한 시간이 주어지면 불가능한 것이 거의 확실해집니다. 블레이드 스파이더가 단단하지는 않았으며, 운이 좋지 않았습니다. 얼마나 실망 스러운가. 플레이어가 종료하고 싶을 정도로 충분합니다.


1
나는 이것에 대한 변형을 들었습니다- "백만의 사건 중 하나가 세계 인구에서 6,000 번 발생합니다".
ceejayoz

19

당신이 원하는 것은 임의의 숫자가 아니라 인간에게 무작위로 보이는 숫자입니다. 다른 사람들은 Shuffle Bad와 같은 개별 알고리즘을 이미 제안했습니다.

이 영역에 대한 상세하고 광범위한 분석은 AI Game Programming Wisdom 2를 참조하십시오 . 이 책은 모든 게임 개발자가 읽을 가치가 있으며 "겉보기에 난수"라는 개념은 다음 장에서 다루어집니다.

AI 결정 및 게임 로직에 대한 필터링 된 무작위성 :

초록 : 기존의 지혜에 따르면 난수 생성기가 더 좋을수록 게임을 더 예측할 수 없게됩니다. 그러나 심리학 연구에 따르면 단기간 동안의 무작위 무작위성은 종종 인간에게 결정적으로 무작위로 보이지 않습니다. 이 기사에서는 무작위 AI 결정과 게임 로직을 플레이어에게 무작위로 보이게 만드는 동시에 강력한 통계적 무작위성을 유지하는 방법을 보여줍니다.

또 다른 장이 흥미로울 수도 있습니다.

난수 통계

초록 : 난수는 일반적으로 인공 지능과 게임에서 가장 많이 사용됩니다. 그들의 잠재력을 무시하는 것은 게임을 예측 가능하고 지루하게 만드는 것입니다. 잘못 사용하면 완전히 무시하는 것만 큼 나빠질 수 있습니다. 난수 생성 방법, 한계 및 기능을 이해하면 게임에서 난수를 사용하는 데 따르는 많은 어려움을 제거 할 수 있습니다. 이 기사는 난수, 세대 및 좋은 숫자를 나쁜 숫자와 구분하는 방법에 대한 통찰력을 제공합니다.


8

확실히 임의의 난수 생성으로 그러한 런을 생성 할 수 있습니까? 적절한 백분율을보기 위해 3-10 롤로 충분히 큰 샘플 세트를 얻지 못할 것입니다.

어쩌면 당신이 원하는 것은 자비 임계치입니다 ... 마지막 10 롤을 기억하고 치명타가 없었 으면 공짜로하십시오. 무작위의 새총과 화살을 부드럽게하십시오.


8

가장 좋은 해결책은 여러 가지 다른 임의 구성표 로 재생 테스트를 수행하고 플레이어를 가장 즐겁게하는 구성표를 선택하는 것입니다.

주어진 조우에서 같은 수의 백 오프 정책을 시도 할 수도 있습니다 (예 : 플레이어 1가 첫 턴에 롤을하는 경우). 다른 1것을 얻으려면 2 1s를 연속 으로 굴려야 합니다. 3 분의 1을 얻으려면 1연속 으로 3 이 필요합니다.


7

불행히도 당신이 요구하는 것은 사실상 임의의 숫자 생성기가 아닙니다. 왜냐하면 다음 숫자를 결정할 때 이전 결과를 고려하기 때문입니다. 이것은 난수 생성기가 작동하는 방식이 아닙니다.

5 개의 적중 중 1 개를 치명적으로하려면 1에서 5 사이의 숫자를 선택하고 해당 적중이 치명적이라고 말하십시오.


1
만약 당신이 어떤 경우에 엄격한 무작위로 생성 된 숫자를 사용한다면, 당신은 "한국어 무작위"결과를 얻게됩니다. 그 결과 플레이어가 화를 내고 좌절감을 느끼게하는 무작위 결과가
나옵니다 (

결과적으로 첫 번째 명중이 치명타라면 다음 4 명은 그렇지 않습니다. OP가 원하는 것처럼 들리지만, 이렇게 말하면 지체됩니다. 당신은 저의 UV를 얻습니다.
belgariontheking

-1 "무작위"와 "메모리가없는"을 혼동하는 것 같습니다 -en.wikipedia.org/wiki/Memorylessness
Alice Purcell

7

mt_rand ()는 Mersenne Twister 구현을 기반으로하므로 얻을 수있는 최상의 무작위 분포 중 하나를 생성합니다.

분명히 원하는 것은 무작위가 아니므로 원하는 것을 정확하게 지정해야합니다. 결과가 실제로 무작위이고 예측할 수 없어야하지만 동시에 언급 된 확률과 부분적으로 차이가 없어야한다는 사실을 이해하게 될 것입니다. 그러나 그 결과는 예측 가능해집니다. 한 번에 최대 10 개의 비 치명타를 설정 한 경우, 플레이어에게 "행에 9 개의 비 치명타를 가졌다면, 다음 치명타는 100 % 확실성으로 중요합니다"라고 말한 것입니다. 무작위로 전혀 신경 쓰지 않습니다.


6

적은 수의 테스트를 통해 다음과 같은 결과를 기대할 수 있습니다.

진정한 임의성은 거대 세트 크기에 대해서만 예측할 수 있으므로 동전을 뒤집고 처음으로 3 번 머리를 숙일 수는 있지만 수백만 번 넘기면 대략 50-50으로 끝납니다.


7
수백만 번 뒤집은 후에도 여전히 동전의 한 면만 보았을 것입니다. 이런 일이 발생하더라도, 당신은 아마도 무한한 불가능한 드라이브에 너무 가까이 앉아있을 것입니다 : P
Grant Peters

haha, 그렇습니다. 그러나 확률은 엄청나게 낮아서 수학 법칙에 따르면 짝수 분포를보아야한다고합니다.
Ed James

6

이전에 생성 된 숫자를 추적하거나 가능한 모든 값을 섞을 것을 제안하는 많은 답변이 있습니다.

개인적으로, 나는 연속으로 3 개의 치트가 나쁘다는 것에 동의하지 않습니다. 또한 연속으로 15 번의 비 치명타가 나쁘다는 데 동의합니다.

각 번호 다음에 치명타 확률 자체를 수정하여 문제를 해결할 것입니다. 예 (아이디어를 보여주기 위해) :

int base_chance = 20;
int current_chance = base_chance;

int hit = generate_random_number(0, 100) + 1; // anything from 1 to 100
if(hit < current_chance)//Or whatever method you use to check
{
    //crit!
    if(current_chance > base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 0.8; // decrease the crit chance for the NEXT hit.
}
else
{
    //no crit.
    if(current_chance < base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 1.1; // increase the crit chance for the NEXT hit.
    //raise the current_chance
}

치명타를받지 않을수록 다음 행동이 치명타 확률이 높아집니다. 포함 된 재설정은 전적으로 선택 사항이며 필요한지 여부를 테스트하기 위해 테스트가 필요합니다. 긴 비 치명적 행동 체인 이후에 한 행에서 하나 이상의 행동에 대한 치명타 확률을 높이는 것이 바람직하거나 바람직하지 않을 수 있습니다.

그냥 내 2 센트를 던지고


나는 이런 종류의 접근법을 좋아한다. 아마 다른 방법으로 할 것입니다. 더 낮은 확률로 시작하여 적중 할 때까지 최대 20 % 이상의 일부 추가 백분율로 빌드 한 후 다시 낮은 양으로 재설정하십시오.
Matthew

5

최고의 답변은 훌륭한 설명이므로, 결정적 이지 않은 "나쁜 줄무늬"의 확률을 제어 할 수있는 알고리즘에 중점을 두겠습니다 . 내가해야한다고 생각하는 것은 다음과 같습니다.

중요한 치명타 확률 인 Bernoulli 분포의 모수 인 p 를 지정하는 대신 , ab , 베타 분포의 모수 인 Bernoulli 분포의 "접합 된 사전"을 지정하십시오. 지금까지 치명타 및 비 치명타 횟수 인 AB를 추적해야합니다 .

이제 ab 를 지정 하려면 치명타 확률 인 a / (a ​​+ b) = p가되도록하십시오. 깔끔한 것은 (a + b)는 A / (A + B)가 p에 얼마나 가깝게되기를 원하는지를 정량화한다는 것입니다.

다음과 같이 샘플링을 수행하십시오.

p(x)베타 분포의 확률 밀도 함수를 보자 . 여러 곳에서 사용할 수 있지만 GSL에서 gsl_ran_beta_pdf로 찾을 수 있습니다.

S = A+B+1
p_1 = p((A+1)/S)
p_2 = p(A/S)

확률 p_1 / (p_1 + p_2)의 베르누이 분포에서 샘플링하여 치명타를 선택하십시오.

임의의 숫자에 "나쁜 줄무늬"가 너무 많으면 ab를 스케일 업 하지만 ab 가 무한대로 가면 한계점에서 앞서 설명한 셔플 백 접근 방식을 사용하게됩니다.

이것을 구현하면 어떻게되는지 알려주십시오!


5

반복 값을 방해하는 분포를 원한다면 간단한 반복 제거 알고리즘을 사용할 수 있습니다.

예 :

int GetRand(int nSize)
{
    return 1 + (::rand() % nSize);
}
int GetDice()
{
    static int nPrevious=-1;
    while (1) {
        int nValue = GetRand(6);
        // only allow repeat 5% of the time
        if (nValue==nPrevious && GetRand(100)<95)
            continue;
        nPrevious = nValue;
        return nValue;
    }
}

이 코드는 95 %의 반복 값을 거부하므로 반복은 불가능하지만 불가능하지는 않습니다. 통계적으로 그것은 추악하지만, 아마도 원하는 결과를 얻을 것입니다. 물론 "5 4 5 4 5"와 같은 배포를 막지는 못합니다. 당신은 더 멋진 시간을 가질 수 있고 마지막 두 번째 (예 : 60 %)와 세 번째 마지막 (예 : 30 %)을 거부 할 수 있습니다.

나는 이것을 좋은 게임 디자인으로 추천하지 않습니다. 원하는 것을 달성하는 방법을 제안하기 만하면됩니다.


치명타와 같은 내 게임의 일부 값은 50 % 이상의 확률을 가질 수 없으므로 반복을 완전히 차단하지만 일부 비율의 경우 이벤트 확률이 낮아집니다.
Thinker

4

실제로 원하는 것이 확실하지 않습니다. 처음 5 번 호출하면 임의 순서로 숫자 1-5를 반환하는 함수를 작성할 수 있습니다.

그러나 그것은 실제로 무작위가 아닙니다. 플레이어는 다음 5 번의 공격에서 정확히 5 점을 얻습니다. 그래도 원하는 것이 될 수 있으며,이 경우에는 직접 코딩해야합니다. (숫자를 포함하는 배열을 만든 다음 섞으십시오)

또는 현재 접근 방식을 계속 사용할 수 있으며 현재 결과가 잘못된 임의 생성기로 인한 것으로 가정합니다. 현재 번호에는 문제가 없을 수 있습니다. 임의의 값은 임의입니다. 때로는 같은 값의 2, 3 또는 8을 연속으로 얻습니다. 그들은 무작위이기 때문에. 좋은 임의 생성기는 평균적으로 모든 숫자가 똑같이 자주 반환되도록 보장합니다.

물론 잘못된 랜덤 생성기를 사용하는 경우 결과가 왜곡 될 수 있으므로 더 나은 랜덤 생성기로 전환하면 문제가 해결됩니다. (더 나은 발전기는 Boost.Random 라이브러리를 확인하십시오)

또는 임의 함수에 의해 반환 된 마지막 N 값을 기억하고 그 결과를 측정 할 수 있습니다. (간단한 예는 "새 결과가 나타날 때마다 값을 버리고 새 값을 가져와야 할 확률이 50 %입니다"입니다.

내가 추측해야한다면, "실제적인"무작위성을 고수하는 것이 최선의 방법이라고 말하고 싶습니다. 좋은 랜덤 제너레이터를 사용하고 있는지 확인한 다음 지금하는 방식대로 진행하십시오.


실제로, 그가 사용하고있는 기능은 부스트 ​​라이브러리에서 최고의 RNG와 같습니다.
Michael Borgwardt

MT는 "최고"가 아닙니다. 마지막으로 확인했습니다. 훌륭하고 간단하며 빠르지 만 최상의 배포를 제공하지는 않습니다. 어쨌든 백만 개의 난수를 잡고 분포를 확인하십시오. 랜덤 함수가 실제로 균일 한 분포를 제공하는지 확인하십시오. 그렇지 않다면 더 좋은 발전기를 찾으십시오. 만일 그렇다면, 그것을 빨아 들여서 가끔씩 치열한 행을 받아들이거나, 부정 행위를하고 결과를 무작위적이고 예측하기 쉽게 만드십시오 .
jalf

4

1에서 5까지의 숫자가 포함 된 목록을 만들어 임의 순서대로 정렬 할 수 있습니다. 그런 다음 작성한 목록을 살펴보십시오. 당신은 적어도 한 번은 모든 숫자를 실행할 수 있습니다 ... 처음 5를 끝낼 때, 다른 5 개의 숫자를 만드십시오 ...


4

블리자드와 같은 점진적 백분율 시스템을 사용하는 것이 좋습니다. http://www.shacknews.com/onearticle.x/57886

일반적으로 RNG를 굴린 다음 값과 비교하여 성공 여부를 결정합니다. 다음과 같이 보일 수 있습니다.

if ( randNumber <= .2 ) {
   //Critical
} else {
   //Normal
}

기본 기회를 점진적으로 늘리기 만하면됩니다 ...

if (randNumber <= .2 + progressiveChance ) {
   progressiveChance = 0;
   //Critical
} else {
   progressiveChance += CHANCE_MODIFIER;
   //Normal hit
}

더 화려 해야하는 경우 더 쉽게 추가 할 수 있습니다. ProgressChance가 100 % 치명타 확률을 피하거나 특정 이벤트에서 재설정 할 수있는 양을 제한 할 수 있습니다. 또한 progressChance + = (1-progressChance) * SCALE (SCALE <1)과 같은 방법으로 각 부스트를 조금씩 증가시킬 수도 있습니다.


4

글쎄, 당신이 수학에 조금 있다면, 시도해 볼 수 있습니다. 지수 분포를

예를 들어, lambda = 0.5 인 경우 예상 값은 2 (이 기사를 읽으십시오!)이며, 매 2 번째 턴마다 (50 %, huh?) 그러나 그러한 확률 분포를 사용하면 0 턴 (이벤트가 이미 발생하고 turn_counter가 재설정 된 것)에서 40 %의 확률로 다음 턴을 칠 확률이 약 65 %입니다. 두 번째 (다음에 다음에) 돌릴 확률은 약 80 %로 세 번째를칩니다.

이 분포의 목적은 적중률이 50 %이고 연속으로 3 번 그리워하는 경우 순조롭게 (잘, 80 % 이상의 확률로, 다음 턴마다 증가) 적중합니다. 이로 인해 더 많은 "공정한"결과가 나타나고 50 % 이상의 확률이 유지됩니다.

치명타 확률이 20 %입니다.

  • 1 차례 치명타 17 %
  • 이전 턴에서 치명타가 발생하지 않는 경우 32 턴으로 2 턴 치명타
  • 이전의 모든 치명타에서 치명타가 발생하지 않는 경우 45 %로 3 회전 치명타
  • 이전 턴에서 치명타가 발생하지 않으면 54 %로 4 턴
  • ...
  • 모든 이전 치명타에서 치명타가 발생하지 않는 경우 80 %-8 턴 치명타

여전히 5 번의 턴에서 3 개의 치명타 + 2 개의 비 치명타 확률은 약 0.2 % (5 % 대)입니다. 그리고 4 개의 결과 비 치명타 확률은 14 %이며, 5 개의 5 %, 6은 1.5 %, 8은 비치 명 8에 대해 0.3 %, 7, 0.07 %입니다. 나는 41 %, 32 %, 26 %, 21 %, 16 %보다 "더 공정한"베팅을했다.

아직도 지루하지 않기를 바랍니다.


이것은 마지막 치명타 이후의 시간 만 "기억"한다는 점을 제외하고는 내 솔루션과 매우 유사합니다. 이 솔루션 하에서, 4 번의 치명타는 한 번의 치명타로 끝나는 것과 미래의 확률에 관한 것입니다. 따라서 치명타가 양호하면이 솔루션은 단점을 제한하지만 단점은 제한하지 않습니다. 내 솔루션은 둘 다에 영향을 미칩니다.
Neil G

다른 솔루션에는 자체 이점이 있다는 것이 분명합니다. 이것은 과학적 관점에서 무작위성을 깨끗하게 유지하는 데 중점을 둡니다. 그것은 가방이나 다른 것을 섞는 것보다 어떻게 든 더 나은 것을 의미하지는 않습니다. 시도해 볼만한 솔루션 일뿐입니다.
Dark

3

결정적인 기회는 마지막 N 개의 공격에 따라 달라집니다. 간단한 체계 중 하나는 일종의 마르코프 체인입니다 : http://en.wikipedia.org/wiki/Markov_chain 그러나 코드는 매우 간단합니다.


IF turns_since_last_critical < M THEN 
   critial = false
   turns_since_last_critical++;
ELSE
   critial = IsCritical(chance);
   IF Critial THEN
       turns_since_last_critica = 0;
   ELSE
       turns_since_last_critica++;
   END IF;
END IF;

물론 비판의 기회는 비판의 확률이 마지막 비판 이후 충분한 회전을했다는 것을 알게되면 비판의 확률보다 낮기 때문에 수학을 만들어야합니다.


마지막 공격 만 고려하면 대부분의 효과를 얻을 수 있습니다. P는 관측 된 적중률, R은 적중 후 적중률, R / 2는 적중 후 적중률로 지정하십시오. 정의상, 어느 시점에서나 P = P * R + (1-P) * (R / 2)를 칠 기회가 있습니다. 이 수단 P = R / (R-2)
MSalters

2

OP,

공평하게 만들고 싶다면 무작위가 아닙니다.

게임의 문제는 실제 경기 길이입니다. 일치하는 시간이 길수록 무작위성이 적어지고 (치명적인 경향은 20 %가 됨) 의도 한 값에 근접하게됩니다.

이전 롤을 기준으로 공격을 미리 계산하는 두 가지 옵션이 있습니다. 5 공격마다 치명타 1 점을 얻습니다 (20 % 기준). 무작위로 발동 할 수 있습니다.

listOfFollowingAttacks = {적중, 적중, 적중, 미스, 치명};

그것이 당신이 원하는 패턴입니다. 따라서 목록에서 임의로 선택하여 비어있을 때까지 다시 만듭니다.

그것은 내 게임을 위해 만든 패턴이며, 내가 원하는 것을 위해 아주 잘 작동합니다.

두 번째 옵션은 치명타 확률을 높이는 것입니다. 모든 공격이 끝날 때마다 더 많은 수를 보게 될 것입니다 (일치하는 것이 빨리 끝나는 것으로 가정). % 확률이 적을수록 더 많은 RNG를 얻습니다.


2

정규 분포를 원할 때 선형 분포를보고 있습니다.

청소년 시절 D & D를하는 것을 기억한다면 여러 개의 n면 다이를 굴려서 결과를 합한 것입니다.

예를 들어, 4 x 6면 주사위를 굴리는 것은 1 x 24면 주사위를 굴리는 것과 다릅니다.


2

City of Heroes에는 실제로이 문제를 정확하게 해결하는 "스트 레이크 브레이커"라는 정비공이 있습니다. 작동 방식은 문자열에서 최저 적중 확률과 관련된 길이의 일련의 미스가 발생한 후 다음 공격이 적중하는 것입니다. 예를 들어, 기회를 맞추기 위해 90 %가 넘는 공격을 놓치면 다음 공격이 자동으로 적중하지만 적중 확률이 60 %보다 낮 으면 "연속 공격자"(I 정확한 숫자를 모른다)



0

값을 가중하는 것은 어떻습니까?

예를 들어 치명타 확률이 20 % 인 경우 치명타를 나타내는 하나의 숫자로 1과 5 사이의 숫자를 생성하거나 치명타로 20과 함께 1과 100 사이의 숫자를 생성하십시오.

그러나 난수 또는 의사 난수로 작업하는 한 현재보고있는 결과를 피할 수있는 방법이 없습니다. 그것은 무작위의 본질입니다.


그리고 왜 그것이 차이를 만들까요? 두 숫자 집합 모두에 대해 중요하게 될 확률은 동일합니다.
samjudson

바로 그거죠. 나는 그의 20 % 예를 들어 그를 위해 두 가지 옵션을 제시하고 있습니다. 정수를 다루는 경우 100이 더 효과적 일 수 있지만, 그렇게 생각하고 싶다면 하나의 "다이"만 시뮬레이션하면됩니다.
Thomas Owens

당신이 제시하는 옵션은 그가 이미하고있는 것입니다.
ceejayoz

2
그가 원하는 것에 대한 것이 아닙니다. 그는 그것이 임의의 숫자 생성기라고 불리는 경우에도 난수가 아닌 숫자 생성기를 원합니다.
ceejayoz

0

에 대한 반응 : "문제는 실생활 결과가 매우 나쁘다는 것입니다. 때때로 플레이어는 5 타격으로 3 개의 치명타를가집니다.

당신은 15 명중에서 아무것도 얻지 못할 확률이 3 ~ 4 % 사이입니다 ...


분당 3500 명의 플레이어가 온라인으로 10000 번의 전투를 벌이는 경우, 전투의 3 %에서 발생하는 문제는 매우 일반적인 문제입니다.
Thinker

다시 한번, 3 %의 전투에서 발생하는 불운은 여전히 ​​불운입니다.
MSalters

0

나는 다음과 같은 "임의로 지연된 퍼백 다이"를 제안 할 것이다.

  • 두 개의 배열을 유지하십시오. 하나는 in-array초기에 0에서 n-1 사이의 값으로 채워지고 다른 하나는 ()out-array 비워집니다.
  • 결과가 요청 될 때 :
    • 모두에서 임의의 값을 반환 정의in-array
    • 이 값을 in-array에서out-array
    • 하나의 무작위 ( 정의되지 않은!를 포함한 모든 요소) 요소를 out-array뒤로 이동in-array

이것은 더 큰 n 이 더 느리게 "반응"할 것이라는 특성을 갖는다 . 예를 들어, 20 % 확률을 원한다면 n 을 5로 설정 하고 0을 때리는 것은 n 을 10으로 설정 하고 0 또는 1을 때리는 것보다 "임의의 랜덤"이 아니며 1000에서 0에서 199로 만드는 것은 거의 작은 샘플에 대한 진정한 무작위성과 구별 할 수 없습니다. 샘플 크기 에 맞게 n 을 조정 해야합니다.


0

플레이어에 대한 무작위 치명타를 미리 계산하십시오 .

// OBJECT
//...
// OnAttack()
//...
c_h = c_h -1;
if ( c_h == 0 ) {
 // Yes, critical hit!
 c_h = random(5) + 1 // for the next time
 // ...
}

0

아마 당신이 잘못된 무작위 분포 함수를 사용하고 있다고 생각합니다. 당신은 아마도 숫자에 고른 분포를 원하지 않을 것입니다. 치명타가 '정기적'조회수보다 더 드물어 지도록 정규 분포를 대신 사용하십시오.

Java로 작업하므로 정규 분포로 임의의 숫자를 제공하는 C ++에서 찾을 수있는 곳이 확실하지 않지만 거기에 무언가가 있어야합니다.

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