1. 程式人生 > >檢測四川麻將是否胡牌演算法的實現

檢測四川麻將是否胡牌演算法的實現

自己寫了一個四川麻將胡牌的演算法,加入有兩組牌讓你判定是否胡牌,就只是最簡單的那種胡法,非常不完善。

其中char *as1 = "1W1W2T2D3W3W5W5W7W7W8W8W9W9W";  char *as2 = "1W1W1W2W3W4W4W5W6W7W8W9W9W9W";

主要思想是:

1)給牌分組,並排序;檢查是否打缺了,只有缺了一門才能胡牌哦;

在排序的時候一定是有14張牌(否則可能就是小相公哦,呵呵……)

for (i=0; i<28; i++)//
 {
  if(*(Cards + i) == 'D')
  {
   pb[b++] = *(Cards + i -1);
  }

  if(*(Cards + i) == 'T')
  {
   pt[t++] = *(Cards + i -1);
  }

  if(*(Cards + i) == 'W')
  {
   pw[w++] = *(Cards + i -1); 
  }
 }
 if(b != 0 && t !=0 && w != 0)
 {
  printf("\n慘了,還沒打缺呢……\n");
  return false;
 }
 sort(pb,b);
 sort(pt,t);
 sort(pw,w);

2)找找看對子在哪裡,再開始三三組合

bool Group( char *pp,int n)
{
 char q[14];
 char r;
 int i,j,k=0;
 r = '0';
 for (i = 0;i < n;i++)
 {
  q[i] = *(pp + i);
 }
 if (n == 0)
 {
  return true;
 }
 else if(n%3 == 2)              //必定存在一對對子
 {
  for (i = k;i<n-1; i++)
  {
   if (*(q + i) == *(q + i + 1) && *(q + i) != r)     //找對子,並剔除對子
   {  
    r = *(q + i);
    for (j = i; j < n - 2; j++)
    {
     *(q + j) = *( q + j + 2);        //所有元素左移兩位
    }
    *(q + j) = '\0';
    
    i--;
    k = i;

    if(Group3S(q,n-2))           //某一花色組合正確
    {
     return true;
    }
    for (j = 0;j < n;j++)
    {
     q[j] = *(pp + j);          //恢復原來的陣列,並進行下一輪對子的選擇
    }
   }                //找出對子,並剔除,在剩餘的12張牌中進行組合
  }
 }
 else                 //沒有對子,只能是三個三個一組(三個相同或者順子)
 {
  if(Group3S(q,n))
  {
   return true;             //某一花色組合正確
  }
 }
 return false;   //輸了  
}

3)如何判斷某一花色組合正確。
遞迴呼叫組合函式Group3S,每次先進行順子組合,若不能成功,再進行三個相同的組合
找到一組三個相同的組合,在遞迴呼叫本函式,不斷的進行順子-三個相同 順子-三個相同
遞迴的次數不會超過四次,因為只有12張牌,每一次找到三個相同的牌,都會減少三張牌實現程式碼如下:

 bool Group3S(char *p, int n)
{
 char pp[14],p2[14];
 int i,j;

 for (i = 0;i < n;i++)
 {
  pp[i] = *(p + i);
  p2[i] = *(p + i);
 }
 bool flag = false;
 if (n == 0)
 {
  return true;
 }
 if(!Group3Shunzi(p,n))
  return true;
 if (Group3Same(p2,n))               //順子出錯,就看看有沒有三個相同的,有就把三個相同的挑出來,在進行順子演算法
 {
  n -= 3;
  flag = Group3S(p2,n);
 }
 return flag;
}

4)找出順子,每找到一組順子就把順子剔除,最後,返回陣列中剩餘的元素的個數,如果返回值為0,
能夠組合成若干個順子,可以胡牌,否則,不能組合成順子,不能胡牌該演算法的核心演算法程式碼如下:

int Group3Shunzi(char *p,int n)
{

char *q,*w;
 int i,j,k,m,l,sp = 0;
 m=0;
 q = p;
 w = p;
 if ( n == 0)
 {
  return 0;
 } for(i = 0; i < n - 2; i++)
 {
  for (j = i+1;j < n - 1; j++ )
  {
   if (*(q + j) - *(q + i) == 1)
   {
    for (k = j + 1; k < n ; k++ )
    {
     if (*(q + k) - *(q + j) == 1)
     {

      if (i == n - 3 )          //把這三個元素移除,把後面的元素往前移動三格
      {
       *(q+i) = '\0';
       n -= 3;
       i--;
       break;    
      } 
      else
      {
       *(q + i) = '0';
       *(q + j) = '0';
       *(q + k) = '0';
       for (m = 0,l = 0;l < n ; l++)
       {
        if (*(q + l) != '0')
        {
         *(w + (m++)) = *(q + l);
        }
       }
       n = m;
       q = w;
       i--;
       break;
      } 
     }
    }
   }
   continue;
  }
 }
 return  n;
}

5)找出相同的三個連續的牌,如果找到就剔除這三個牌,並返回真,傳遞進來的陣列元素比原來少了3個如果沒有,返回假

bool Group3Same(char *p,int n)
{

 char * q;
 int sp=0;
 int i,j;
 q = p;
 if (n == 0)
 {
  return true;
 }
 for(i = 0; i < n - 2; i++)
 {
  if (*(q + i + 1) == *(q + i)&& *(q + i + 2) == *(q + i + 1))
  { 
   if (i == n - 3 )            //把這三個元素移除,把後面的元素往前移動三格
   {
    *(q+i) = '\0';
    p = q;
    return true;
   } 
   else
   {
    for (j = i;j < n - 3; j++)
    {
     *(q + j)  =  *(q + j + 3) ; 
    }
    *(q+j) = '\0';
    p = q;
    return true;
   }
  }
 }
 return false;
}

這是我自己想的一個辦法,如果你覺得哪裡不對或者是有更多好辦法,可以教教我,呵呵……