UVA127 纸牌游戏

你的任务是模拟一种叫「Accordian」的纸牌游戏,他的游戏规则如下: 

一副扑克牌有52张牌,首先把纸牌一张一张由左到右排好(不能有重叠,所以共有52堆牌,每堆一张),当某一张牌与他左边那张牌或者左边的第三张牌有「Match」的时候,就把这张牌移到那张牌上面去。在这里两张牌「Match」指的是这两张牌的花色(suit)或者点数(rank)一样。当你做了一个移动之后,要察看是否还可以做其他的移动。在任何时间,只有最上面那张牌可以被移动。如果因为移动一张牌使得产生一个空格(也就是被移动的那堆牌只有一张牌),你必须把右边所有的牌堆往左移一格。如此不断的寻找可移动的牌,直到没有一张牌可以移动游戏就结束了。 

在选择可以移动的牌的时候可能有些状况会发生。如果有两张牌都可以移动,你应该要移动最左边的那张牌。当一张牌可以被移动到左边一格,或左边三格的时候,你必须移动到左边三格。 

Input 

输入包含多组测试资料。每组测试资料两列,每列有26张牌的资料。每张牌以2个字元代表。第一个字元代表牌的点数(A=Ace, 2~9, T=10, J=Jack, Q=Queen, K=King),第二个字元代表牌的花色(C=Clubs, D =Diamonds, H=Hearts, S=Spades) 

若遇到仅含#的一列代表输入结束。请参考Sample Input。 

Output 

对每组测试资料输出游戏结束时剩下几堆牌,以及每堆牌有多少张牌。请注意如果只有1堆牌,pile后没有加s,请参考Sample Output。 

代码:非链表法

#include <algorithm> 

#include <iostream> 

#include <string> 

#include <vector>

 using namespace std; 

//CARD结构体,存储一张牌,Face[0]表示花色,Face[1]表示点数

struct CARD 

{

char Face[2];

} Src; 

//比较两张牌是否匹配。花色或点数相同即匹配

inline bool Match(const CARD &c1, const CARD &c2)

 { 

 return (c1.Face[0] == c2.Face[0] || c1.Face[1] == c2.Face[1]); 

} 

int main(void) 

{ //主函数

 typedef vector<CARD> PILE; 

 char Pack[256]; //用于存储输入的一副牌,下面循环读取输入的数据

 for (string Line; getline(cin, Line) && Line[0] != '#'; cout << endl) 

{  

 strcpy(Pack, Line.c_str()); //读取并处理输入的数据

  while (getline(cin, Line) && Line.empty()); //读取第2行 

  strcat(Pack, Line.c_str()); 

  *remove(&Pack[0], &Pack[strlen(Pack)], ' ') = '\0'; //删除行中的空格 

  vector<PILE> Piles; 

  for (int i = 0; i < 52; ++i) 

{ //循环发出每一张牌  

  PILE Stack(1, ((CARD*)&Pack)[i]);

    Piles.push_back(Stack); //将新发的牌放在最后一叠   

 //j表示当前牌的位置,k表示j左边与之匹配的牌的位置    

for (size_t j = Piles.size() - 1, k; j < Piles.size(); ++j)

 {     //以下循环向左查找可以移到的最左边的位置   

  for (k = j, Src = Piles[j].back(); k > 0; --k)

 {   

   if (k >= 3)

 { //先判定左边是否存在第3张    

   if (Match(Src, Piles[k - 3].back())) 

{        //如果与左边第3张匹配,则将k指向这张牌   

     k -= 2;       

 continue;    

   }

 //虚拟移到k指向的位置,继续向左查找 

     }   

   if (!Match(Src, Piles[k - 1].back()))

 {      

 break; //如果左边第3张和第1张都失配,跳出循环

     }   

  }    

 if (k != j) 

{ //k与原位置j不相等表示可以移动   

   Piles[k].push_back(Piles[j].back()); //移动牌  

    Piles[j].pop_back(); 

     if (Piles[j].empty()) 

{ //如果牌叠被移空则删除之  

     Piles.erase(Piles.begin() + j);  

    }     

 j = k; //将移动牌查找的起点定为k 

    }  

  }   

}

 //以下按要求的格式输出结果。注意到Pile有单复数的区分  

 int nSize = Piles.size();  

 cout << nSize << " Pile" << (nSize > 1 ? "s " : " ") << "remaining:"; 

  for (i = 0; i < nSize; cout << ' ' << (Piles[i++]).size()); 

 }

  return 0;

 }

链表法:

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int N=55;
struct node
{
    char face;
    char suit;
};
vector< vector<node> > List;     
bool match(node a,node b)
{
      return a.face==b.face||a.suit==b.suit;
}
bool test()
{
     bool flag=false;
     int k,t;
     int s=List.size();
     for(int i=s-1;i>0;i--)
  {
         if(i-3>=0&&match(List[i].back(),List[i-3].back()))
   {
                k=i;
                t=3;
                flag=true;
         }               //根据题意,先往左边的第三个挪动
         else if(i-1>=0&&match(List[i].back(),List[i-1].back()))
   {
                k=i;
                t=1;
                flag=true;
         }       //在往左边挪动
     }
     if(flag)
  {
          List[k-t].push_back(List[k].back());
          List[k].pop_back();
          if(List[k].empty())
    {
               List.erase(List.begin()+k);//挪动后,如果该组空了,右边的都要往左边来挪动。
          } 
          return true;
     }
     return false;
}
//得到牌最后的位置
int main()
{
     node p;
     vector<node> l;
     while(cin>>p.face&&p.face!='#')
  {
           cin>>p.suit;
           l.clear();
           l.push_back(p);
           List.clear();
           List.push_back(l);
           for(int i=2;i<=52;i++)
     {
                cin>>p.face>>p.suit;
                l.pop_back();
                l.push_back(p);
                List.push_back(l);
           }
          while(test());
          string c=List.size()>1?"s":"";
          cout<<List.size()<<"pile"<<c<<" remaining:";
          for(i=0;i<List.size();i++)
    {
               cout<<' '<<List[i].size();
          }
               cout<<endl;
     }
     return 0;
}
View Code 





你的任务是模拟一种叫「Accordian」的纸牌游戏,他的游戏规则如下: 

一副扑克牌有52张牌,首先把纸牌一张一张由左到右排好(不能有重叠,所以共有52堆牌,每堆一张),当某一张牌与他左边那张牌或者左边的第三张牌有「Match」的时候,就把这张牌移到那张牌上面去。在这里两张牌「Match」指的是这两张牌的花色(suit)或者点数(rank)一样。当你做了一个移动之后,要察看是否还可以做其他的移动。在任何时间,只有最上面那张牌可以被移动。如果因为移动一张牌使得产生一个空格(也就是被移动的那堆牌只有一张牌),你必须把右边所有的牌堆往左移一格。如此不断的寻找可移动的牌,直到没有一张牌可以移动游戏就结束了。 

在选择可以移动的牌的时候可能有些状况会发生。如果有两张牌都可以移动,你应该要移动最左边的那张牌。当一张牌可以被移动到左边一格,或左边三格的时候,你必须移动到左边三格。 

Input 

输入包含多组测试资料。每组测试资料两列,每列有26张牌的资料。每张牌以2个字元代表。第一个字元代表牌的点数(A=Ace, 2~9, T=10, J=Jack, Q=Queen, K=King),第二个字元代表牌的花色(C=Clubs, D =Diamonds, H=Hearts, S=Spades) 

若遇到仅含#的一列代表输入结束。请参考Sample Input。 

Output 

对每组测试资料输出游戏结束时剩下几堆牌,以及每堆牌有多少张牌。请注意如果只有1堆牌,pile后没有加s,请参考Sample Output。 

代码:非链表法

#include <algorithm> 

#include <iostream> 

#include <string> 

#include <vector>

 using namespace std; 

//CARD结构体,存储一张牌,Face[0]表示花色,Face[1]表示点数

struct CARD 

{

char Face[2];

} Src; 

//比较两张牌是否匹配。花色或点数相同即匹配

inline bool Match(const CARD &c1, const CARD &c2)

 { 

 return (c1.Face[0] == c2.Face[0] || c1.Face[1] == c2.Face[1]); 

} 

int main(void) 

{ //主函数

 typedef vector<CARD> PILE; 

 char Pack[256]; //用于存储输入的一副牌,下面循环读取输入的数据

 for (string Line; getline(cin, Line) && Line[0] != '#'; cout << endl) 

{  

 strcpy(Pack, Line.c_str()); //读取并处理输入的数据

  while (getline(cin, Line) && Line.empty()); //读取第2行 

  strcat(Pack, Line.c_str()); 

  *remove(&Pack[0], &Pack[strlen(Pack)], ' ') = '\0'; //删除行中的空格 

  vector<PILE> Piles; 

  for (int i = 0; i < 52; ++i) 

{ //循环发出每一张牌  

  PILE Stack(1, ((CARD*)&Pack)[i]);

    Piles.push_back(Stack); //将新发的牌放在最后一叠   

 //j表示当前牌的位置,k表示j左边与之匹配的牌的位置    

for (size_t j = Piles.size() - 1, k; j < Piles.size(); ++j)

 {     //以下循环向左查找可以移到的最左边的位置   

  for (k = j, Src = Piles[j].back(); k > 0; --k)

 {   

   if (k >= 3)

 { //先判定左边是否存在第3张    

   if (Match(Src, Piles[k - 3].back())) 

{        //如果与左边第3张匹配,则将k指向这张牌   

     k -= 2;       

 continue;    

   }

 //虚拟移到k指向的位置,继续向左查找 

     }   

   if (!Match(Src, Piles[k - 1].back()))

 {      

 break; //如果左边第3张和第1张都失配,跳出循环

     }   

  }    

 if (k != j) 

{ //k与原位置j不相等表示可以移动   

   Piles[k].push_back(Piles[j].back()); //移动牌  

    Piles[j].pop_back(); 

     if (Piles[j].empty()) 

{ //如果牌叠被移空则删除之  

     Piles.erase(Piles.begin() + j);  

    }     

 j = k; //将移动牌查找的起点定为k 

    }  

  }   

}

 //以下按要求的格式输出结果。注意到Pile有单复数的区分  

 int nSize = Piles.size();  

 cout << nSize << " Pile" << (nSize > 1 ? "s " : " ") << "remaining:"; 

  for (i = 0; i < nSize; cout << ' ' << (Piles[i++]).size()); 

 }

  return 0;

 }

链表法:

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int N=55;
struct node
{
    char face;
    char suit;
};
vector< vector<node> > List;     
bool match(node a,node b)
{
      return a.face==b.face||a.suit==b.suit;
}
bool test()
{
     bool flag=false;
     int k,t;
     int s=List.size();
     for(int i=s-1;i>0;i--)
  {
         if(i-3>=0&&match(List[i].back(),List[i-3].back()))
   {
                k=i;
                t=3;
                flag=true;
         }               //根据题意,先往左边的第三个挪动
         else if(i-1>=0&&match(List[i].back(),List[i-1].back()))
   {
                k=i;
                t=1;
                flag=true;
         }       //在往左边挪动
     }
     if(flag)
  {
          List[k-t].push_back(List[k].back());
          List[k].pop_back();
          if(List[k].empty())
    {
               List.erase(List.begin()+k);//挪动后,如果该组空了,右边的都要往左边来挪动。
          } 
          return true;
     }
     return false;
}
//得到牌最后的位置
int main()
{
     node p;
     vector<node> l;
     while(cin>>p.face&&p.face!='#')
  {
           cin>>p.suit;
           l.clear();
           l.push_back(p);
           List.clear();
           List.push_back(l);
           for(int i=2;i<=52;i++)
     {
                cin>>p.face>>p.suit;
                l.pop_back();
                l.push_back(p);
                List.push_back(l);
           }
          while(test());
          string c=List.size()>1?"s":"";
          cout<<List.size()<<"pile"<<c<<" remaining:";
          for(i=0;i<List.size();i++)
    {
               cout<<' '<<List[i].size();
          }
               cout<<endl;
     }
     return 0;
}
View Code

 

posted on 2013-07-08 16:35  Forgiving  阅读(154)  评论(0编辑  收藏  举报