Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Encapsulate a memcache for Texas Hold’em

0.00/5 (No votes)
15 Jul 2013CPOL 6.7K   78  
An article about encapsulating a memcache.

Introduction

This tip shows how to encapsulate a memcache for Texas hold'em. I will explain how the encapsulation makes the game logic easier. I can't give the source of the memcache, so I will explain some logical code to compensate.

Using the code 

For packet:

C++
#pragma once
#ifndef ES_TCP_MAX_BUFFER    
#   define  ES_TCP_MAX_BUFFER    1024*16
#endif

#ifndef _WINDEF_
typedef unsigned char       BYTE;
#endif 

#include <string>
#include <queue>
#include <vector>
#include <deque>
#include <list>
#include <iostream>
#include <sstream>
#include <map>
#include <arpa/inet.h>
#include <iomanip>
using namespace std;

#if WIN32
typedef long long       int64_t;
#endif

#ifndef WIN32
#   define _atoi64 atoll
#endif

#define     SERVER_PACEKTVER    1
#define     PROTOL_HEADER_SIZE  8

typedef unsigned long long __u64;
#define de_htonll(x) \
({ \
    __u64 __x = (x); \
    ((__u64)( \
    (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
    (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
    (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
    (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) <<  8) | \
    (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >>  8) | \
    (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
    (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
    (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
})

inline long long htonll(long long hvalue)
{
    short  i=20;
    if( htons(i) == i ) 
    {
        return hvalue;
    } 
    else 
    {
        return (long long)de_htonll(hvalue);
    }
}

inline long long ntohll(long long nvalue)
{
    short  i=20;
    if( htons(i) == i ) 
    {
        return nvalue;
    } 
    else 
    {
        return (long long)de_htonll(nvalue);
    }
}

inline string ESHexDumpImp(const void *pdata, unsigned int len)
{
   string outstr;
   if(pdata == 0 || len == 0)
   {
       return "";
   }
    
    int cnt = 0;
    int n = 0;
    int cnt2 = 0;
    stringstream  sstr;
    const char *data = (const char *)pdata;
    sstr<<"Address               Hexadecimal values                  Printable\n";
    sstr<<"-------  -----------------------------------------------  -------------\n";
    unsigned char buffer[20];
    unsigned int rpos = 0;

    while ( 1 )
    {
        if(len <= rpos)
        {
            break;
        }
        if(len >= rpos + 16)
        {
            memcpy(buffer, data + rpos, 16);
            rpos += 16;
            cnt = 16;
        }
        else
        {
            memcpy(buffer, data + rpos, len - rpos);
            cnt = len - rpos;
            rpos = len;
        }
        if(cnt <= 0)
        {
            outstr = sstr.str();
            return outstr;
        }

        sstr << setw(7) << ( int ) rpos << "  ";

        cnt2 = 0;
        for ( n = 0; n < 16; n++ )
        {
            cnt2 = cnt2 + 1;
            if ( cnt2 <= cnt )
            {
                sstr << hex << setw(2) << setfill ( '0' ) << 
                         (unsigned int)buffer[n];
            }
            else
            {
                    sstr << "  ";
            }
            sstr << " ";
        }

        sstr << setfill ( ' ' );

        sstr << " ";
        cnt2 = 0;
        for ( n = 0; n < 16; n++ )
        {
            cnt2 = cnt2 + 1;
            if ( cnt2 <= cnt )
            {
                if ( buffer[n] < 32 || 126 < buffer[n] )
                {
                    sstr << '.';
                }
                else
                {
                    sstr << buffer[n];
                }
            }
        }
        sstr << "\n";
        sstr << dec;
    }

    outstr = sstr.str();
    return outstr;
}

template <unsigned _buffer_size, unsigned _header_size>
class PacketBase
{
public:
    char *packet_buf(void)   {return m_strBuf;}
    unsigned packet_size(void)    {return m_nPacketSize;}
protected:
    PacketBase(void){}
    ~PacketBase(void){}
    enum
    {
        PACKET_HEADER_SIZE = _header_size,
        PACKET_BUFFER_SIZE = _buffer_size
    };
    unsigned  m_nPacketSize ; 
    unsigned  m_nBufPos;
    char m_strBuf[PACKET_BUFFER_SIZE];  

protected:
    ////////////////////////////////////////////////////////////////////////////////
    bool _copy(const void *pInBuf, unsigned nLen)
    {
        if(NULL==pInBuf || nLen > PACKET_BUFFER_SIZE){
            return false;
    }

    _reset();
    memcpy(m_strBuf, pInBuf, nLen);
    m_nPacketSize = nLen;
    return true;
}

////////////////////////////////////////////////////////////////////////////////
void _begin(short nCmdType, short cVersion)
{
    _reset();
    _writeHeader("ES", sizeof(char)*2, 0);

    short cmdType = htons(nCmdType);
    _writeHeader((char*)&cmdType, sizeof(short), 2);
    
    short version = htons(cVersion);
    _writeHeader((char*)&version, sizeof(short), 4);      
}

void _SetBegin(short nCmdType)
{
    short cmdType = htons(nCmdType);
    _writeHeader((char*)&cmdType, sizeof(short), 2);
}
public:
short GetCmdType(void)
{
    short nCmdType;
    _readHeader((char*)&nCmdType, sizeof(short), 2);
    return ntohs(nCmdType);
}
short GetVersion(void)
{
    short c;
    _readHeader((char *)&c, sizeof(short), 4);     
    return ntohs(c);
}
short GetBodyLength(void)
{
    short nLen;
    _readHeader((char*)&nLen, sizeof(short), 6);   
    return ntohs(nLen);
}

protected:
void _end(unsigned   *sequence*   = 0)
{
    short nBody = m_nPacketSize - PACKET_HEADER_SIZE;
    short bodyLen = htons(nBody);
    _writeHeader((char*)&bodyLen, sizeof(short), 6);    
}
    
void _reset(void)
{
    memset(m_strBuf, 0, PACKET_BUFFER_SIZE);
    m_nBufPos = PACKET_HEADER_SIZE;
    m_nPacketSize = PACKET_HEADER_SIZE;
}
   
bool _Read(char *pOut, unsigned nLen)
{
    if((nLen + m_nBufPos) > m_nPacketSize )
        return false ;
    memcpy(pOut, m_strBuf + m_nBufPos, nLen);
    m_nBufPos += nLen;
    return true;
}
  
bool _ReadDel(char *pOut, unsigned nLen)
{
    if(!_Read(pOut, nLen)){
        return false;
    }
    memcpy(m_strBuf + m_nBufPos - nLen, m_strBuf + 
             m_nBufPos, PACKET_BUFFER_SIZE - m_nBufPos);
    m_nBufPos -= nLen;
    m_nPacketSize -= nLen;
    _end();
    return true;
}
  
void _readundo(unsigned nLen)
{
    m_nBufPos -= nLen;
}
  
char *_readpoint(unsigned nLen)   
{
    if((nLen + m_nBufPos) > m_nPacketSize){
        return NULL; 
    }
    char *p = &m_strBuf[m_nBufPos];
    m_nBufPos += nLen;
    return p;
}

bool _Write(const char *pIn, unsigned nLen)
{
    if( (nLen + m_nPacketSize) > PACKET_BUFFER_SIZE){
        return false ;
    }
    memcpy(m_strBuf+m_nPacketSize, pIn, nLen);
    m_nPacketSize += nLen;
    return true;
}

bool _Insert(const char *pIn, unsigned nLen)
{
    if((nLen + m_nPacketSize) > PACKET_BUFFER_SIZE){
        return false;
    }
    memcpy(m_strBuf+PACKET_HEADER_SIZE+nLen, 
      m_strBuf+PACKET_HEADER_SIZE, m_nPacketSize-PACKET_HEADER_SIZE);
    memcpy(m_strBuf+PACKET_HEADER_SIZE, pIn, nLen);
    m_nPacketSize += nLen;
    _end();
    return true;
}

bool _writezero(void)
{
    if((m_nPacketSize + 1) > PACKET_BUFFER_SIZE){
        return false ;
    }
    memset(m_strBuf+m_nPacketSize, '\0', sizeof(char)) ;
    m_nPacketSize ++;
    return true;
}

void _readHeader(char *pOut, unsigned nLen, unsigned nPos)
{
    if( nPos+nLen <= PACKET_HEADER_SIZE)
    {
        memcpy(pOut, m_strBuf+nPos, nLen) ;
    }
}

void _writeHeader(char *pIn, unsigned nLen, unsigned nPos)
    {
        if( nPos+nLen <= PACKET_HEADER_SIZE)
        {
            memcpy(m_strBuf+nPos, pIn, nLen) ;
        }
    }
};

template <unsigned BUFFER_SIZE, unsigned HEADER_SIZE=PROTOL_HEADER_SIZE>
class InputPacket: public PacketBase<BUFFER_SIZE, HEADER_SIZE>
{
public:
    typedef PacketBase<BUFFER_SIZE, HEADER_SIZE> base;

    int ReadInt(void)
    {
        int nValue = -1; 
        base::_Read((char*)&nValue, sizeof(int)); 
        return ntohl(nValue);
    } 

    short ReadShort(void)
    {
        short nValue = -1; 
        base::_Read((char*)&nValue, sizeof(short)); 
        return ntohs(nValue);
    }

    BYTE ReadByte(void)
    {
        BYTE nValue = -1; 
        base::_Read((char*)&nValue, sizeof(BYTE)); 
        return nValue;
    }

    int64_t ReadInt64(void)
    {
        int64_t nValue = -1; 
        base::_Read((char*)&nValue, sizeof(int64_t));
        return ntohll(nValue);
    }

    bool ReadString(char *pOutString, unsigned nMaxLen)
    {
        int nLen = ReadInt();
        if(nLen == -1){    
            return false;
        }
        if(nLen > nMaxLen || nLen+base::m_nBufPos>base::m_nPacketSize )
        {
            base::_readundo(sizeof(unsigned));
            return false;
        }
        return base::_Read(pOutString, nLen);
    }

    char *ReadChar(void)
    {
        unsigned nLen = ReadInt();
        if(nLen == (unsigned)-1 || nLen+base::m_nBufPos>base::m_nPacketSize) {
            base::_readundo(sizeof(unsigned));
            return NULL;
        }
        return base::_readpoint(nLen);
    }



    bool ReadString(string &str)
    {
        char *p = ReadChar();
        str =  (p == NULL ? "" : p);
        return p != NULL;
    }

    int ReadBinary(char *pBuf, unsigned nMaxLen)
    {
        unsigned nLen = ReadInt();
        if(nLen == (unsigned)-1 || nLen > nMaxLen || 
                  nLen+base::m_nBufPos>base::m_nPacketSize )
        {
            base::_readundo(sizeof(unsigned));
            return -1;
        }
        if(base::_Read(pBuf, nLen)){
            return nLen ;
        }
        return 0;
    } 
    void Reset(void)
    {
        base::_reset();
    }
    bool Copy(const void *pInBuf, unsigned nLen)
    {
        return base::_copy(pInBuf, nLen);
    }
};

template <unsigned BUFFER_SIZE, unsigned HEADER_SIZE=PROTOL_HEADER_SIZE>
class OutputPacket: public PacketBase<BUFFER_SIZE, HEADER_SIZE>
{
public:
    OutputPacket(void){}
public:
    typedef PacketBase<BUFFER_SIZE, HEADER_SIZE> base;

    bool WriteInt(int nValue)
    {
        int value = htonl(nValue);
        return base::_Write((char*)&value, sizeof(int));
    }

    bool WriteInt64(int64_t nValue)     
    {
        int64_t value = htonll(nValue);
        return base::_Write((char*)&value, sizeof(int64_t));
    }

    bool WriteByte(BYTE nValue)     
    {
        return base::_Write((char*)&nValue, sizeof(BYTE));
    }

    bool WriteShort(short nValue)
    {
        short value = htons(nValue);
        return base::_Write((char*)&value, sizeof(short));
    }

    bool InsertInt(int nValue)
    {
        int value = htonl(nValue);
        return base::_Insert((char*)&value, sizeof(int));
    }

    bool InsertByte(BYTE nValue)    
    {
        return base::_Insert((char*)&nValue, sizeof(BYTE));
    }

    bool WriteString(const char *pString)
    {
        int nLen = (int)strlen(pString) ;
        WriteInt(nLen + 1) ;
        return base::_Write(pString, nLen) && base::_writezero();
    }

    bool WriteString(const string &strDate)
    {
        int nLen = strDate.size();
        WriteInt(nLen + 1) ;
        return base::_Write(strDate.c_str(), nLen) && base::_writezero();
    }

    bool WriteBinary(const char *pBuf, unsigned nLen)
    {
        WriteInt(nLen) ;
        return base::_Write(pBuf, nLen) ;
    }

    bool Copy(const void *pInBuf, unsigned nLen)
    {
        return base::_copy(pInBuf, nLen);
    }
    void Begin(short nCommand, char cVersion = SERVER_PACEKTVER)
    {
        base::_begin(nCommand, cVersion);
    }
    void End(void)
    {
        base::_end();
    }
   
    void SetBegin(short nCommand)
    {
        base::_SetBegin(nCommand);
    }
};

typedef InputPacket<ES_TCP_MAX_BUFFER>   ESInputPacket;
typedef OutputPacket<ES_TCP_MAX_BUFFER>  ESOutputPacket;

And this is for memcache:

C++
#include "ESMemcache.h"
using namespace std;

ESMemcache::ESMemcache(void)
{
}

ESMemcache::~ESMemcache(void)
{
}

int ESMemcache::setTimeOut(int msec)
{
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, msec);
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, msec);
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, msec);
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, -1);
    return 0;
}

bool ESMemcache::Init(char* pIPPort, int msec)
{
    memc = memcached_create(NULL);
    int nPort = 0;
    char * pszPort = strchr(pIPPort, ':');
    if (pszPort) {
        nPort = atoi(pszPort + 1);
        *pszPort = 0;
    }
    setTimeOut(msec);
    rc = memcached_server_add(memc, pIPPort, nPort);
    if(rc != MEMCACHED_SUCCESS)
        return false;
    return rc == MEMCACHED_SUCCESS;
}

bool ESMemcache::SetRecord(char* key, const char* value, 
     const size_t bytes, const time_t expire)
{
    rc = memcached_set(memc, key, strlen(key), value, bytes, expire, 0);
    return rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED;
}

bool ESMemcache::Replace(char* key, const char* value, const size_t bytes, const time_t expire)
{
    rc = memcached_replace(memc, key, strlen(key), value, bytes, expire, 0);
    return rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED;
}

void ESMemcache::GetRecord(const char* key, std::string &value)
{
    size_t value_length = 0;
    uint32_t flags = 0;
    char *val = memcached_get(memc, key, strlen(key), &value_length, &flags, &rc);
    if(val !=NULL)
    {
        value = val;
        free(val);
    }
    else
    {
        value.clear();
    }
}

bool ESMemcache::DeleteRecord(const char* key)
{
    rc = memcached_delete(memc, key, strlen(key), 0);
    return rc == MEMCACHED_SUCCESS;
}

bool ESMemcache::Increment(const char *key, int offset, uint64_t &value)
{
    rc = memcached_increment(memc, key, strlen(key), offset, &value);
    return rc == MEMCACHED_SUCCESS;
}

bool ESMemcache::Decrement(const char *key, int offset, uint64_t &value)
{
    rc = memcached_decrement(memc, key, strlen(key), offset, &value);
    return rc == MEMCACHED_SUCCESS;
}

bool ESMemcache::IsKeyExist(const char *key)
{
    size_t value_length = 0;
    uint32_t flags = 0;
    memcached_get(memc, key, strlen(key), &value_length, &flags, &rc);
    if (rc == MEMCACHED_NOTFOUND) {
        return false;
    }
    return true;
}

Some game logic:

C++
#pragma once
#include "PokerGlobal.h"
class CPokerHands
{
public:
    CPokerHands(void)
    {
        Initialize();
    };
private:
    POKERCARD m_Cards[TOTAL_OF_CARDS];
    POKERCARD *m_pHands;
    SAME_CARDS_COUNT m_SameCards[3];
    UCHAR m_ColorCount[4];
    UCHAR m_nFlushColor;
    UCHAR m_nSameCount;
    UCHAR m_nPairCount ; 
    UCHAR m_nThreeKindCount;
    UCHAR m_nTypeHands ;
public:

    int GetHandsType(void) {return m_nTypeHands;};
    void CheckHandsType(POKERCARD *pHand)
    {
        assert(m_Cards[0].p_card != 0);
        m_pHands = pHand;
    } 
    void Initialize(void)
    {
        m_pHands = NULL;

        memset(m_Cards, 0, sizeof(m_Cards));
        memset(m_ColorCount, 0, sizeof(m_ColorCount));
        memset(m_SameCards, 0, sizeof(m_SameCards));
    }

    void SetHands(USHORT c1, USHORT c2, USHORT *pBoardCard)
    {
        m_Cards[0].p_card = c1; 
        m_Cards[1].p_card = c2;
        m_Cards[2].p_card = pBoardCard[0];
        m_Cards[3].p_card = pBoardCard[1];
        m_Cards[4].p_card = pBoardCard[2];
        m_Cards[5].p_card = pBoardCard[3];
        m_Cards[6].p_card = pBoardCard[4];
    }
    void SetHands(UCHAR *hands)
    {
        for(int i = 0; i < TOTAL_OF_CARDS; i ++)
        {
            m_Cards[i].p_color = hands[i*2];
            m_Cards[i].p_value = hands[i*2+1];

            assert(m_Cards[i].p_value >= 2 && m_Cards[i].p_value <= 14);
            assert(m_Cards[i].p_color >= 1 && m_Cards[i].p_color <= 4);
        }
    }
private:

    void SortCards(void)
    {
        USHORT temp, max;
        for(int i = 0; i < TOTAL_OF_CARDS; i ++)
        {
            max = i;
            for(int j = i + 1; j < TOTAL_OF_CARDS; j ++)
            { 
                if((m_Cards[j].p_value > m_Cards[max].p_value))
                    max = j;
                if(m_nFlushColor != 0 && m_Cards[j].p_value == m_Cards[max].p_value
                        && m_Cards[j].p_color==m_nFlushColor)
                    max = j;
            }
            if(max != i)
            {
                temp = m_Cards[i].p_card;
                m_Cards[i].p_card = m_Cards[max].p_card;
                m_Cards[max].p_card = temp;
            }
        }
    }

    void CountFlush(void)
    {
        for(int i = 0; i < TOTAL_OF_CARDS; i ++)
        {
            if(++m_ColorCount[m_Cards[i].p_color-1] >= TOTAL_OF_HANDS)
            {
                m_nFlushColor = m_Cards[i].p_color;
            }
        }
    }

    void CountSameCards(void)
    {
        int i, nCount = 0;
        UCHAR start = 0;

        for(i = 1; i < TOTAL_OF_CARDS; i ++)
        {
            if(nCount == 0)
            {
                nCount = 1;
                start = m_Cards[i-1].p_value;
            }
            if(start == m_Cards[i].p_value)
                nCount++;
            else
            {
                if(nCount >= 2)
                    set_same_cards(i, nCount);
                nCount = 0;
            }
        }
    if(nCount >= 2)
        set_same_cards(i, nCount);
}

void set_same_cards(int nPos, int nCount)
{
    m_SameCards[m_nSameCount].count = nCount;
    switch(nCount)
    {
        case 2:
            break;
        case 3:
            break;
    };
}

int IsStraight(bool bFlush = true)
{
    int i = 0, nCount = 0 ;
    UCHAR pos = 0;
    while(i ++ < TOTAL_OF_CARDS-1)
    {
        if(nCount == 0)
        {
            if(bFlush && m_Cards[i-1].p_color != m_nFlushColor)
            nCount = 1;
            pos = m_Cards[i-1].p_value;
        }
        continue;

        if(pos == m_Cards[i].p_value + nCount)
        {
            if(++nCount == 4 && pos == 5 && m_Cards[0].p_value == 14)
            {
                if(!bFlush || m_Cards[0].p_color == m_nFlushColor)
                    return 100 + i;
            }
            if(nCount >= TOTAL_OF_HANDS) return i;
        }else
        {
            if(m_Cards[i].p_value != m_Cards[i-1].p_value)
                nCount = 0;
        }
    }
    return -1;
}
private:

void FilterStraight(int nPos, bool bFlush = true)
{
    if(nPos > 100)
    {
        nPos -= 100;
        int nAcePos = 0;
        {
            for(int i = 0; i < 2; i ++)
            {
                if(m_Cards[i].p_color == m_nFlushColor)
                {
                    nAcePos = i;
                    break;
                }
            }
        }
        m_pHands[handpos--].p_card = m_Cards[nAcePos].p_card;
    }
    while(handpos >= 0)
    {
        {
            {
                nPos --; 
                continue;
            }
            {
                if(handpos < TOTAL_OF_HANDS - 1 &&
                    m_pHands[handpos+1].p_value == m_Cards[nPos].p_value)
                {
                    nPos --;
                    continue;
                }
            }
            m_pHands[handpos--].p_card = m_Cards[nPos--].p_card;
        }
        if(bFlush && m_pHands[0].p_value == 14)
            m_nTypeHands = TYPE_ROYAL_FLUSH;
}
void FilterFourCard(int nPos)
{
    m_pHands[0].p_card = m_Cards[nPos].p_card ;
    m_pHands[1].p_card = m_Cards[nPos+1].p_card ;
    m_pHands[2].p_card = m_Cards[nPos+2].p_card ;
    m_pHands[3].p_card = m_Cards[nPos+3].p_card ;

    nPos = nPos == 0 ? 4 : 0;
    m_pHands[4].p_card = m_Cards[nPos].p_card;
}

void FilterFirstThreeCard(void)
{
    int nPos = -1;
    for(int i = 0; i < m_nSameCount; i ++)
    {
        if(m_SameCards[i].count == 3)
        {
            nPos = m_SameCards[i].pos;
            break;
        }
    }
    assert(nPos != -1);
    for(int i = 0; i < 3; i ++)
    m_pHands[i].p_card = m_Cards[nPos+i].p_card;
}

void FilterFullHouse(void)
{
    int nPos = 0;
    FilterFirstThreeCard();

    if(m_nThreeKindCount > 1)
    {
        nPos = m_SameCards[1].pos;
        m_pHands[3].p_card = m_Cards[nPos].p_card;
        m_pHands[4].p_card = m_Cards[nPos+1].p_card;
    }else
    {
        for(int i = 0; i < m_nSameCount; i ++)
        {
            if(m_SameCards[i].count == 2)
            {
                nPos = m_SameCards[i].pos;
                break;
            }
        }
        m_pHands[3].p_card = m_Cards[nPos].p_card;
        m_pHands[4].p_card = m_Cards[nPos+1].p_card;
    }
}

void FilterFlush(void)
{
    int nPos = 0;
    for(int i = 0; i < TOTAL_OF_CARDS && nPos < TOTAL_OF_HANDS; i ++)
        if(m_Cards[i].p_color == m_nFlushColor)
            m_pHands[nPos++].p_card = m_Cards[i].p_card;
}

void FilterThreeCard(void)
{
    FilterFirstThreeCard();

    UCHAR ch = m_pHands[0].p_value;
    for(int i = 0, n = 3; i < TOTAL_OF_CARDS && n < TOTAL_OF_HANDS; i ++)
        if(ch != m_Cards[i].p_value)
            m_pHands[n++].p_card = m_Cards[i].p_card; 
}

void FilterTwoPair(void)
{
    assert(m_SameCards[0].count == 2);
    assert(m_SameCards[1].count == 2);

    int nPos = m_SameCards[0].pos;
    m_pHands[0].p_card = m_Cards[nPos].p_card;
    m_pHands[1].p_card = m_Cards[nPos+1].p_card;

    nPos = m_SameCards[1].pos;
    m_pHands[2].p_card = m_Cards[nPos].p_card;
    m_pHands[3].p_card = m_Cards[nPos+1].p_card;

    for(int i = 0; i < TOTAL_OF_CARDS; i ++)
    {
        if(m_Cards[i].p_value != m_pHands[0].p_value && m_Cards[i].p_value != m_pHands[2].p_value)
        {
            m_pHands[4].p_card = m_Cards[i].p_card;
            break;
        }
    }
}

void FilterPair(void)
{
    assert(m_SameCards[0].count == 2);
    int nPos = m_SameCards[0].pos;
    m_pHands[0].p_card = m_Cards[nPos].p_card;
    m_pHands[1].p_card = m_Cards[nPos+1].p_card;

    for(int i = 0, n = 2; i < TOTAL_OF_CARDS && n < TOTAL_OF_HANDS; i ++)
    {
        if(m_Cards[i].p_value != m_pHands[0].p_value)
            m_pHands[n++].p_card = m_Cards[i].p_card;
    }
}
void FilterHighCard(void)
{
    for(int i = 0; i < TOTAL_OF_HANDS; i ++)
        m_pHands[i].p_card = m_Cards[i].p_card;

    if(m_pHands[0].p_value < 11)
        m_nTypeHands = TYPE_PIE_CARD;
}
private:

bool CheckStraightFlush(void)
{
    if(m_nFlushColor == 0)
        return false;

    int nPos = IsStraight(true);
    if(nPos != -1)
    {
        m_nTypeHands = TYPE_STRAIGHT_FLUSH;
        FilterStraight(nPos, true);
        return true;
    }
    return false;
}

bool CheckFourCard(void)
{
    for(int i = 0; i < m_nSameCount; i ++)
    {
        if(m_SameCards[i].count == 4)
        {
            m_nTypeHands = TYPE_FOUR_KIND;
            return true;
        }
    }
    return false;
}

bool CheckFullHouse(void)
{
    if(m_nThreeKindCount < 1)
    if(m_nThreeKindCount == 1 && m_nPairCount < 1)

    m_nTypeHands = TYPE_FULL_HOUSE;
    FilterFullHouse();
    return true;
}

bool CheckFlush(void)
{
    if(m_nFlushColor == 0)
        return false;
    m_nTypeHands = TYPE_FLUSH;
    FilterFlush();

    return true;
}

bool CheckStraight(void)
{
    int nPos = IsStraight(false);
    if(nPos != -1)
    {
        m_nTypeHands = TYPE_STRAIGHT;
        FilterStraight(nPos, false);
        return true;
    }
    return false;
}
bool CheckThreeCard(void)
{
    if(m_nThreeKindCount < 1)
        return false;

    m_nTypeHands = TYPE_THREE_KIND;
    FilterThreeCard();

    return true;
}

bool CheckTwoPair(void)
{
    if(m_nPairCount < 2)
        return false;

    m_nTypeHands = TYPE_TWO_PAIRS;
    FilterTwoPair();

    return true;
}

bool CheckPair(void)
{
    if(m_nPairCount < 1)
        return false;

    m_nTypeHands = TYPE_PAIR;
    FilterPair();

    return true;
}

bool CheckHighCard(void)
{
    m_nTypeHands = TYPE_HIGH_CARD;
    FilterHighCard();

    return true;
}  
};

If you are interested in it, you can download the attachment.

Points of Interest

If I add an adoptor, this API can work with almost no SQL. That is cool.

History  

Alpha version.  

Todo  

  • An adopter 
  • Auto serialization and deserialization  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)