Click here to Skip to main content
Click here to Skip to main content

Encapsulate a memcache for Texas Hold’em

, 15 Jul 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
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:

#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:

#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:

#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)

Share

About the Author

skydirve

United States United States
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150331.1 | Last Updated 15 Jul 2013
Article Copyright 2013 by skydirve
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid