游戏规则
A和B两个同学玩简单的纸牌游戏,每人手里有n张牌,两人轮流出牌并依次排列在桌面上,每次出掉手里的第1张牌,出牌后如果发现桌面上有跟刚才打出的牌的数字相同的牌,则把从相同的那张牌开始的全部牌按次序放在自己手里的牌的末尾。当一个人手中的牌先出完时,游戏结束,对方获胜。
如n为5,每人手中有5张牌;
A手里的牌依次为2 3 5 6 1,B手里的牌依次为1 5 4 2 9;
A出2;
B出1;
A出3;
B出5;
A出5,发现前面有一张5,则把两个5都拿掉,这时他手里有6 1 5 5;
桌子上的牌依次为2 1 3;
B出4;
A出6;
B出2,发现前面有一张2,则把从2开始的牌全部拿掉,这时他手里有9 2 1 3 4 6 2;
桌子上没有牌了;
A出1;
B出9;
A出5;
B出2;
依次类推,直到某人先出完牌为止,则对方是胜者。
设计思路
玩家手中的牌是按出牌顺序存储在队列中,队头出牌,队尾收牌;桌面上的牌是按玩家出牌顺序存储在栈结构中。
游戏开始,玩家出牌,即该玩家的手牌队头元素出队,然后到桌面栈中从栈顶向下依次与该玩家出的牌进行对比比较;若有相同的牌,即之前有玩家出过相同的牌,那么则按自栈顶向下的顺序直到相同牌处,将这些牌出栈,并将这些出栈牌逆序插入该出牌玩家的手牌队尾;如果没有相同牌,那么该玩家出的牌入桌面栈。接着下一玩家出牌,仍是按上述的规则进行,轮流往复,直到其中一名玩家的手牌队列为空,该玩家获胜。
综上,无论是玩家手牌队列还是桌面卡牌栈,都要进行多次的增删,所以都采用链式结构。
相关代码
//主程序
int main() {
//设置游戏循环标识、轮流出牌标识、初始化时间种子
int GameStart = 1, Skip = 0, NOG = 0;
//设置时间种子,用于产生随机数作为卡牌值
srand((int)time(0));
//显示游戏介绍
Show_Instruction();
cout << "输入1开始游戏,输入0退出-----》" << endl;
cin >> GameStart;
while (GameStart == 1) {
cout << "游戏开始!" << endl;
//默认每人手中初始有十张牌,并初始化玩家手牌链队及桌面卡牌链栈
int A[Card_Number], B[Card_Number];
LinkQueue<int> A_Card;
LinkQueue<int> B_Card;
LinkStack<int> Table;
//随机生成两组卡牌,卡牌范围默认是[1-9]
cout << "正在发牌,请稍后......" << endl;
//生成卡牌函数
Deal_Card(A);
Sleep(4 * 1000);
Deal_Card(B);
//将数组元素入链队
for (int i = 0; i < Card_Number; i++) {
A_Card.EnQueue(A[i]);
B_Card.EnQueue(B[i]);
}
//将此时玩家手中的牌显示
cout << "发牌后,两名玩家的手牌分别是:" << endl;
cout << "A玩家:";
A_Card.OutQueue();
cout << endl << "B玩家:";
B_Card.OutQueue();
cout << endl;
while (!A_Card.Empty() && !B_Card.Empty()) {
Sleep(4 * 1000);
NOG++;
cout << endl;
cout << endl << "第" << NOG << "次玩家出牌==============================" << endl;
cout << "A玩家手牌:";
A_Card.OutQueue();
cout << endl << "B玩家手牌:";
B_Card.OutQueue();
cout << endl << "桌面上的牌:";
Table.ReOut();
cout << endl;
LinkStack<int> Temp;//初始化一个临时链栈,暂时存储从桌面拿出的牌,重新放入玩家手中,保证按照之前出牌顺序收入玩家手中
if (Skip == 1) {//默认A玩家先出牌
int tempA = A_Card.DeQueue();//A玩家出牌
cout << "此时A玩家出牌:" << tempA << endl;
int siteA = Table.FindNum(tempA);//确定是否之前已经出过了相同的牌及位置
if (siteA != 0) {//如果之前出过相同的牌
cout << "回收桌面上,与玩家出牌相同的牌及相同牌之间的所有牌" << endl;
for (int i = 0; i < siteA; i++)//循环将两张相同牌及之间所有的牌从桌面拿出
Temp.Push(Table.Pop());
for (int j = 0; j < siteA; j++)//并将拿出的牌列按之前的出牌顺序收回到A玩家的牌底
A_Card.EnQueue(Temp.Pop());
A_Card.EnQueue(tempA);
Temp.~LinkStack();//销毁临时链栈
}
else {//如果之前没有出过相同的牌
cout << "不回收" << endl;
Table.Push(tempA);//将牌放到桌面
}
Skip--;//改变Skip参数,轮到另一玩家出牌
}
else {
int tempB = B_Card.DeQueue();//B玩家出牌
cout << "此时B玩家出牌:" << tempB << endl;
int siteB = Table.FindNum(tempB);//确定是否之前已经出过了相同的牌及位置
if (siteB != 0) {//如果之前出过相同的牌
cout << "回收桌面上,与玩家出牌相同的牌及相同牌之间的所有牌" << endl;
for (int i = 0; i < siteB; i++)//循环将两张相同牌及之间所有的牌从桌面拿出
Temp.Push(Table.Pop());
for (int j = 0; j < siteB; j++)//并将拿出的牌列按之前的出牌顺序收回到B玩家的牌底
B_Card.EnQueue(Temp.Pop());
B_Card.EnQueue(tempB);
Temp.~LinkStack();//销毁临时链栈
}
else {//如果之前没有出过相同的牌
cout << "不回收" << endl;
Table.Push(tempB);//将牌放到桌面
}
Skip++;//改变Skip参数,轮到另一玩家出牌
}
}
cout << endl;
if (A_Card.Empty())
cout << "A玩家最先出完手中的卡牌,A玩家获胜!" << endl;
else
cout << "B玩家最先出完手中的卡牌,B玩家获胜!" << endl;
cout << endl << "是否继续游戏(输入1继续,输入0退出)-----》" << endl;
cin >> GameStart;
}
return 0;
}
运行截图
在程序运行后,会先显示游戏的相关介绍
确认开始游戏后
备注
在主函数中的Deal_Card(A),Table.FindNum(tempA)调用的函数均是单独函数,如若需要请点击这里下载,有分享的完整项目代码文件。
这是博主在学习过程中编写的,可能会存在瑕疵,分享仅供参考,望大佬们评判指点!