纸牌游戏

``Accordian'' Patience 

You are to simulate the playing of games of ``Accordian'' patience, the rules for which are as follows:

    Deal cards one by one in a row from left to right, not overlapping. Whenever the card matches its immediate neighbour on the left, or matches the third card to the left, it may be moved onto that card. Cards match if they are of the same suit or same rank. After making a move, look to see if it has made additional moves possible. Only the top card of each pile may be moved at any given time. Gaps between piles should be closed up as soon as they appear by moving all piles on the right of the gap one position to the left. Deal out the whole pack, combining cards towards the left whenever possible. The game is won if the pack is reduced to a single pile. 

Situations can arise where more than one play is possible. Where two cards may be moved, you should adopt the strategy of always moving the leftmost card possible. Where a card may be moved either one position to the left or three positions to the left, move it three positions.

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

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

其实题目真不难但是卡在题意细微处了,注意红色标记的地方,主要是要移动的话西如果左边第三张匹配,则移动到第三堆否则在判断左边第一张,另外不能一次把一个牌堆一次性移动完(个人就这样办过结果怎么着测试不对),另外就是每次移动一张之后都要再次检查是否有可移动的。本人用的容器vector

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;

struct card
{
    char rank,suit;
    card(char a,char b){
        rank=a;suit=b;
    }
};

int equal(card a,card b)
{
    if(a.suit==b.suit||a.rank==b.rank)
        return 1;
    return 0;
}
int main()
{
    char s[3];
    int ismoved;
    vector<stack<card> > holder;
    while(scanf("%s",s)&&s[0]!='#')
    {
        card in(s[0],s[1]);
        stack<card> cards;
        cards.push(in);
        holder.push_back(cards);
        if(holder.size()==52)
        {
            ismoved=1;
            //int count=0;
            while(ismoved)
            {
                ismoved=0;
                for(int i=1;i<holder.size();i++)
                {
                    if(i>=3&&equal(holder[i].top(),holder[i-3].top()))
                    {
                        ismoved=1;      //因为每次要移动最左边能移动的那个所以不能一次性把能移动的一组全部移动
                                        //以为移动玩一次之后当前牌堆前可能有能移动的另外的牌了

                        holder[i-3].push(holder[i].top());
                        holder[i].pop();
                        if(holder[i].empty())
                        {
                            holder.erase(holder.begin()+i);
                        }
                        break;
                    }
                    else if(equal(holder[i].top(),holder[i-1].top()))
                    {
                        ismoved=1;
                        holder[i-1].push(holder[i].top());
                        holder[i].pop();
                        if(holder[i].empty())
                        {
                            holder.erase(holder.begin()+i);
                        }
                        break;
                    }
                }
            }
            //printf("count=%d\n",count);
            if(holder.size()>1)
                printf("%d piles remaining:",holder.size());
            else
                printf("%d pile remaining:",holder.size());
            for(int i=0;i<holder.size();i++)
                printf(" %d",holder[i].size());
            printf("\n");
            holder.clear();
        }

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值