问题:
一个人玩起了接竹竿。
规则是,当一个人出的牌在上面的牌中有一样数字的,则他可以将这两个牌和两牌之间的牌拿走,然后再出一张扑克。
左手先出牌,所赢的牌是按照以前的顺序出的。
比如:左手剩了1,2两张牌,上一步赢了一次,是2,3,4,2 那么他的出牌顺序就是1,2,2,3,4,2。
当一个人手中没牌时,则另一个人胜利。
输入:
第一行一个数T,玩了T次
每次游戏开始是一个数n,只用了数字 <=n 的扑克,
后面有两行数字,每行有 2*n 个数,
第一行代表左手的扑克。
第二行代表右手的扑克。
1 <= T <= 10
1 <= n <= 13
输出:
对于每次游戏,输出游戏的结果,
(左右手累积出牌十万次不分输赢)
每次游戏输出占一行,左手赢输出1,
右手赢输出2,
平局输出0
分析:
左手,右手的 牌,可以分别 用一个队列来记录,方便从前删除,从后插入,以及判断是否为空。
打出去的牌可以用一个数组记录。
如果不懂 队列的 定义,可以看看。
代码:
#include<queue>
#include<iostream>
#include<string>
#include<sstream>
#include<algorithm>
using namespace std; //左手先出牌
int main()
{
int T;
cin>>T; //输入T
while (T--)
{
int n,a; //用点数<=n的扑克牌 ,每个手有数量为2n的牌
int ping[20]; // 这个数组用来记录 左右手 已经出的牌
int lp,step;
cin>>n; //输入n
queue<int> left,right; //定义 左 右 两个队列。
for (int i=0;i<2*n;i++) // 左手的 2n 张牌
{
cin>>a;
left.push(a); // 从后面向队列中插入元素
}
for (int i=0;i<2*n;i++) // 右手的 2n 张牌
{
cin>>a;
right.push(a); // 从后面向队列中插入元素
}
step = 0; //记录出牌的次数
lp = 0; //lp是用来记录 已经出的牌的序号
int man=1; // man 是用来 帮助 判断是 左手,还是右手出牌的变量。。
int ans = 0 ; // 判断输赢的变量,平局为0 ,左赢为1, 右赢为2
while (step<100000)
{
if (man%2==1)
{ //先左手出牌
while (true)
{
step++;
ping[lp++] = left.front(); //记录左手出的牌
left.pop(); //左手的牌 删去 最上面的一个
bool fafe = true; //
for (int i=0;i<lp-1;i++)
{
if (ping[i]==ping[lp-1]) //ping[lp-1] 是刚刚出的牌。开始判断左手出的牌是否与前面的相同
{
fafe = false;
for (int j=i;j<lp;j++) //如果有相同的,就把中间这些牌都加到 left 队的后面。
left.push(ping[j]);
lp = i; // 因为从 i 号牌拿走,所以下次发牌 的序号是第 i 个。
break;
}
}
if (fafe)
break; // 如果有相同的,就跳出循环
}
if (left.empty()) // 如果 left 空
{
ans = 2; // 右赢
break;
}
man^=1; // ^ 异或 运算,相同为 0,不同为 1.。。能走到这一步,说明没有相同的。man变成0
} // 那么下一次循环就从右手开始
else //右手 (同左手)
{
while (true)
{
step++;
ping[lp++] = right.front();
right.pop();
bool fafe = true;
for (int i=0;i<lp-1;i++)
{
if (ping[i]==ping[lp-1]){
fafe = false;
for (int j=i;j<lp;j++)
right.push(ping[j]);
lp = i;
break;
}
}
if (fafe) break;
}
if (right.empty()) // 如果右手 空,左赢。
{
ans = 1;
break;
}
man^=1; //能走到这一步,说明没有相同的。man变成 1 .那么下次循环,就从左手开始
}
}
if (step>=100000)
{
ans = 0; // 10万次出牌没有胜负,为平局
cout<<ans<<endl;
}
else
{
cout<<ans<<endl;
}
}
return 0;
}