توليد الأرقام العشوائية في Android باستخدام Kotlin: ما تحت الغطاء؟

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيف تجعل Android "يلقي النرد"؟ نحلل توليد الأرقام العشوائية بلغة Kotlin

\n\n

هل تساءلت يومًا كيف "يختار" هاتفك رقمًا عشوائيًا؟ تبدو مهمة بسيطة - الحصول على عدد صحيح عشوائي من 5 إلى 10. ولكن تحت غطاء Android و Kotlin تختبئ آلية كاملة تعتمد عليها ليس فقط سهولة الاستخدام، بل وأمان تطبيقك. ليس من المستغرب أن سؤال "How can I generate random number in specific range in Android?" قد جمع آلاف المشاهدات على Stack Overflow. لن نقدم إجابة جاهزة فحسب - بل سننظر في المصادر ونتعرف على ما يحدث بالفعل.

\n\n

في هذه المقالة ستتعلم:

\n
    \n
  • كيفية توليد رقم عشوائي بشكل صحيح في نطاق معين بلغة Kotlin.
  • \n
  • الفرق بين kotlin.random.Random و java.util.Random و SecureRandom.
  • \n
  • لماذا تحتاج ألعاب الحظ إلى فئة واحدة، بينما تحتاج توليد كلمات المرور إلى فئة أخرى.
  • \n
  • كيف تتجنب الأخطاء النمطية التي تحول "العشوائية" إلى قابلية للتنبؤ.
  • \n
\n\n

هيا بنا!

\n\n

كلاسيكيات النوع: Random في Kotlin (ولماذا هذا ليس صحيحًا دائمًا)

\n\n

الطريقة الأكثر وضوحًا هي استخدام kotlin.random.Random. إنه مدمج مباشرة في اللغة ويعمل فورًا. إليك كيفية توليد رقم عشوائي من 0 إلى 100 (شامل):

\n\n
import kotlin.random.Random\n\nfun main() {\n    val randomNumber = Random.nextInt(0, 101) // من 0 إلى 100 شامل\n    println("الرقم العشوائي: $randomNumber")\n}
\n\n

كل شيء بسيط. لكن دعنا ننظر تحت الغطاء. Random.nextInt(from, until) داخليًا يستخدم java.util.Random (على منصة JVM). وهذا بدوره يولد الأرقام باستخدام مولد خطي متطابق (LCG). الصيغة بسيطة:

\n\n

new_seed = (old_seed * A + C) mod M

\n\n

حيث A و C و M ثوابت. هذا سريع، لكنه غير آمن تشفيريًا. إذا تمكن المهاجم من معرفة بضعة أرقام، يمكنه استعادة البذرة (seed) والتنبؤ بجميع الأرقام اللاحقة.

\n\n

متى تستخدم: للألعاب (غير النقدية)، الاختيار العشوائي لعنصر من قائمة، خلط البطاقات في تطبيق عادي.

\n\n

المستوى المتقدم: ThreadLocalRandom لتعدد الخيوط

\n\n

إذا كان تطبيقك يستخدم بشكل نشط coroutines أو تعدد الخيوط، فإن Random العادي قد يصبح عنق زجاجة. كل استدعاء لـ nextInt() يتم مزامنته لتجنب حالات السباق. الحل هو ThreadLocalRandom من Java:

\n\n
import java.util.concurrent.ThreadLocalRandom\n\nfun getRandomInRange(min: Int, max: Int): Int {\n    return ThreadLocalRandom.current().nextInt(min, max + 1)\n}
\n\n

هذه الفئة تخصص نسخة منفصلة من Random لكل خيط. لا حاجة للمزامنة - كل خيط يعمل مع المولد الخاص به. عمليًا، هذا يعطي زيادة في الأداء في سيناريوهات تعدد الخيوط.

\n\n

الأمان قبل كل شيء: SecureRandom

\n\n

تخيل الآن أنك تقوم بتوليد كلمة مرور لمرة واحدة (OTP) أو رمز لاستعادة الوصول. استخدام Random العادي هو جريمة. هنا يأتي دور SecureRandom:

\n\n
import java.security.SecureRandom\n\nfun generateSecureCode(length: Int): String {\n    val secureRandom = SecureRandom()\n    val digits = "0123456789"\n    return (1..length)\n        .map { digits[secureRandom.nextInt(digits.length)] }\n        .joinToString("")\n}
\n\n

SecureRandom يجمع الإنتروبيا من مصادر نظام التشغيل: ضوضاء الميكروفون، توقيتات ضغطات المفاتيح (في المحاكي - من ملف /dev/random أو /dev/urandom). هذا يجعله غير قابل للتنبؤ. لكن الثمن هو السرعة - يمكن أن يكون أبطأ بعشرات المرات من Random العادي.

\n\n

هام: على Android، S

المدونات

توصيات الكتب