اگر تا حالا با سیشارپ کار کرده باشید، احتمالاً سراغ تولید عدد تصادفی رفتهاید. برای مثال ممکن است بخواهید یک عدد بین 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 در سیشارپ
همچنین اگر قصد دارید مهارت خود را در زبان سی شارپ ارتقا دهید، دوره آموزش سی شارپ سطح متوسط میتواند انتخاب بسیار مناسبی برای شما باشد.
برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربریتان شوید