2011-08-31 4 views
5

내가 C#을 임의의 클래스는 "진정한 무작위로"숫자를하지 않는 것을 알고있다 "랜덤"되는 것이 아니라,이 코드에 문제가 함께 간다 :C# 임의의 숫자는

public void autoAttack(enemy theEnemy) 
    { 
     //Gets the random number 
     float damage = randomNumber((int)(strength * 1.5), (int)(strength * 2.5)); 

     //Reduces the damage by the enemy's armor 
     damage *= (100/(100 + theEnemy.armor)); 

     //Tells the user how much damage they did 
     Console.WriteLine("You attack the enemy for {0} damage", (int)damage); 

     //Deals the actual damage 
     theEnemy.health -= (int)damage; 

     //Tells the user how much health the enemy has left 
     Console.WriteLine("The enemy has {0} health left", theEnemy.health); 
    } 

I 여기에 함수를 호출 (숫자가 무작위로한다면 나는 확인을 위해 그것을 5 번 호출) :

 if (thePlayer.input == "fight") 
     { 
      Console.WriteLine("you want to fight"); 
      thePlayer.autoAttack(enemy1); 
      thePlayer.autoAttack(enemy1); 
      thePlayer.autoAttack(enemy1); 
     } 

을하지만, 내가 출력을 확인할 때, 나는 각 3 함수 호출에 대한 동일한 번호를. 그러나, 나는이 프로그램을 실행할 때마다, 나는 이런 식으로 (3 번 반복하는) 다른 번호를 :

You attack the enemy for 30 damage. 
The enemy has 70 health left. 

You attack the enemy for 30 damage. 
The enemy has 40 health left. 

You attack the enemy for 30 damage. 
The enemy has 10 health left. 

내가 다음// 디버그를 다시 프로그램을 다시 실행하고 다른 번호를 대신 30합니다 하지만 3 번 모두 반복됩니다.

제 질문은 :이 함수를 호출 할 때마다 다른 난수를 얻으려면 어떻게해야합니까? 나는 지금 막 "동일한"수를 계속해서 또 다시 얻고있다.

private int randomNumber(int min, int max) 
    { 
     Random random = new Random(); 
     return random.Next(min, max); 
    } 
+4

'randomNumber' 함수는 어떻게 생겼습니까? – Nija

+0

[이 게시물] (http://www.codeducky.org/random-numbers-c-net-primer/)에서이 문제와 .NET Random 클래스의 다른 문제를 설명 할 수 있습니다. – ChaseMedallion

답변

26

내 생각은 randomNumber 차례로 기반으로 새로운 의사 난수 생성기를 만들어 Random마다의 새로운 인스턴스를 ... 만들고 있다는 것입니다 : 여기

은 내가 사용하는 임의의 클래스의 호출입니다 현재 시간은 ... 당신이 생각하는 것처럼 자주 변하지 않습니다.

하지 마십시오. Random의 동일한 인스턴스를 반복적으로 사용하십시오. 그러나 을 입력하지 마십시오.은 고정 Random 변수를 만들어 수정합니다. Random은 스레드로부터 안전하지 않으므로 장기간에는 잘 작동하지 않습니다. 테스트에서 모두 멋지게 보일 것입니다. 그러면 동시성으로 인해 불행하게 될 때 신비하게 모든 0을 얻게 될 것입니다 : (

다행히도 스레드 로컬을 사용하여 작업하는 것은 그리 어렵지 않습니다. .NET 4. 당신은 스레드 당 Random의 새로운 인스턴스로 끝날

나는이 코드를 포함하여 유용하게 사용할 수있는 article on this very topic를 작성했습니다. 당신이 당신의 new Random() 전화를 변경하는 경우

using System; 
using System.Threading; 

public static class RandomProvider 
{  
    private static int seed = Environment.TickCount; 

    private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random> 
     (() => new Random(Interlocked.Increment(ref seed))); 

    public static Random GetThreadRandom() 
    { 
     return randomWrapper.Value; 
    } 
} 

RandomProvider.GetThreadRandom()으로하면 아마 모든 일을 처리 할 것입니다. ed (다시, .NET 4로 가정). 이는 테스트 가능성을 다루지는 않지만 한 번에 한 걸음 ...

+0

질문 에서처럼 최소값과 최대 값을 사용하려면 어떻게 수정해야합니까? – Julien

0

randomNumber은 무엇입니까?

일반적으로 의사 난수 생성기가 시드됩니다 (시간 관련 것 또는 두 개의 키 누르기 또는 네트워크 패킷 사이의 시간과 같이 무작위로 생성됨).

사용중인 생성기와 시드 방식을 나타내지는 않습니다.

+0

예를 들어 원래 게시물 – Mento

7

randomNumber의 코드를 표시하지 않았습니다. 모양이 비슷하다면

private int randomNumber(int m, int n) { 
    Random rg = new Random(); 
    int y = rg.Next(); 
    int z = // some calculations using m and n 
    return z; 
} 

음, 문제가 있습니다.Random의 새 인스턴스를 계속 생성하는 경우 가끔은 동일한 시드 (기본 시드는 정밀도가 제한적인 시스템 시계입니다. 충분히 빠르게 만들고 동일한 시드를 얻음)가 생성 될 수 있습니다. 발전기는 항상 동일합니다. 이 작업을 수행 할 경우에도 Random의 출력은 여전히 ​​"true"를 무작위로하지 않습니다,

private readonly Random rg = new Random(); 
private int randomNumber(int m, int n) { 
    int y = this.rg.Next(); 
    int z = // some calculations using m and n 
    return z; 
} 

을 그리고 다른 점을 정리하기 :

은 한 번 Random의 인스턴스를 인스턴스화해야이 문제를 해결합니다. 그것은 단지 쑤저 랜덤입니다.

+1

+1에 사용한 난수 클래스를 추가했습니다. 그러나 매우 짧은 연속으로 호출 될 경우 * 거의 항상 동일한 값을 산출 할 가능성이 높습니다. ;-) "기본 시드 값은 시스템 클럭에서 파생되고 유한 해상도입니다." –

+0

@pst, 아니, 그게 똑같은 가치를 산출하지는 않아. 'seed' (초기 값)는 시계에 달려 있지만 사용하면 내부 상태가 바뀝니다. –

+0

@ J-16 SDiZ : pst가 의미하는 바는 만약 여러분이'Random'의 새로운 인스턴스를 인스턴스화하고 하나의 무작위 값을 리턴하는 메소드를 가지고 있고 그 메소드를 루프 안에서 연속적으로 호출한다면, 값이 변경되지 않으면 시드 값이 몇 번 반복되고 시드 값이 시계 변경에서 변경되면 다른 값이 몇 번 반복됩니다. – jason

0

루프에서 임의의 숫자를 생성하면 무작위로 생성되지 않습니다. 왜냐하면 난수는 기본적으로 현재 시스템 시간에 내부적으로 생성되기 때문입니다. 그래서 루프에 코드를 삽입 :

Thread.Sleep(10); 

그래서 시스템은 10m 초 동안 절전 모드로 전환됩니다. 그리고 새로운 새로운 난수를 얻을 수 있습니다. 보장 된 솔루션입니다. 그러나 이것은 또한 시스템의 성능에 영향을 미칩니다.

+0

혼란 스러울 때 수면을 사용하는 것은 2 ~ 3 회의 반복 된 값을 계속 지키고 당황 스러울 때 나의 조잡한 해결 방법이었습니다. BTW, 나는 여전히 (100)에서 반복을 받고 있었다. (500)에서 그것은 무작위로 보였다. 하지만 그래, 성능은 끔찍해. @ 제이슨의 대답은 위의 좋은 수정입니다. – nanonerd

0

메서드 외부에서 임의의 개체를 인스턴스화합니다. (랜덤 랜덤 = 새 랜덤(); 메서드 앞에 쓰여 져야 함)

랜덤이 really random이 아니라는 사실을 이해하는 것이 중요합니다.

관련 문제