⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hand.cpp

📁 上面上传的autotools一文(也就是《使用GNU autotools 改造一个软件项目》)配套的示例程序源代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
      if (tmp.GoMahjong_real()) {
         *this = tmp;
         return true;
      }
   }

   tmp = *this;
   if (tmp.Chow(t, CHOW_UPPER, true, HT_RON)) {
      if (tmp.GoMahjong_real()) {
         *this = tmp;
         return true;
      }
   }

   tmp = *this;
   if (tmp.Chow(t, CHOW_MIDDLE, true, HT_RON)) {
      if (tmp.GoMahjong_real()) {
         *this = tmp;
         return true;
      }
   }

   tmp = *this;
   for (int j = 0; j < m_iNumTiles; j++) {
      if (m_Tiles[j].flags & (HT_LOCKED | HT_TOCHOW))
         continue;
      if (m_Tiles[j].tile == t) {
         tmp.AddTile(t, HT_PAIR | HT_RON | HT_FROMOPPONENT, tmp.m_iNumTileSets);
         tmp.m_Tiles[j].flags |= (HT_PAIR | HT_RON);
         tmp.m_Tiles[j].tileset = tmp.m_iNumTileSets;

         // Add this pair to the tileset
         tmp.m_TileSets[tmp.m_iNumTileSets].first = tmp.m_Tiles[j].tile;
         tmp.m_TileSets[tmp.m_iNumTileSets].type = (HT_PAIR | HT_RON);
         tmp.m_iNumTileSets++;

         if (tmp.GoMahjong_real()) {
            *this = tmp;
            return true;
         }

         break;
      }
   }

   // If all above fail, check if we have Thirteen Unique
   // Wonders or Seven Pairs...
   tmp = *this;
   tmp.AddTile(t, HT_FROMOPPONENT);

   if (tmp.ThirteenWonders()) {
      *this = tmp;
      return true;
   }

   if (tmp.SevenPairs()) {
      *this = tmp;
      return true;
   }

   return false; // does NOT have a Mahjong
}

// Check if we have "Thirteen Unique Wonders" special hand.
bool CHand::ThirteenWonders()
{
   const CTile ttw[] = {"1C", "9C", "1D", "9D", "1B", "9B",
      "EW", "SW", "WW", "NW", "RD", "GD", "WD"};

   bool havetwo = false;

   int i, j;

   // first check if all the tiles are majors...
   for (j = 0; j < m_iNumTiles; j++) {
      if (!m_Tiles[j].tile.IsMajor())
         return false; // we have minors; fail
   }

   for (i = 0; i < 13; i++) {
      int count = 0;
      for (j = 0; j < m_iNumTiles; j++) {
         if (m_Tiles[j].tile == ttw[i]) {
            count++;
         }
      }

      if (count <= 0 || count > 2) {
         return false; // we have 3 or more same tiles; fail
      }

      if (count == 2) {
         if (havetwo) {
            return false;
         }
         havetwo = true;
      }
   }

   // MUST have one pair
   if (havetwo) {
      // Success. Set the "Thirteen Wonders" flag to all tiles
      for (i = 0; i < m_iNumTiles; i++) {
         m_Tiles[i].flags |= HT_THIRTEENWONDERS;
      }
      return true;
   }

   return false; // fail!
}

// Check if we have "Seven Pairs" special hand.
bool CHand::SevenPairs()
{
   if (m_iNumTiles <= 0)
      return true;

   if (m_iNumTileSets > 0)
      return false; // non-concealed hand is not possible

   CHand tmp = *this;
   CTile t = m_Tiles[0].tile;

   // three or more same tiles is not allowed!
   if (tmp.Pung(t, false))
      return false;

   tmp.RemoveTile(t);
   if (tmp.RemoveTile(t)) {
      if (tmp.SevenPairs()) {
         // FIXME: add the seven pairs to the tileset?
         for (int i = 0; i < m_iNumTiles; i++) {
            m_Tiles[i].flags |= HT_PAIR;
         }
         return true;
      }
   }

   return false;
}

// Return true if the hand in its current state of
// organization is a ready hand.
// (That is, we only need one more tile to go mah-jong.)
bool CHand::IsReady()
{
   int i, concealed = 0;
   CTile t[MAX_HANDTILE];

   for (i = 0; i < m_iNumTiles; i++) {
      if (m_Tiles[i].flags & (HT_LOCKED | HT_TOCHOW))
         continue; // skip locked tiles

      CHand tmp;

      tmp = *this;
      if (tmp.Pung(m_Tiles[i].tile, false)) {
         if (tmp.IsReady()) {
            return true;
         }
      }

      tmp = *this;
      if (tmp.Chow(m_Tiles[i].tile, CHOW_LOWER, false)) {
         if (tmp.IsReady()) {
            return true;
         }
      }

      t[concealed++] = m_Tiles[i].tile;
   }

   if (concealed == 1) {
      // only 1 tile remaining; can form a pair with another tile
      return true;
   } else if (concealed == 4) {
      // check if we have 1 pair and another 2 tiles which can
      // form a chew or pung with another tile.

      // search for a pair
      int m, n, other[2], count = 0;

      for (m = 0; m < 4; m++) {
         for (n = m + 1; n < 4; n++) {
            if (m == n)
               continue;
            if (t[m] == t[n]) {
               break; // we've found the pair
            }
         }
         if (n < 4)
            break; // break out if we've already found the pair
      }

      if (m >= 4 || n >= 4)
         return false; // no pair found; fail

      for (i = 0; i < 4; i++) {
         if (i != m && i != n) {
            assert(count < 2);
            other[count++] = i;
         }
      }
      assert(count == 2);

      // If the other 2 tiles are not of the same suit...
      if (t[other[0]].GetSuit() != t[other[1]].GetSuit())
         return false; // fail!

      int d = abs(t[other[0]].GetValue() - t[other[1]].GetValue());
      return (d >= 0 && d < 3);
   }

   if (IsThirteenWondersReady())
      return true;

   if (IsSevenPairsReady())
      return true;

   return false; // does NOT have a Ready Hand
}

bool CHand::IsThirteenWondersReady()
{
   const CTile ttw[] = {"1C", "9C", "1D", "9D", "1B", "9B",
      "EW", "SW", "WW", "NW", "RD", "GD", "WD"};

   bool havetwo = false;

   int i, j;

   // first check if all the tiles are majors...
   for (j = 0; j < m_iNumTiles; j++) {
      if (!m_Tiles[j].tile.IsMajor())
         return false; // we have minors; fail
   }

   for (i = 0; i < 13; i++) {
      int count = 0;
      for (j = 0; j < m_iNumTiles; j++) {
         if (m_Tiles[j].tile == ttw[i]) {
            count++;
         }
      }

      if (count > 2) {
         return false; // we have 3 or more same tiles; fail
      } else if (count == 2) {
         if (havetwo) {
            return false;
         }
         havetwo = true;
      }
   }

   return true; // Success.
}

bool CHand::IsSevenPairsReady()
{
   if (m_iNumTiles <= 1)
      return true;

   if (m_iNumTileSets > 0)
      return false; // non-concealed hand is not possible

   CHand tmp = *this;
   CTile t = m_Tiles[0].tile;

   tmp.RemoveTile(t);
   if (tmp.RemoveTile(t)) {
      if (tmp.RemoveTile(t)) {
         // three or more same tiles is not allowed!
         return false;
      }
   } else {
      t = m_Tiles[1].tile;
      tmp = *this;
      tmp.RemoveTile(t);
      if (tmp.RemoveTile(t)) {
         if (tmp.RemoveTile(t)) {
            // three or more same tiles is not allowed!
            return false;
         }
      } else {
         return false; // 2 or more "orphaned" tiles are found
      }
   }

   return tmp.IsSevenPairsReady();
}

// Gets the waiting tiles, store it into the tiles array
// and returns the number of found waiting tiles.
int CHand::GetWaitingTile(CTile tiles[], int max)
{
   int current = 0;
   return GetWaitingTile(tiles, max, current);
}

// This is the real function to get the waiting tiles.
int CHand::GetWaitingTile(CTile tiles[], int max, int &current)
{
   int i, j, concealed = 0;
   CTile t[MAX_HANDTILE];

   for (i = 0; i < m_iNumTiles; i++) {
      if (m_Tiles[i].flags & (HT_LOCKED | HT_TOCHOW))
         continue; // skip locked tiles

      CHand tmp;

      tmp = *this;
      if (tmp.Pung(m_Tiles[i].tile, false)) {
         tmp.GetWaitingTile(tiles, max, current);
      }

      tmp = *this;
      if (tmp.Chow(m_Tiles[i].tile, CHOW_LOWER, false)) {
         tmp.GetWaitingTile(tiles, max, current);
      }

      t[concealed++] = m_Tiles[i].tile;
   }

   if (concealed == 1) {
      // only 1 tile remaining; can form a pair with another tile
      for (j = 0; j < current; j++) {
         if (tiles[j] == t[0])
            break;
      }
      if (j >= current) {
         if (current >= max) {
            fprintf(stderr, "CHand::GetWaitingTile(): current >= max!\n");
            return current;
         }
         tiles[current++] = t[0];
      }
   } else if (concealed == 4) {
      // check if we have 1 pair and another 2 tiles which can
      // form a chew or pung with another tile.

      // search for a pair
      int m, n, other[2], count = 0;

      for (m = 0; m < 4; m++) {
         for (n = m + 1; n < 4; n++) {
            if (m == n)
               continue;
            if (t[m] == t[n]) {
               break; // we've found the pair
            }
         }
         if (n < 4)
            break; // break out if we've already found the pair
      }

      if (m >= 4 || n >= 4)
         return current; // no pair found; fail

      for (i = 0; i < 4; i++) {
         if (i != m && i != n) {
            assert(count < 2);
            other[count++] = i;
         }
      }
      assert(count == 2);

      // If the other 2 tiles are not of the same suit...
      if (t[other[0]].GetSuit() != t[other[1]].GetSuit())
         return current; // fail!

      if (t[other[0]].GetValue() > t[other[1]].GetValue()) {
         int temp = other[0];
         other[0] = other[1];
         other[1] = temp;
      }

      int d = t[other[1]].GetValue() - t[other[0]].GetValue();
      assert(d >= 0);

      switch (d) {
      case 0:
         for (j = 0; j < current; j++) {
            if (tiles[j] == t[other[0]])
               break;
         }
         if (j >= current) {
            if (current >= max) {
               fprintf(stderr, "CHand::GetWaitingTile(): current >= max!\n");
               return current;
            }
            tiles[current++] = t[other[0]];
         }
         break;

      case 1:
         if (t[other[0]].GetSuit() & (TILESUIT_WIND | TILESUIT_DRAGON)) {
            break; // chow is impossible for Winds or Dragons
         }

         if (t[other[0]].GetValue() > 1) {
            for (j = 0; j < current; j++) {
               if (tiles[j] == t[other[0]]() - 1)
                  break;
            }
            if (j >= current) {
               if (current >= max) {
                  fprintf(stderr, "CHand::GetWaitingTile(): current >= max!\n");
                  return current;
               }
               tiles[current++] = t[other[0]]() - 1;
            }
         }

         if (t[other[1]].GetValue() < 9) {
            for (j = 0; j < current; j++) {
               if (tiles[j] == t[other[1]]() + 1)
                  break;
            }
            if (j >= current) {
               if (current >= max) {
                  fprintf(stderr, "CHand::GetWaitingTile(): current >= max!\n");
                  return current;
               }
               tiles[current++] = t[other[1]]() + 1;
            }
         }
         break;

      case 2:
         if (t[other[0]].GetSuit() & (TILESUIT_WIND | TILESUIT_DRAGON)) {
            break; // chow is impossible for Winds or Dragons
         }

         for (j = 0; j < current; j++) {
            if (tiles[j] == t[other[0]]() + 1)
               break;
         }
         if (j >= current) {
            if (current >= max) {
               fprintf(stderr, "CHand::GetWaitingTile(): current >= max!\n");
               return current;
            }
            tiles[current++] = t[other[0]]() + 1;
         }
         break;
      }
   }

   if (current <= 0) {
      GetThirteenWondersWaitingTile(tiles, max, current);
   }

   if (current <= 0) {
      GetSevenPairsWaitingTile(tiles, max, current);
   }

   return current;
}

int CHand::GetThirteenWondersWaitingTile(CTile tiles[], int max, int &current)
{
   const CTile ttw[] = {"1C", "9C", "1D", "9D", "1B", "9B",
      "EW", "SW", "WW", "NW", "RD", "GD", "WD"};

   int i, j, zero = -1;
   bool havetwo = false;

   // first check if all the tiles are majors...
   for (i = 0; i < m_iNumTiles; i++) {
      if (!m_Tiles[i].tile.IsMajor())
         return current; // we have minors; fail
   }

   for (i = 0; i < 13; i++) {
      int count = 0;
      for (j = 0; j < m_iNumTiles; j++) {
         if (m_Tiles[j].tile == ttw[i]) {
            count++;
         }
      }
      if (count > 2) {
         return current; // we have 3 or more same tiles; fail
      } else if (count == 2) {
         if (havetwo) {
            return current; // fail
         }
         havetwo = true;
      } else if (count == 0) {
         zero = i;
      }
   }

   if (!havetwo) {
      // we're waiting for ALL majors!
      for (i = 0; i < 13; i++) {
         if (current >= max) {
            fprintf(stderr, "CHand::GetThirteenWondersWaitingTile(): current >= max\n");
            return current;
         }
         tiles[current++] = ttw[i];
      }
   } else if (zero != -1) {
      if (current >= max) {
         fprintf(stderr, "CHand::GetThirteenWondersWaitingTile(): current >= max\n");
         return current;
      }
      tiles[current++] = ttw[zero];
   }

   return current; // success!
}

int CHand::GetSevenPairsWaitingTile(CTile tiles[], int max, int &current)
{
   assert(m_iNumTiles >= 1);

   if (m_iNumTiles == 1) {
      // We've got the wanted tile
      if (current >= max) {
         fprintf(stderr, "CHand::GetSevenPairsWaitingTile(): current >= max\n");
         return current;
      }
      tiles[current++] = m_Tiles[0].tile;
      return current;
   }

   if (m_iNumTileSets > 0)
      return current; // non-concealed hand is not possible

   CHand tmp = *this;
   CTile t = m_Tiles[0].tile;

   tmp.RemoveTile(t);
   if (tmp.RemoveTile(t)) {
      if (tmp.RemoveTile(t)) {
         return current; // three or more same tiles is not allowed!
      }
   } else {
      t = m_Tiles[1].tile;
      tmp = *this;
      tmp.RemoveTile(t);
      if (tmp.RemoveTile(t)) {
         if (tmp.RemoveTile(t)) {
            return current; // three or more same tiles is not allowed!
         }
      } else {
         return current; // 2 or more "orphaned" tiles are found
      }
   }

   return tmp.GetSevenPairsWaitingTile(tiles, max, current);
}

// Return true if the hand in its current state of
// organization is a concealed hand.
bool CHand::IsConcealed()
{
   for (int i = 0; i < m_iNumTileSets; i++) {
      if (m_TileSets[i].type & (HT_OPEN & ~HT_CLOSEDKONG)) {
         if (m_TileSets[i].type & HT_RON)
            continue;
         return false; // it is NOT a concealed hand
      }
   }
   return true; // it is a concealed hand
}

void CHand::Restore()
{
   int i, n = 0;
   const int flag = (HT_CLOSEDPUNG | HT_CLOSEDCHOW |
      HT_PAIR | HT_THIRTEENWONDERS);

   for (i = 0; i < m_iNumTiles; i++) {
      m_Tiles[i].flags &= ~flag;
   }

   for (i = 0; i < m_iNumTileSets; i++) {
      if (m_TileSets[i].type & flag)
         continue;
      m_TileSets[n++] = m_TileSets[i];
   }
   m_iNumTileSets = n;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -