一副扑克牌54张,用DELPHI写一方法,当点"洗牌"按钮时,将原有的54张牌重新打乱(假设最初按1,2,3,4....54的顺序放入一数组中) 

解决方案 »

  1.   

    用randomize 和 random()函数啊。不难吧。
    用一个二维数组纪录54张牌,一维纪录牌值1~54,二维为标志位。如P[1][0]、P[2][0]....P[54][0]
    写个循环,随机产生一个整数,每当随机抽出一张牌后,将二维标志置1,如P[33][1]。标志位的目的是为了防止重复抽中。
    直到所有牌抽完为止。
    算法可以优化,为了防止随机总是抽到已选中的牌,可以在抽到已选中牌后将整数依次加1,直到找到有标志位的。
    呵呵,这个以前我在做powerbuilder的时候做过,只不过用的不是牌而已。
      

  2.   

    你等等哈,我是从pb转过来的对delphi语法也不熟。
    其实语法次要,关键是算法。
      

  3.   

    后来想了想,觉得用两个1维数组更合适些,下面是窗口中〔洗牌〕按钮的代码。
    注意这里面算法的关键:当随机抽到的牌重复时,不是一味的再去随机抽牌,而是找临近的没有抽过的牌。这样的好处是
    当N特别大时比如不是54张牌而是100000个整数时执行效率就非常高。当然,略微降低了随机质量,但这是另一个话题,暂不讨论。学编程要精益求精,呵呵。这是我早几年面试PB时面试官微笑的告诉我的。
    不要总是抄袭别人源代码哦。:)procedure TForm1.Button1Click(Sender: TObject);
    type
    PX=array[1..N] of integer; //存储牌的数组
    var
    i,li_random:integer;
    P1,P2:PX;
    begin
    screen.cursor:=crHourglass;
      //初始化数组
      for i:=1 to N do
        begin
          p1[i]:=0;
          p2[i]:=i;
        end;
      //开始洗牌
      randomize;
      for i:=1 to N do
        begin
          begin
            repeat
              li_random:=random(N);//随机抽取一张牌
            until li_random>0;
            //判断随机抽出的牌是否已抽取过
            if li_random=p2[li_random] then//未抽取过,直接赋值
              begin
                p1[i]:=p2[li_random];
                p2[li_random]:=0;
              end
            else
              repeat//抽取过,循环加1直到遇到没有抽取过的牌
                if li_random=N then
                  li_random:=1
                else
                  li_random:=li_random+1;
                if li_random=p2[li_random] then
                  begin
                    p1[i]:=p2[li_random];
                    p2[li_random]:=0;
                  end;
              until p1[i]>0;
            end;
        end;
        //输出洗牌后的牌序
        memo1.Text:='';
        for i:=1 to N do
          memo1.Text:=memo1.Text+' '+IntToStr(P1[i]);
    screen.cursor:=crDefault;
    end;