你的任务是模拟一种叫「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;
}