2010年2月12日 星期五

TuPokerRule - 分析牌型

// u_TPokerRule.pas

unit u_TPokerRule;

interface
uses
        Windows, Classes, SysUtils,
        StdCtrls,
        ch_LogMessages,

        u_TList,
        u_TDeck,
        u_TexasHoldConst;

type

//******************************************************************************
// 類別名稱:TuPokerRule
// 功  能:分析牌型
//******************************************************************************
        TuPokerRule = class
          private
            m_PokerRuleMessToFiles : TLogMessToFiles;
            m_nPokerRule : integer; // 牌型

            // 計算每個花色的牌有幾張
            m_aCategory : array[0..3] of integer;
            // 記錄 每種 數字 有幾張
            m_aSumIndex: array[0..CARD_INDEX_LIMIT] of integer;
            // 記錄有幾種牌型
            m_aSumRules: array[0..POKER_RULES_LIMIT - 1]of integer;

            // 暫存要分析的撲克
            m_TempPokerList : TuList; // type TCardData.nListIndex;
            m_CardDataList: TuList; // type TCardData;
            m_MaxRulePoker : TuList; // type TCardData; 最大的五張牌


            m_pDeck : TuDeck;

            function _GetFlushIndex(): Integer; // 抓同花是那一個花色

            function _GetMaxRules : Integer; // 取最大的牌型
            procedure _OnRanderMaxPoker( nRuleType:Integer ); // 依牌型抓最大的五張

            procedure _OnMaxPokerZilch;         // 抓 最大的五張
            procedure _OnMaxPokerOnePair;       // 抓 一對 最大的五張
            procedure _OnMaxPokerTwoPair;       // 抓 兩對 最大的五張
            procedure _OnMaxPokerThreeKind;     // 抓 三條 最大的五張
            procedure _OnMaxPokerStraight;      // 抓 順子 最大的五張
            procedure _OnMaxPokerFlush;         // 抓 同花 最大的五張
            procedure _OnMaxPokerFullHouse;     // 抓 葫蘆 最大的五張
            procedure _OnMaxPokerFourKind;      // 抓 鐵支 最大的五張
            procedure _OnMaxPokerStraightFlush; // 抓 同花順 最大的五張

            function _PokerRulesTwoPair:Integer;         // 檢查有沒有 兩對
            function _PokerRulesStraight : Integer;      // 檢查有沒有 順子
            function _PokerRulesFlush :Integer;          // 檢查有沒有 同花
            function _PokerRulesFullHouse: Integer;      // 檢查有沒有 葫蘆
            function _PokerRulesStraightFlush():Integer; // 檢查有沒有 同花順
            function _PokerRulesRoyalFlush():Integer;    // 檢查有沒有 同花順

            procedure _debug_LogPoker;// 將 牌 匯出
          public
            constructor Create(var pDeck: TuDeck);
            destructor Destroy(); override;

            procedure Init();
            procedure OnAddCard(nIndex:Integer);        // 將牌加入
            function GetPokerRule(): Integer;           // 取出最大的牌型
            procedure GetMaxRulePoker(var MaxPoker:TuList); // 將最大的五張牌寫入 MaxPoker

        end;



//******************************************************************************
// 類別名稱:TuUITextPokerRule
// 功  能:牌型顯示 文字版本
//******************************************************************************
        TuTextPokerRule = class
          private
            //m_uiText : TuUIText;
            m_strPokerRule : string; // 轉換完成的字串
            m_AToKTextList : TStringList; // A 到 K 的文字 字串
            m_PokerRulesFormat : TStringList; //
          public
            constructor Create();
            destructor Destroy(); override;
            procedure OnProcess(PokerRules: Word; var CardDataList : TuList ); // 牌型 五張牌
            property Text: string read m_strPokerRule;
        end;



implementation

// { TuUITextPokerRule }

constructor TuTextPokerRule.Create;
begin
        m_AToKTextList := TStringList.Create();
        if( Assigned( m_AToKTextList ) = True ) then begin
            m_AToKTextList.LoadFromFile( INI_DATA_PATH + 'AToKText_en.ini' );
        end;

        m_PokerRulesFormat := TStringList.Create();
        if( Assigned( m_PokerRulesFormat ) = True ) then begin
            m_PokerRulesFormat.LoadFromFile( INI_DATA_PATH + 'PokerRulesTextFormat_en.ini' );
        end;

end;


destructor TuTextPokerRule.Destroy;
begin
        m_PokerRulesFormat.Free;
        m_AToKTextList.Free;
  inherited;
end;


procedure TuTextPokerRule.OnProcess(PokerRules: Word;
  var CardDataList: TuList);
var
        strP1:string;
        strP2:string;

        TmpCardData : TCardData;
        TmpCardDataList : TuList;
        nIndex : Integer;
begin

        if CardDataList.Count = 0 then
            exit;

        strP1 := '';
        strP2 := '';
        // 牌型
        case PokerRules of
          POKER_RULES_ZILCH: begin

              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];
          end;
          POKER_RULES_ONE_PAIR: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);

          end;

          POKER_RULES_TWO_PAIRS: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);

              TmpCardData := CardDataList.GetItems(3);
              nIndex := TmpCardData.Index - 1;
              strP2 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_THREE_KIND: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_STRAIGHT: begin
              TmpCardData := CardDataList.GetItems(4);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];

              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP2 := m_AToKTextList.Strings[ nIndex ];
          end;

          POKER_RULES_FLUSH: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];

          end;

          POKER_RULES_FULLHOUSE: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);

              TmpCardData := CardDataList.GetItems(3);
              nIndex := TmpCardData.Index - 1;
              strP2 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_FOUR_KIND: begin
              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP1 := Format('%ss',[m_AToKTextList.Strings[ nIndex ]]);
          end;

          POKER_RULES_STRAIGHT_FLUSH: begin
              TmpCardData := CardDataList.GetItems(4);
              nIndex := TmpCardData.Index - 1;
              strP1 := m_AToKTextList.Strings[ nIndex ];

              TmpCardData := CardDataList.GetItems(0);
              nIndex := TmpCardData.Index - 1;
              strP2 := m_AToKTextList.Strings[ nIndex ];
          end;

//          POKER_RULES_STRAIGHT_FLUSH: begin
//              TmpCardData := CardDataList.GetItems(0);
//              nIndex := TmpCardData.Index - 1;
//              strP1 := m_AToKTextList.Strings[ nIndex ];
//
//              TmpCardData := CardDataList.GetItems(4);
//              nIndex := TmpCardData.Index - 1;
//              strP2 := m_AToKTextList.Strings[ nIndex ];
//          end;


        end;

        m_strPokerRule := Format(m_PokerRulesFormat.Strings[PokerRules], [strP1, strP2]);

end;

constructor TuPokerRule.Create(var pDeck: TuDeck);
begin
        m_pDeck := pDeck;
        m_TempPokerList := TuList.Create();
        m_MaxRulePoker := TuList.Create();
        m_CardDataList := TuList.Create();

        m_PokerRuleMessToFiles := TLogMessToFiles.Create('PokerRuleMessage.txt');
end;

destructor TuPokerRule.Destroy;
begin
        m_PokerRuleMessToFiles.Free;
        m_TempPokerList.Free;
        m_MaxRulePoker.Free;
        m_CardDataList.Free;
end;


//******************************************************************************
// 函式名稱:Init
// 功  能:使用TuPokerRule 之前要先呼叫Init 用來清除所有資料
//******************************************************************************
procedure TuPokerRule.Init;
var
        i:integer;
begin

        // 初始化 PokerRules 記錄
        m_nPokerRule := POKER_RULES_ZILCH;

        // 清除花色記錄器
        for i := 0 to High(m_aCategory) do begin
            m_aCategory[i] := 0;
        end;

        // 清除牌數字記錄器
        for i := 0 to High(m_aSumIndex) do begin
            m_aSumIndex[i] := 0;
        end;

        // 清除牌數字記錄器
        for i := 0 to High(m_aSumRules) do begin
            m_aSumRules[i] := 0;
        end;

        // 清除暫存陣列
        m_TempPokerList.Clear();
        m_MaxRulePoker.Clear();
        m_CardDataList.Clear();
end;


//******************************************************************************
// 函式名稱:OnAddCard
// 功  能:將要運牌的牌加入TuPokerRule
//******************************************************************************
procedure TuPokerRule.OnAddCard(nIndex:Integer);
begin

        if( nIndex = - 1 ) then begin
            exit;
        end;
        m_TempPokerList.Add(Pointer(nIndex));
        m_CardDataList.Add(m_pDeck.Items(nIndex));
end;


//******************************************************************************
// 函式名稱:GetPokerRule
// 功  能:TuPokerRule 最主要的函式 計算牌型 計算最大的五張牌
//******************************************************************************
function TuPokerRule.GetPokerRule():Integer ;
var

        i: integer;
        nNum: integer;
        nListIndex: integer;
        nCategory : integer;
        // 有幾對
        nPairCount : integer;
        nThreeCount : integer;


begin
    try
        if m_TempPokerList.Count = 0 then  // 沒有牌不用處理
          exit;

        m_CardDataList.Sort(compareByPoker);

        for i := 0 to m_TempPokerList.Count - 1 do begin

            nListIndex := Integer(m_TempPokerList.GetItems(i));
            nCategory := m_pDeck.Category(nListIndex);
            nNum :=  m_pDeck.Index(nListIndex);

            // 計數每種花色有幾張
            m_aCategory[nCategory] := m_aCategory[nCategory] + 1;

            // 計數 同樣數字的撲克牌有幾張
            m_aSumIndex[nNum] :=  m_aSumIndex[nNum] + 1;

            if nNum = 13 then
                m_aSumIndex[0] :=  m_aSumIndex[0] + 1;

        end;

        for i := 1 to High(m_aSumIndex) do begin
            case m_aSumIndex[i] of
                2: m_aSumRules[POKER_RULES_ONE_PAIR] :=  m_aSumRules[POKER_RULES_ONE_PAIR] + 1;     // 計數對子
                3: m_aSumRules[POKER_RULES_THREE_KIND] := m_aSumRules[POKER_RULES_THREE_KIND] + 1;  // 計數三條
                4: m_aSumRules[POKER_RULES_FOUR_KIND] := m_aSumRules[POKER_RULES_FOUR_KIND] + 1;   // 計數四隻
            end;
        end;

        // 這裡有牌型是互斥的 可以使用 if else 作區分加快計算
        m_aSumRules[POKER_RULES_TWO_PAIRS] := _PokerRulesTwoPair();  // 檢查 兩對
        m_aSumRules[POKER_RULES_STRAIGHT] := _PokerRulesStraight();  // 檢查 順子
        m_aSumRules[POKER_RULES_FLUSH] := _PokerRulesFlush();        // 檢查 同花
        m_aSumRules[POKER_RULES_FULLHOUSE] := _PokerRulesFullHouse(); // 檢查 葫蘆
        m_aSumRules[POKER_RULES_STRAIGHT_FLUSH] := _PokerRulesStraightFlush();// 檢查 同花順
        m_aSumRules[POKER_RULES_ROYAL_FLUSH] := _PokerRulesRoyalFlush();  // 檢查 大同花順

        Result := _GetMaxRules();
        _OnRanderMaxPoker(Result);

      except
          m_PokerRuleMessToFiles.m_WriteTXTOne('GetPokerRule', 1);
      end;


end;


//******************************************************************************
// 函式名稱:_OnRanderMaxPoker
// 功  能:依牌型種類 抓出最大的五張牌
//******************************************************************************
procedure TuPokerRule._OnRanderMaxPoker(nRuleType: Integer);
begin

        case nRuleType of
            POKER_RULES_ZILCH:        _OnMaxPokerZilch;       // 沒有
            POKER_RULES_ONE_PAIR:     _OnMaxPokerOnePair;     // 一對
            POKER_RULES_TWO_PAIRS:    _OnMaxPokerTwoPair;     // 兩對
            POKER_RULES_THREE_KIND:   _OnMaxPokerThreeKind;   // 三條
//          POKER_RULES_SMALL_STRAIGHT:                     // 小順子
            POKER_RULES_STRAIGHT:     _OnMaxPokerStraight;    // 順子
            POKER_RULES_FLUSH:        _OnMaxPokerFlush;           // 同花
            POKER_RULES_FULLHOUSE:    _OnMaxPokerFullHouse;   // 葫蘆
            POKER_RULES_FOUR_KIND:    _OnMaxPokerFourKind;    // 鐵支
            POKER_RULES_STRAIGHT_FLUSH:_OnMaxPokerStraightFlush;  // 同花順
            POKER_RULES_ROYAL_FLUSH:  _OnMaxPokerStraightFlush;   // 大同花順
        end;

end;


//******************************************************************************
// 函式名稱:_GetMaxRules
// 功  能:選出 最大的牌型
//******************************************************************************
function TuPokerRule._GetMaxRules() : Integer;
var
        i : Integer;
begin

        for i := POKER_RULES_LIMIT - 1  downto POKER_RULES_ZILCH do begin
            if( m_aSumRules[i] > 0 ) then begin
                m_nPokerRule := i;
                break;
            end;
        end;
        Result := m_nPokerRule;

end;


//******************************************************************************
// 函式名稱:PokerRulesTwoPair
// 功  能:檢查有沒有兩對
//******************************************************************************
function TuPokerRule._PokerRulesTwoPair():integer;
begin

        if  m_aSumRules[POKER_RULES_ONE_PAIR] < 2 then
        begin
            Result := 0;
            exit;
        end;
        Result := 1;

end;


//******************************************************************************
// 函式名稱:PokerRulesStraight
// 功  能:檢查牌型 順子 & 順便檢查是不是最小順
//******************************************************************************
function TuPokerRule._PokerRulesStraight : integer;
var
        i : integer;
        nCountStraight : integer;
        nMaxCountStraight : integer;
begin
        nCountStraight := 0;
        nMaxCountStraight := 0;

        Result := 0;

        for i := High(m_aSumIndex) downto 0  do begin
            if m_aSumIndex[i] = 0 then
                nCountStraight := 0;

            if m_aSumIndex[i] > 0 then
                nCountStraight := nCountStraight + 1;

            if nMaxCountStraight < nCountStraight then
                nMaxCountStraight := nCountStraight;
        end;

        // 有超過5張連續的牌 代表有順子
        if nMaxCountStraight >= 5 then begin
            Result := 1;
        end;

        // 這裡要另外檢查 是否為最小順  A 2 3 4 5

        if( m_aSumIndex[1] > 0) And
          ( m_aSumIndex[2] > 0) And
          ( m_aSumIndex[3] > 0) And
          ( m_aSumIndex[4] > 0) And
          ( m_aSumIndex[0] > 0) then begin

            if nMaxCountStraight = 5 then begin
                m_aSumRules[POKER_RULES_SMALL_STRAIGHT] := 1;
            end;
            
            Result := 1;
        end;


end;


//******************************************************************************
// 函式名稱:PokerRulesFlush
// 功  能:檢查牌型 同花
//******************************************************************************
function TuPokerRule._PokerRulesFlush :integer;
var
        i : integer;
        nListIndex : integer;
        nNum : integer;
        nCategory : integer;
begin
        Result := 0;
        // 檢查是否有五張的花色
        for i := 0 to High(m_aCategory) do begin
            if( m_aCategory[i] >= 5 ) then begin
                m_nPokerRule := POKER_RULES_FLUSH;
                Result := 1;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:PokerRulesFullHouse
// 功  能:檢查牌型 葫蘆
//******************************************************************************
function TuPokerRule._PokerRulesFullHouse: integer;
begin

        Result := 0;
        case m_aSumRules[POKER_RULES_THREE_KIND] of
            // 有兩組三條
            2: Result := 1;
            // 有一組三條 + 一組對子
            1:
                begin
                if(m_aSumRules[POKER_RULES_ONE_PAIR] > 0 ) then
                    Result := 1;
                end;
        end;
    
end;


// 加入了 m_CardDataList 找時間改寫..
//******************************************************************************
// 函式名稱:PokerRulesStraightFlush
// 功  能:檢查牌型 同花順
//******************************************************************************
function TuPokerRule._PokerRulesStraightFlush():Integer ;
var
        i : Integer;
        nA : Integer;
        nTemp : Integer;
        nCategoryIndex: Integer;
        nCategory2Index: Integer;
        nCategory3Index: Integer;

        nSum: Integer;
        nMaxSum : Integer;

        aArray : TuList;

        str : String;
        strFileName :string;

begin

        Result := 0;
        // 沒有同花 跟 順子 就不用檢查 同花順        
        if ( m_aSumRules[POKER_RULES_STRAIGHT] = 0 ) Or
           (m_aSumRules[POKER_RULES_FLUSH] = 0) then
           exit;


        aArray := TuList.Create();

        for i := 0 to m_TempPokerList.Count - 1  do begin
            aArray.Add(m_TempPokerList.GetItems(i));
        end;

        aArray.Sort(compareByInteger);

        nCategoryIndex := _GetFlushIndex();


        // 檢查有沒有連續的順子
        nSum := 0;
        nMaxSum := 0;
        for i := 0 to m_TempPokerList.Count - 2 do
        begin
            nCategory2Index :=  m_pDeck.Category(Integer(aArray.GetItems(i + 1)));
            nCategory3Index :=  m_pDeck.Category(Integer(aArray.GetItems(i)));

            if( Integer(aArray.GetItems(i + 1)) - Integer(aArray.GetItems( i )) = 1 ) And
            ( nCategory2Index = nCategory3Index ) then
            begin
                nSum := nSum + 1;
                if( nMaxSum < nSum ) then
                    nMaxSum := nMaxSum + 1;
            end
            else
            begin
                nSum := 0;
            end;
        end;

        if( nMaxSum >= 4 ) then
        begin
            Result := 1;
            aArray.Free();
            exit;
        end;

        // 如果有小順 要另外檢查  只要檢查 有沒有同花色A 就行了
        if( nMaxSum <> 3 ) Or
          (m_aSumRules[POKER_RULES_SMALL_STRAIGHT] = 0 )then begin
            aArray.Free();
            exit;
        end;

        // 計算同花色的A 的索引值
        nA := nCategoryIndex * 13 + 12 ;
        for i := 0 to m_TempPokerList.Count -1 do
        begin
            //nTemp := aArray[i];
            if Integer(aArray.GetItems(i)) = nA then
            begin
                Result := 1;
                break;
            end;
        end;

        aArray.Free();


end;


//******************************************************************************
// 函式名稱:_PokerRulesRoyalFlush
// 功  能:檢查牌型 大同花順
//******************************************************************************
function TuPokerRule._PokerRulesRoyalFlush: Integer;
var
        i:Integer;
        j:integer;
        TmpCardData : TCardData;
        nCategory:integer;
        nCardIndex:integer;
begin
        Result := 0;
        // 沒有同花順 就不用檢查 大同花順
        if ( m_aSumRules[POKER_RULES_STRAIGHT_FLUSH] = 0 ) then
           exit;

        nCategory := _GetFlushIndex();
        nCardIndex := 13;

        // 抓滿五張
        j := m_CardDataList.Count - 1;
        for i := 0 to 4 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if (TmpCardData.Index <> nCardIndex) Or
               (TmpCardData.Category <> nCategory) then begin 
               Result := 0;
               exit;

            end;
            j := j - 1;
            nCardIndex := nCardIndex - 1;
        end;

        Result := 1;

end;


//******************************************************************************
// 函式名稱:GetMaxRulePoker
// 功  能:計算最大的牌型
//******************************************************************************
procedure TuPokerRule.GetMaxRulePoker(var MaxPoker: TuList);
var
        i : integer;
begin

        MaxPoker.Clear();
        for i := 0 to m_MaxRulePoker.Count -1 do begin
            MaxPoker.Add(m_MaxRulePoker.GetItems(i));
        end;
        
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerOnePair
// 功  能:將沒有任何牌形 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerZilch;
var
        i: integer;
        j: integer;
        TmpCardData : TCardData;
begin
        // 抓五張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerOnePair
// 功  能:將牌形一對 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerOnePair;
var
        i: integer;
        j: integer;
        nNum: integer;

        TmpCardData : TCardData;
begin
        // 抓最大的一對牌
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 2 then begin
                for j := 0 to m_CardDataList.Count - 1 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    //nListIndex := TmpCardData.ListIndex;
                    nNum :=  TmpCardData.Index;
                    if nNum = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;
                end;
                Break;
            end;
        end;

        // 抓剩下的三張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if m_aSumIndex[TmpCardData.Index] = 2 then begin
                Continue;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_OnMaxPokerTwoPair
// 功  能:將牌形兩對 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerTwoPair;
var

        i: integer;
        j: integer;
        nNum: integer;
        nListIndex: integer;
        nPairCount: integer;
        TmpCardData : TCardData;
begin

        // 抓最大的兩對牌
        nPairCount := 0;
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 2 then begin
                nPairCount := nPairCount + 1;
                for j := 0 to m_CardDataList.Count - 1 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    //nListIndex := TmpCardData.ListIndex;
                    nNum :=  TmpCardData.Index;
                    if nNum = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;
                end;
                if nPairCount = 2 then begin
                    break;
                end;
            end;
        end;

        // 抓第五張
        nPairCount := 0;
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);

            if m_aSumIndex[TmpCardData.Index] = 2 then begin
                nPairCount := nPairCount + 1;
                if nPairCount <= 4 then begin
                    Continue;
                end;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            break;

        end;
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerThreeKind
// 功  能:將牌形三條 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerThreeKind;
var
        i: integer;
        j: integer;
        nNum: integer;

        TmpCardData : TCardData;
begin
        // 抓三條
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 3 then begin
                for j := 0 to m_CardDataList.Count - 1 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    //nListIndex := TmpCardData.ListIndex;
                    nNum :=  TmpCardData.Index;
                    if nNum = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;
                end;
                Break;
            end;
        end;

        // 抓滿五張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if m_aSumIndex[TmpCardData.Index] = 3 then begin
                Continue;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;


end;


//******************************************************************************
// 函式名稱:_OnMaxPokerStraight
// 功  能:將牌形 順子 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerStraight;
var
        i : integer;

        nCardDataIndex : integer;
        nCardDataNextIndex : Integer;
        nCountStraight : integer;
        nMaxCountStraight : integer;

        TmpCardData : TCardData;
        TmpCardDataNext : TCardData;
begin

        _debug_LogPoker();
        
        nCountStraight := 0;
        nMaxCountStraight := 0;

        nCardDataIndex := m_CardDataList.Count - 1;
        nCardDataNextIndex := nCardDataIndex - 1;
        for i := m_CardDataList.Count - 1 downto 1 do begin
            TmpCardData := m_CardDataList.GetItems(nCardDataIndex);
            TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);

            // 先加入第一張牌
            if m_MaxRulePoker.Count = 0 then
                m_MaxRulePoker.Add(TmpCardData);

            // 如果 兩張牌面數字一樣 換下一張
            while (nCardDataNextIndex > 0) And
                (TmpCardData.Index = (TmpCardDataNext.Index )) do begin
                nCardDataNextIndex := nCardDataNextIndex - 1;
                TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);
            end;

            // 下一張是不是比前一張少一
            if TmpCardData.Index = (TmpCardDataNext.Index + 1) then begin
                m_MaxRulePoker.Add(TmpCardDataNext);
            end else begin
                m_MaxRulePoker.Clear;
            end;

            // 超過五張
            if m_MaxRulePoker.Count = 5 then
                Break;

            nCardDataIndex := nCardDataNextIndex;
            nCardDataNextIndex := nCardDataNextIndex - 1;

            if nCardDataIndex = 0 then begin
                Break;
            end;

        end;

        // 如果是小順 要另外處理A
        if m_aSumRules[POKER_RULES_SMALL_STRAIGHT] <> 0 then begin
            for i := m_CardDataList.Count - 1 downto 0 do begin
                TmpCardData := m_CardDataList.GetItems(i);
                if TmpCardData.Index = 13 then begin
                    m_MaxRulePoker.Add(TmpCardData);
                    break;
                end;
            end;
        end;


end;


//******************************************************************************
// 函式名稱:_OnMaxPokerFlush
// 功  能:將牌形 同花 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerFlush;
var
        i : integer;
        nListIndex : integer;
        nNum : integer;
        nCategory : integer;

        TmpCardData : TCardData;
begin

        nCategory := _GetFlushIndex();

        for i := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(i);
            if TmpCardData.Category = nCategory then begin
                m_MaxRulePoker.Add(TmpCardData);
            end;

            if m_MaxRulePoker.Count = 5 then
                Break;
        end;
end;


//******************************************************************************
// 函式名稱:_OnMaxPokerFullHouse
// 功  能:將牌形 葫蘆 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerFullHouse;
var
        i: integer;
        j: integer;
        nMaxThreeKind : integer;
        TmpCardData : TCardData;
begin
        // 抓最大的三條
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 3 then begin

                for j := m_CardDataList.Count - 1 downto 0 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    if TmpCardData.Index = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;

                    if m_MaxRulePoker.Count = 3 then
                        Break;
                end;
                nMaxThreeKind := i;
                Break;
            end;
        end;

        // 抓最大的對子
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] >= 2 then begin
                if i = nMaxThreeKind then begin
                    continue;
                end;

                for j := m_CardDataList.Count - 1 downto 0 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    if TmpCardData.Index = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;

                    if m_MaxRulePoker.Count = 5 then begin
                        Exit;
                    end;
                end;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_OnMaxPokerFourKind
// 功  能:將牌形 鐵支 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerFourKind;
var
        i: integer;
        j: integer;
        nMaxFourKind : integer;
        TmpCardData : TCardData;
begin
        // 抓最大的鐵支四張
        for i := High(m_aSumIndex) downto 1 do begin
            if m_aSumIndex[i] = 4 then begin

                for j := m_CardDataList.Count - 1 downto 0 do begin
                    TmpCardData := m_CardDataList.GetItems(j);
                    if TmpCardData.Index = i then begin
                        m_MaxRulePoker.Add(TmpCardData);
                    end;

                    if m_MaxRulePoker.Count = 4 then
                        Break;
                end;
                nMaxFourKind := i;
                Break;
            end;
        end;

        // 抓滿五張
        for j := m_CardDataList.Count - 1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(j);
            if TmpCardData.Index = nMaxFourKind then begin
                Continue;
            end;

            m_MaxRulePoker.Add(TmpCardData);
            if m_MaxRulePoker.Count = 5 then begin
                Break;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_OnMaxPokerStraightFlush
// 功  能:將牌形 同花順 的最大五張牌抓出來
//******************************************************************************
procedure TuPokerRule._OnMaxPokerStraightFlush;
var
        i : integer;

        nCardDataIndex : integer;
        nCardDataNextIndex : Integer;
        nCountStraight : integer;
        nMaxCountStraight : integer;

        TmpCardData : TCardData;
        TmpCardDataNext : TCardData;

        nCategory : integer;
begin
        _debug_LogPoker();

        nCategory := _GetFlushIndex();

        
        nCountStraight := 0;
        nMaxCountStraight := 0;

        nCardDataIndex := m_CardDataList.Count - 1;
        for i := m_CardDataList.Count - 1 downto 1 do begin

            TmpCardData := m_CardDataList.GetItems(nCardDataIndex);
            while TmpCardData.Category <> nCategory do begin
                nCardDataIndex := nCardDataIndex - 1;
                TmpCardData := m_CardDataList.GetItems(nCardDataIndex);
            end;

            nCardDataNextIndex := nCardDataIndex - 1;
            TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);
            while (nCardDataNextIndex > 0 ) And
                (TmpCardDataNext.Category <> nCategory) do begin
                nCardDataNextIndex := nCardDataNextIndex - 1;
                TmpCardDataNext := m_CardDataList.GetItems(nCardDataNextIndex);
            end;

            // 先加入第一張牌
            if m_MaxRulePoker.Count = 0 then
                m_MaxRulePoker.Add(TmpCardData);

//            同樣花色不可能數字一樣 // 如果 兩張牌面數字一樣 換下一張
//            while TmpCardData.Index = (TmpCardDataNext.Index ) do begin
//                nCardDataNextIndex := nCardDataNextIndex - 1;
//                TmpCardDataNext := m_CardDataList[nCardDataNextIndex];
//            end;

            // 下一張是不是比前一張少一
            if TmpCardData.Index = (TmpCardDataNext.Index + 1) then begin
                m_MaxRulePoker.Add(TmpCardDataNext);
            end else begin
                m_MaxRulePoker.Clear;
            end;

            // 超過五張
            if m_MaxRulePoker.Count = 5 then
                Break;

            nCardDataIndex := nCardDataNextIndex;
//            nCardDataNextIndex := nCardDataNextIndex - 1;

            if nCardDataIndex = 0 then begin
                Break;
            end;

        end;

        // 如果是小順 要另外處理A
        if m_aSumRules[POKER_RULES_SMALL_STRAIGHT] <> 0 then begin
            for i := m_CardDataList.Count - 1 downto 0 do begin
                TmpCardData := m_CardDataList.GetItems(i);
                if TmpCardData.Index = 13 then begin
                    m_MaxRulePoker.Add(TmpCardData);
                    break;
                end;
            end;
        end;

end;


//******************************************************************************
// 函式名稱:_GetFlushIndex
// 功  能:傳回同花的花色索引
//******************************************************************************
function TuPokerRule._GetFlushIndex: Integer;
var
        i:integer;
begin

        Result := -1 ;
        // 查一下什麼同花
        for i := 0 to High(m_aCategory) do
        begin
            if( m_aCategory[i] >= 5 ) then
            begin
                Result := i;
                break;
            end;
        end;

        if Result = -1 then begin
            Result := 0;
        end;

        
end;


procedure TuPokerRule._debug_LogPoker;
var
        i:Integer;
        str:String;
        strPoker:string;
        TmpCardData : TCardData;
begin
        exit;
        str := '';
        strPoker := '';
        for i := m_CardDataList.Count -1 downto 0 do begin
            TmpCardData := m_CardDataList.GetItems(i);
            str := Format('%d ', [TmpCardData.Index] );
            strPoker := strPoker + str;
        end;
        m_PokerRuleMessToFiles.m_WriteTXTOne(strPoker, 1);

end;


end.


應該感受的出來這一份代碼表現的緊張, 在時間壓力下寫出來的代碼實在是慘無人道丫!

在接下來的C++版時會大力的改善 Switch 實在是個使用多型的好地方!

沒有留言:

張貼留言