开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情
不知道大家有没有玩过这种小游戏:就是把一副扑克牌平均分成两部分,每个人拿一份。玩家1先拿出手上第一张牌,放出来,玩家2也同样拿出直接的第一张牌,接下来玩家1......两个交替出牌,出牌时候,如果某人打出牌和桌面上某张牌相同,那么就可以把两张牌及中间的牌拿走,以此放到中间牌末尾,当任意一个人手上没有牌了,则他输了。(保证自己手上一直有牌)
在这里为了方便,我们不考虑花色,且假设牌面只有1-9,这时候对于某玩家来说,有几种操作? 两种:出牌或者赢牌。
假设:玩家A 有牌:2 4 1 2 5 6 玩家B有牌:3 1 3 5 6 4
依次循环下去
对于画图,好像思路很简单,但是太多重复,那么我们如何代码实现他呢?
第一步:选择数据结构
因为需要按照顺序放入,且从head拿出,tail插入,所以我们可以选择队尾插入,队首拿出的队列,出队入队恰好对于出牌赢牌;
因为桌子上牌,是从末尾依次拿走,对于栈的先入后出,所以打出去的牌有栈存储,有人赢牌相当于出栈。
第二步:创建一个类,实现队列:
head用来存储队头,tail存储队尾,这是data大小我设置的1000,其实应该再大一些,防止越界。
如果最后代码是自己写的队列,那么需要手动实现队列:参考手写队列 - 掘金 (juejin.cn)
第三步: 创建应该类,实现栈
class static{
int data=new int[10];
int top;
}
top存储栈顶,数组data存储栈中元素,大小10就可以,因为只有九种不同牌面。所以最多存在九张不一样的,当加入第十张,必定会取走一部分牌。
第四步:创建两个玩家和牌存储
queue q1=new queue();
queue q2=new queue();
static s=new static();
接下来进行初始化: 先:没有牌 q1.head=q1.tail=1 q2.head=q2.tail=1; s.top=0;
第五步:读入牌:可以通过Scanner键盘读入,也可以最开始就初始化该内容。
读牌时候 tail++;
第六步:模拟玩家:
定义变量t存储A打出的第一张牌,把他和队列比较,看是赢牌还是出牌。
t=q1.data[q1.head];
int flag=0;
for(int i=0;i<s.top;i++){
if(t==s.data[i]{
flag=1;
break
}
}
当flag=0,表示没有赢牌,把打出牌留在桌上。 q1.head++;s.top++;s.data[s.top]=t
当flag=1,标识赢牌,如何把牌放到末尾?
假设这个是A打出的牌:那么A的head队首元素后退一位,标识打出去了,然后把他添加到自己队尾,队尾后退一个。
一位可能会从队列取出多个元素,所以使用循环
while(栈出队值!=t){ A元素末尾数据=栈出; 末尾后移: 栈顶--; }
if(flag==1){
q1.head++;
q1.data[q1.tail]=t;
q1.tai++;
while(s.data[s.top]!=t){
q1.data[q1.tail]=s.data[s.top];
q1.tail++;
s.top--;
}
第七步:模拟输赢:
在出牌之前添加while,当有一个玩家牌为null结束出牌,输出xx赢了。当然可能会存在一直玩下去的情况,那么如何优化?可以选择一个新变量,假设玩的次数是xx次,就直接结束循环,输出:平手。
完整代码:
public class PlayGame {
public static void main(String[] args) {
Stack<Integer> deskStack = new Stack<>();//桌子上的牌,用栈进行管理
Queue<Integer> playerA = new LinkedList();//用队列管理每个选手的牌
Queue<Integer> playerB = new LinkedList();
int book[] = new int[10];
Scanner scanner = new Scanner(System.in);
//发牌,每人6张
for (int i = 0; i < 6; i++) {
playerA.add(scanner.nextInt());
}
for (int i = 0; i < 6; i++) {
playerB.add(scanner.nextInt());
}
//当两个队列都不为空,表示游戏没有结束
while (!playerA.isEmpty() && !playerB.isEmpty()) {
int ta = playerA.peek();//A出一张牌
//判断A出的牌能不能赢牌
if (book[ta] == 0) {//桌子上没有这张牌
//A不能赢牌
playerA.remove();//打出的牌出队列
deskStack.add(ta);//打出的牌入栈
book[ta]=1;//标记打出的牌出现在桌子上
}else {//A能赢牌
playerA.remove();//打出的牌出队列
playerA.add(ta);//打出的牌入队列
while (deskStack.lastElement()!=ta) {
book[deskStack.lastElement()] = 0;
playerA.add(deskStack.lastElement());
deskStack.pop();
}
}
int tb = playerB.peek();//B出一张牌
//判断B出的牌能不能赢,代码和A一样的
}
if (playerA.isEmpty()) {
System.out.println("B赢了");
System.out.print("B手中的牌为:");
while (!playerB.isEmpty()) {
System.out.print(playerB.peek()+" ");
playerB.remove();
}
}else {
System.out.println("A赢了");
System.out.print("A手中的牌为:");
while (!playerA.isEmpty()) {
System.out.print(playerA.peek()+" ");
playerA.remove();
}
}
System.out.println("");
System.out.print("桌子上的牌为:");
while (!deskStack.isEmpty()) {
System.out.print(deskStack.lastElement()+" ");
deskStack.pop();
}
}
解决此类问题,首先通过描述,找到对应的数据结构,然后通过不同情况判断,进行拆分,最后对代码汇总。