تولید اعداد تصادفی غیرتکراری در سی‌شارپ

 تولید اعداد تصادفی غیرتکراری در سی‌شارپ
فهرست مقاله [نمایش]

    اگر تا حالا با سی‌شارپ کار کرده باشید، احتمالاً سراغ تولید عدد تصادفی رفته‌اید. برای مثال ممکن است بخواهید یک عدد بین 1 تا 100 تولید کنید که به‌صورت تصادفی باشد. اما یک مشکل مهم در این میان وجود دارد: ممکنه عدد تکراری تولید بشه!

    تعریف عدد تصادفی

    عدد تصادفی یعنی عددی که غیرقابل پیش‌بینی باشه و هر بار خروجی متفاوتی داشته باشه. مثلاً وقتی میگی از 1 تا 10 یه عدد بده، ممکنه دفعه اول 7 باشه، دفعه بعد 3 و ...

    مشکل تکراری بودن در Random

    کلاس Random که توی سی‌شارپ هست، فقط عدد تصادفی می‌سازه؛ اما حواسش نیست که قبلاً اون عدد ساخته شده یا نه. یعنی ممکنه پشت‌سرهم عدد 5 بسازه و دوبار تکراری بده.

    چرا تولید عدد غیرتکراری مهم است؟

    چند تا مثال ساده:

    تولید کارت‌های بازی (مثل دک‌کارت)

    قرعه‌کشی بین افراد

    ساخت آزمون با سوالات تصادفی بدون تکرار

    ساخت آی‌دی‌های یونیک برای داده‌ها

    همه اینا نیاز دارن عدد یا داده تصادفی باشه ولی تکراری نباشه.

     

    2. آشنایی با کلاس Random و محدودیت آن

    کلاس Random ساده‌ترین روش برای تولید عدد شانسیه.

    مثال ساده از تولید عدد تصادفی

    var rnd = new Random();
    int num = rnd.Next(1, 101);
    Console.WriteLine(num);

    این کد یه عدد بین 1 تا 100 می‌ده. اما...

    کلاس Random تکراری بودن را کنترل نمی‌کند

    اگه چند بار پشت‌سرهم صدا بزنی:

    var rnd = new Random();
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine(rnd.Next(1, 6));
    }

    ممکنه خروجی بشه:

    3
    5
    3
    1
    5
    

    یعنی 3 و 5 دو بار تکرار شدن. خودش مراقب نیست تکرار نشه.

     

    3. روش اول: استفاده از HashSet برای جلوگیری از تکرار

    HashSet یه ساختار داده است که اجازه ورود مقدار تکراری نمی‌ده.

    کاری که می‌کنیم اینه: هر عددی که Random می‌سازه، می‌ریزیم داخل HashSet. اگه قبلاً اون عدد وجود داشته باشه، دوباره نمی‌ره توش.

    مثال کاربردی

    using System.Collections.Generic;
    HashSet<int> numbers = new HashSet<int>();
    Random rnd = new Random();
    while (numbers.Count < 10) // تعداد اعداد موردنیاز
    {
        int num = rnd.Next(1, 101); // بازه 1 تا 100
        numbers.Add(num);
    }
    foreach (var n in numbers)
        Console.WriteLine(n);
    

    مزایا و معایب

    مزایا:

    ساده و سریع برای تعداد کم

    جلوگیری قطعی از تکرار

    معایب:

    اگه تعداد درخواستی نزدیک به اندازه بازه باشه، کند می‌شه

    ممکنه Random بارها تکراری بزنه و قبول نشه

     

    4. روش دوم: تولید لیست و انجام Shuffle (الگوریتم Fisher–Yates)

    این روش برای وقتی خوبه که همه عددهای یه بازه رو می‌خوای بدون تکرار.

    توضیح مفهوم

    کل اعداد رو توی یه لیست می‌ریزیم، بعد ترتیبشونو شانسی می‌کنیم (Shuffle).

    کد عملی

    using System;
    using System.Linq;
    using System.Collections.Generic;
    List<int> numbers = Enumerable.Range(1, 100).ToList();
    Random rnd = new Random();
    for (int i = numbers.Count - 1; i > 0; i--)
    {
        int j = rnd.Next(i + 1);
        (numbers[i], numbers[j]) = (numbers[j], numbers[i]);
    }
    // نمایش 10 عدد اول
    foreach (var n in numbers.Take(10))
        Console.WriteLine(n);
    

    موارد استفاده

    شافل کارت بازی

    ساخت لیست ترتیب سوالات امتحان

    قرعه‌کشی بین همه افراد

     

    5. روش سوم: تابع کمکی سفارشی برای استفاده راحت‌تر

    می‌تونیم یه متد بسازیم که خودش اینا رو انجام بده.

    ساخت متد اختصاصی

    
    List<int> GetUniqueRandomNumbers(int min, int max, int count)
    {
        List<int> numbers = Enumerable.Range(min, max - min + 1).ToList();
        Random rnd = new Random();
        for (int i = numbers.Count - 1; i > 0; i--)
        {
            int j = rnd.Next(i + 1);
            (numbers[i], numbers[j]) = (numbers[j], numbers[i]);
        }
        return numbers.Take(count).ToList();
    }
    var result = GetUniqueRandomNumbers(1, 50, 7);
    result.ForEach(Console.WriteLine);
    

    کاربرد در پروژه‌ها

    قابل استفاده تو کلاس‌های مختلف

    راحت و قابل تست

    بدون نگرانی از تکرار

     

    6. روش‌های پیشرفته‌تر 

    اگه بخوای امنیت بالاتری داشته باشی، می‌تونی از RandomNumberGenerator استفاده کنی.

    مثال ساده

    top-level:
    using System.Security.Cryptography;
    using System.Collections.Generic;
    HashSet<int> uniqueNumbers = new HashSet<int>();
    while (uniqueNumbers.Count < 10)
    {
        byte[] bytes = RandomNumberGenerator.GetBytes(4);
        int value = BitConverter.ToInt32(bytes, 0);
        int finalNum = Math.Abs(value % 100) + 1;
        uniqueNumbers.Add(finalNum);
    }
    foreach (var n in uniqueNumbers)
        Console.WriteLine(n);
    

    تفاوت با Random

    امن‌تر

    برای کارهای عمومی لازم نیست

    کمی پیچیده‌تره

     

    7. مقایسه روش‌ها

    روشسرعتدقتکاربردتوضیح
    HashSetخوبمتوسطتعداد کمساده و سریع
    Shuffleعالیعالیتعداد زیادبدون تکرار واقعی
    متد کمکیعالیعالیپروژه‌ایقابل استفاده مجدد
    RNG امنمتوسطخیلی بالاامنیتیبرای رمزنگاری

     

    8. نتیجه‌گیری

    در نهایت، اینکه از کدوم روش استفاده کنی بستگی به نیازت داره:

    اگه تعداد محدودی عدد می‌خوای → HashSet

    اگه کل بازه رو می‌خوای بدون تکرار → Shuffle

    اگه می‌خوای کدت تمیز و قابل استفاده مجدد باشه → تابع کمکی

    اگه امنیت خیلی مهمه → RandomNumberGenerator

    پیشنهاد نهایی: همیشه اول ببین هدفت چیه، بعد یکی از این روش‌ها رو انتخاب کن تا هم عددات تصادفی باشن و هم تکراری نشه!

    اگر می‌خواهید در کار با تولید اعداد تصادفی حرفه‌ای‌تر شوید، پیشنهاد می‌کنم این مطلب را از دست ندهید: ۴ نکته کاربردی برای کار با Random در سی‌شارپ 

    همچنین اگر قصد دارید مهارت خود را در زبان سی‌ شارپ ارتقا دهید، دوره آموزش سی شارپ سطح متوسط می‌تواند انتخاب بسیار مناسبی برای شما باشد.

    اطلاعات نویسنده
    • نویسنده: تیم تحریریه باگتو

    ارسال دیدگاه

    برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربری‌تان شوید


    دیدگاه کاربران

    آموزش پیشنهادی باگتو


    course image

    آموزش سی شارپ - سطح متوسط

    1,490,000 تومان


    اطلاعات بیشتر

    course image

    ستارگان سی شارپ

    9,900,000 تومان


    اطلاعات بیشتر

    }