2011-11-04 39 views
5

Tôi có một hàm đệ quy, và bên trong hàm một phần tử ngẫu nhiên từ một mảng được chọn, nhưng không có vấn đề gì tôi làm tiếp tục nhận được cùng một hạt giống.Chức năng đệ quy hạt giống ngẫu nhiên. Tôi phải làm nó như thế nào?

static Random rand = new Random(); 
public String spintaxParser(String s) 
    { 
     if (s.Contains('{')) 
     { 
      int closingBracePosition = s.IndexOf('}'); 
      int openingBracePosition = closingBracePosition; 

      while (!s[openingBracePosition].Equals('{')) 
       openingBracePosition--; 

      String spintaxBlock = s.Substring(openingBracePosition, closingBracePosition - openingBracePosition + 1); 

      String[] items = spintaxBlock.Substring(1, spintaxBlock.Length - 2).Split('|'); 


      s = s.Replace(spintaxBlock, items[rand.Next(items.Length)]); 

      return spintaxParser(s); 
     } 
     else 
     { 
      return s; 
     } 
    } 

Cách tốt nhất để xử lý Ngẫu nhiên trong chức năng đệ quy là gì?

+2

Bạn có một số mã không? –

+0

Bạn đã thử tìm kiếm câu trả lời cho điều này chưa? Có rất nhiều câu hỏi về chủ đề sử dụng Random - ví dụ: http://stackoverflow.com/questions/4855756/random-number-generation-same-number-returned (tự đề cập đến các câu hỏi liên quan khác). – AAT

+0

Chúng tôi sẽ cần một số mã nguồn để thực sự có thể trợ giúp. –

Trả lời

3

Khai báo một cá thể (tĩnh) đơn lẻ của đối tượng Random nằm ngoài phạm vi hàm đệ quy của bạn, sau đó gọi cá thể từ bên trong hàm đệ quy của bạn.

Hàm khởi tạo mặc định là Random sẽ tự động thêm dấu thời gian hiện tại, vì vậy bạn sẽ nhận được cùng một giá trị nhiều lần vì bạn liên tục tạo một đối tượng mới của đối tượng Random.

Chỉnh sửa: Ngoài ra, bạn có thể thử điều này, mặc dù nó chắc chắn không lý tưởng. Tôi thích một cá thể Random đơn lẻ hoặc một hạt giống tĩnh hơn phương pháp này.

Random r = new Random(Guid.NewGuid().GetHashCode()); 
+0

có thể tạo một thể hiện mới của lớp Ngẫu nhiên bên trong hàm đệ quy và chuyển vào dấu thời gian không? –

+0

@SianJakeyEllis bạn có thể tạo một hạt giống toàn cầu (tĩnh) và tái sử dụng nó trong hàm tạo khi tạo các đối tượng ngẫu nhiên của bạn. Tuy nhiên, đó có thể là một chút ít hơn so với hiệu quả lý tưởng khôn ngoan. –

2

Sẽ hữu ích nếu bạn đăng mã. Nhưng trong sự vắng mặt đó, tôi sẽ sử dụng sức mạnh tâm linh của tôi và đoán rằng bạn đang sử dụng một mô hình như thế này

void MyRecursiveFunction() { 
    var index=new Random().Next(...); 
    ... 
} 

Nếu đúng, việc sửa chữa là thay đổi mã của bạn để nó không "ngẫu nhiên mới()" chỉ một lần và vượt qua nó (hoặc lưu trữ nó trong một số biến cá thể thích hợp) thay vì xây dựng một cái mới mỗi lần.

1

Chuyển Random làm tham số cho hàm đệ quy và sử dụng phiên bản được truyền để nhận giá trị tiếp theo từ nó mỗi lần.

public void Recurse(object param, Random rand) 
{ 

    ... 
    var val = rand.Next(); 
    //use the value ... 
    Recurse(obj, rand); 
} 

Recurse(arg, new Random()); 

Rõ ràng, đệ quy sẽ bị loại bỏ theo một cách nào đó nhưng điều này thể hiện nguyên tắc.

0

Tôi khuyên bạn nên đưa đối tượng ngẫu nhiên vào chính hàm đệ quy. Thử nghiệm này nên chứng minh rằng bạn sẽ không luôn có được cùng một int.

[Test] 
    public void TestSpintaxRandom() 
    { 
     spintaxParser("{|||{|||{|||{|||{|||{|||{|||{|||}}}}}}}}", new Random()); 
    } 

    public String spintaxParser(String s, Random r) 
    { 
     if (s.Contains('{')) 
     { 
      var closingBracePosition = s.IndexOf('}'); 
      var openingBracePosition = closingBracePosition; 

      while (!s[openingBracePosition].Equals('{')) 
       openingBracePosition--; 

      var spintaxBlock = s.Substring(openingBracePosition, closingBracePosition - openingBracePosition + 1); 
      var items = spintaxBlock.Substring(1, spintaxBlock.Length - 2).Split('|'); 

      var next = r.Next(items.Length); 
      Console.WriteLine(next); 
      s = s.Replace(spintaxBlock, items[next]); 

      return spintaxParser(s, r); 
     } 

     return s; 
    } 
Các vấn đề liên quan