easyDelphi Q&A
+1 تصويت
62 مشاهدات

 

هذا مثال لتوليد اربع ارقام  .. من 1 الى 4 بترتيب عشوائي وبدون تكرار

 

  

var
  ArrNum: Array of Integer;
   i, j, n: Integer;
  NumDouble: Boolean;
begin

  for j := 0 to 3 do
  begin
    NumDouble := false;
    while True do
    begin
      n := RandomRange(1, 4);
      for i := Low(ArrNum) to High(ArrNum) do
      begin
        if ArrNum[i] = n then
          NumDouble := True
      end;
      if NumDouble = false then
      begin
        ArrNum := ArrNum + [n];
        Break;
      end;
    end;
  end;
  end;


المشكلة في هذا الكود انه عند جلب رقم عشوائي غالبا مايتكرر 
و بالتالي يستم تكرار الحلقة الى غاية اجاد رقم غير مكرر وهذا قد يستغرق وقت كبير وبالتالي يحدث تشنج للبرنامج 
سُئل في تصنيف vcl بواسطة (10,670 نقاط) | 62 مشاهدات
 

2 إجابة

+1 تصويت
أفضل إجابة

فكرة رائعة استاذ سامرلكن اضنك نسيت توضيح نقطة مهمة وهيا عند سحب رقم عشؤائ تقوم بنقله الى بداية المصفوفة او نهايتها ثم حذفه من المصفوفة
لكي تستطيع تقليص المصفوفة (المجال) والحفاظ على ترتيب المجال واستخدام RandomRange مرة اخرى في اختيار رقم اخر

وهذ هو الكود بعد تصحيحه  
 

 ArrNum, ArrRange: Array of Integer;
  i, n: Integer;
begin

  for i := 1 to 4 do
  begin
    ArrRange := ArrRange + [i];
  end;

  while Length(ArrRange) > 0 do
  begin
    i := RandomRange(Low(ArrRange), High(ArrRange));
    ArrNum := ArrNum + [ArrRange[i]];
    n := ArrRange[0];
    ArrRange[0] := ArrRange[i];
    ArrRange[i] := n;
    Delete(ArrRange, 0, 1);
  end;


 وكل الشكر للاستاذ سامر على الفكرة .

تم الرد عليه بواسطة (10,670 نقاط)
مختارة بواسطة
انا لم اطرح الية حذف عنصر. . لا يهم ان كانت مصفوفة او list ..
ما يهم ان الرقم العشوائي هو مكان الكرت. وليس قيمة الكرت.
اسحب الكرت.. اي انقله لمجموعة ثانية.. او انسخه واحذف الاول... لا يهم كيف تقوم بهذا. المهم ان يختفي من الاولى ويظهر في الثانية.
طبعا الحجم سيتقلص.. وانا ذكرت هذا.

بكل الاحوال . انا سعيد بان الاجابة كانت مناسبة لسؤالك.

يمكنك إتباع هذه الخواريزمية هنا :

unit UMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Vcl.ComCtrls;

type
  TRandomIntArray = array [0..3] of Integer;

  TFrmMain = class(TForm)
    Btn_ChooseRandom: TButton;
    Edt_Result: TEdit;
    procedure Btn_ChooseRandomClick(Sender: TObject);
  private
    { Private declarations }
    function calculate_Randoms: TRandomIntArray;
  public
    { Public declarations }
  end;

var
  FrmMain: TFrmMain;

implementation
uses
  Math;
{$R *.dfm}

function IsNumberInArray(const ANumber: integer;
  const AArray: array of integer; ALow, AHigh : integer): boolean;
var
  i: integer;
begin
  for i := ALow to AHigh do
    if ANumber = AArray[i] then
      Exit(true); // old delphi you must replace this line by this(begin result := true; break; end;)
  result := false;
end;

function TFrmMain.calculate_Randoms: TRandomIntArray;
var
  RandomInt: TRandomIntArray;
  I, J: Integer;
begin
  Randomize;

    RandomInt[0] := RandomRange(1, 5);

  for I := 1 to 3 do
  begin
    RandomInt[I] := RandomRange(1, 5);
    for J := 1 to 3 do
    begin
      if IsNumberInArray(RandomInt[I], RandomInt, 0, I-1)  then
      begin
        while IsNumberInArray(RandomInt[I], RandomInt, 0, I-1) do
        RandomInt[I] := RandomRange(1, 5); Application.ProcessMessages;
      end else Break;
    end;
  end;

  Result := RandomInt;
end;


procedure TFrmMain.Btn_ChooseRandomClick(Sender: TObject);
var
  Arr_: TRandomIntArray;
  I: Integer;
begin
  Edt_Result.Clear;
  Arr_ := calculate_Randoms;
  for I := 0 to 3 do
  begin
    Edt_Result.Text := Edt_Result.Text + IntToStr(Arr_[I]);
  end;
end;

end.

وحظا طيبا wink

شكرا اخ محمد على الاجابة  .. كود جيد لكنه كبير قليلا ولقد اجبت على السؤال بكود مختصر .. في النهاية تعدد الاجابات امر جيد .
0 تصويتات

هذه تشبه سحب عدد من كروت اللعب . سحب مجموعة كروت ولنقل 5  من مجموعة اكبر 52 كرت .

  1.  اعمل مصفوفة لكل الكروت 
  2. اوجد رقم عشوائي . سيعبر هذا الرقم عن مكان الكرت الذي سيتم سحبه .
  3. احفظ بيانات الكرت الموجود عند المكان العشوائي الذي ظهر عندك في الخطوة الثانية في مصفوفة النتيجة.
  4. احذف الكرت من المجموعة الاساسية الكبيرة.
  5. كرر العمليات السابقة بحسب عدد الكروت المطلوب

ستلاحظ انك تاخذ مكان عشوائي للقيمة . وليس القيمة نفسها . وستلاحظ ايضا ان في كل مرة تقلص مجال الرقم العشوائي بتقليص المجموعة الاساسية .

فكرة بالموضوع . بشكل يديوي . عندك مجموعة ارقام . اخترت مكان عشوائي . ثم سحبت الكرت من هذا المكان ووضعته في مجموعة اخرى .

ان شاء الله تكون اجابتي هي ما تبحث عنه

تم الرد عليه بواسطة (20,380 نقاط)
كيف أخذ رقم عشوائي من مجموعة ؟
اذا استعملت RandomRange(1, 10)
في المرة اتالية لايمكن اشتثنار الرقم المختار سابقا وربما يتكرر اختيار نفس الرقم .
يبدو ان لم افهم كلامك في البدابة جيد لانه كان هناك شئ ناقص وقد ذكرته لك في اجابة على السؤال

اسئلة متعلقة

+2 تصويتات
2 إجابة
سُئل أغسطس 9، 2018 في تصنيف vcl بواسطة KHALED (6,560 نقاط) | 129 مشاهدات
+3 تصويتات
2 إجابة
سُئل أغسطس 14، 2018 في تصنيف vcl بواسطة Yamada Fakir (1,410 نقاط) | 157 مشاهدات
0 تصويتات
1 إجابة
سُئل أبريل 7 في تصنيف vcl بواسطة NADIRE (860 نقاط) | 20 مشاهدات
0 تصويتات
1 إجابة
سُئل فبراير 8 في تصنيف vcl بواسطة Amar Gozim (10,670 نقاط) | 40 مشاهدات
+4 تصويتات
1 إجابة
سُئل سبتمبر 21، 2018 في تصنيف SQL Server بواسطة Yamada Fakir (1,410 نقاط) | 133 مشاهدات
ادعُ اصدقائك في الفايسبوك لمشاركتك
Comodo SSL

مرحبًا بك إلى EasyDelphi Q&A، حيث يمكنك طرح الأسئلة والحصول على الإجابة عليها من المستخدمين الآخرين.

لا يسمح بطلب او السؤال عن كراك او تفعيل او كسر او فك او اي شيء يخالف اتفاقيات الترخيص  مهما كان السبب ومهما كان البرنامج ونوعه. ولا حتى نشر روابط تحتوي على مثل هذه الاشياء لا في الاسئلة ولا في الاجابات ولا التعليقات . نهائيا

324 سؤال
533 إجابة
928 تعليق
222 مستخدم