在Delphi中随机化对提高速度

时间:2015-02-23 22:34:25

标签: delphi

我试图提高日常工作的速度,并希望得到一些投入。 情况如下:

在锦标赛中使用拼字游戏,以下条件适用:

  1. 比赛由20名或更多球员组成。
  2. 比赛次数在2到14之间,具体取决于锦标赛。
  3. 根据锦标赛的规模,玩家可按年龄划分。
  4. 目标是为锦标赛进行两次特别的投注:

    1. 玩家将随机配对每场比赛
    2. 玩家将被随机配对,但每场比赛将拥有相同的合作伙伴。
    3. 条件适用于边注注必须有偶数球员。 播放器表格包含:
    4. ID:整数,名称:字符串,分区:整数;

      有一个Sidebet表:

      PlayerID:Integer,RandomeEachGame:Boolean,RandomAllSame:Boolean;

      分数表包含:

      PlayerID:整数,GameNumber:整数,分数:整数;

      有一个RandomSidebets表:

      Player1ID:整数;

      Player2ID:整数

      GameNumber:整数; //哪个游戏得分为

      SameAllGames:Boolean; //如果是,那么配对是针对同一个伙伴的边路,否则它就是不同的伙伴边缘。

      我试图创建随机配对,处理似乎过多。我将特定分区中的玩家加载到动态阵列中,然后我从动态阵列中随机拉出,从阵列中移除该项目,这样我就不会在每场比赛中多次使用同一个玩家,并且为合作伙伴做同样的事情,然后将合作伙伴写入表格,以了解合作伙伴。

          Var
              Division : integer;
          I, J     : integer;
          DSourceUsed : TIntArray;
          DSource     : TIntArray;
          rndnum     : integer;
          Fld1       : TField;
      
      
          for Division := 1 to NumberofDivisions do begin
            SQLTEXT := 'SELECT sb.PlayerID FROM SIDEBET sb ';
        SQLTEXT := SQLTEXT + ' INNER JOIN PLAYERS p ON Sb.PlayerID=p.BPlayerID ';
        SQLTEXT := SQLTEXT + Format( ' WHERE (sb.RandomEachGame=) AND (p.Division=%d)', [ Division ] );
        Qry.SQL.Text := SQLTEXT;
        Qry.Open;
        if ( Qry.RecordCount > 0 ) then begin
              if RandomMethod = mrmAllSame then begin
                SetLength( DSource, Qry.RecordCount );
                SetLength( DSourceUsed, Qry.RecordCount );
            Qry.First;
            Fld1 := Qry.FieldByName( 'PlayerID' );
                I := 0;
            while not Qry.eof do begin
              DSourceUsed[ I ] := Fld1.AsInteger;
                  DSource[ I ] := Fld1.AsInteger;
                  inc( I );
          Qry.Next;
            end;
                for I := 0 to Qry.RecordCount - 1 do begin
              rndnum := RandomRange( 0, Length( DSourceUsed ) - 1 );
          DSource[ I ] := DSourceUsed[ rndnum ];
          DeleteX( DSourceUsed, rndnum ); // Routine that removes index from array so we don't repeat partners
            end;
            for I := 0 to Qry.RecordCount - 1 do begin
              if not Odd( I ) then begin
                    for J := 1 to NumberofGames do begin
                      QryGame.SQL.Text := Format( 'INSERT INTO RandomSideBets (Player11ID, Player2ID, Game) Values (%d, %d, %d, %d)', [ DSource[ I ], DSource[ I + 1 ], J, True ] );
              QryGame.Execute;
            end;
          end;
            end;
          end
          else begin
          for J := 1 to NumberOfGames do begin
            SetLength( DSource, Qry.RecordCount );
            SetLength( DSourceUsed, Qry.RecordCount );
            Qry.First;
            Fld1 := Qry.FieldByName( 'PlayerID' );
                I := 0;
            while not Qry.eof do begin
              DSourceUsed[ I ] := Fld1.AsInteger;
          DSource[ I ] := Fld1.AsInteger;
              inc( I );
          Qry.Next;
            end;
                for I := 0 to Qry.RecordCount - 1 do begin
              rndnum := RandomRange( 0, Length( DSourceUsed ) - 1 );
          DSource[ I ] := DSourceUsed[ rndnum ];
          DeleteX( DSourceUsed, rndnum ); // Delete index from array
            end;
                for I := 0 to Qry.RecordCount - 1 do begin
              if not Odd( I ) then begin
            QryGame.SQL.Text := Format( 'INSERT INTO RANDOMSIDEBET (Player1ID, Player2ID, Game, SameAllGames) Values (%d, %d, %d, %b)', [ DSource[ I ], DSource[ I + 1 ], J, FALSE ] );
            QryGame.Execute;
          end;
            end;
              end;
            end;
      end;
      Qry.Close;
          end;
      

2 个答案:

答案 0 :(得分:1)

您正在进行大量的同步查询,每个查询都要求数据到达服务器并返回(2 *延迟,加上处理时间)。

在本地缓存插入数组,然后当你完成算法时,立即发送它们(你没有提到你的SQL风格,所以你自己),或删除整个事情并写一个存储过程在服务器端执行此操作(与以前相同的附录)。存储过程将避免服务器之间的所有大型数据传输,这是服务器本身的本地传输。

此外,也许是时候使用异步处理了。这是2015年。你的大部分CPU时间浪费在等待I / O(你甚至使用的核心),或什么都不做(可能是你付钱的其他7个核心)。

答案 1 :(得分:0)

您只需要将数据库记录加载到单个数组中,然后您无需对物理记录进行排序或从列表中删除以获得随机化。相反,只需将一个整数数组随机化,作为播放器列表中的索引。

E.g。你加载了50个玩家的列表(我以硬编码50为例,你可以使用适当的变量来实际计算)。

var playerindex: array of integer;
SetLength(playerindex, 50);
for i := 0 to 50 - 1 do
    playerindex[i] := Random(50);

现在使用playerindex值索引你的实际玩家列表以获得随机对:

for pair := 0 to 50 div 2 - 1 do // 25 pairs
begin
  p1 := players[playerindex[pair * 2]];
  p2 := players[playerindex[pair * 2 + 1]];
  // record p1 and p2 as each pair of players
end;