求13张扑克牌的原顺序
题目:
有一个游戏,取一个花色的所有13张扑克牌,成为一摞,按照如下的规则取牌:
(1)将最上面一张牌放到这一摞牌的最下面
(2)然后将最上面的一张牌取出以后不断重复1,2的动作,直到所有的扑克牌取完为止。
问题:如果要使得取出扑克牌的顺序为从小到大,即顺序为:A、2、3、4、5、6、7、8、9、10、J、Q、K,请使用C/C++编程求出最初扑克牌的顺序应该是什么。
解题思路:
方法一:观察这个问题,它有放牌和取牌两个过程,结束条件为所有扑克牌取完。所以我将两个过程都写成一个函数,然后放在主函数的循环中重复执行,直到满足结束条件。从正向解决这个问题,我定义了一个数组赋值1~13,这个13个数代表了我的牌在原牌堆中的顺序,那么我重复进行操作一、二后取出的序列就是牌面A~K对应在原牌堆的位置,按照这个顺序对A~K进行排序后得到的即为最初扑克牌的顺序。
操作一:记录第一个元素>>数组元素循环前移一个>>第一个元素赋给最后一个位置
操作二:记录第一个元素>>数组元素循环前移一个>>返回第一个元素并且牌堆长度-1(取牌)
方法二:我将题目中操作一理解为将整个牌堆首尾相连(一群人围成圈),操作二理解为每次都取当前牌环的第二张牌(依次进行从1开始的报数,报到2的人被淘汰),那么整个问题就可以看成一个经典的约瑟夫问题。
我有一道约瑟夫问题的代码,可以先去理解那道。
约瑟夫问题-CSDN博客https://blog.csdn.net/a921876874/article/details/142664107?spm=1001.2014.3001.5501
程序代码:
方法一(模拟取牌过程):
#include <stdio.h>
void one_fun(int *);//操作一
int two_fun(int *);//操作二
int len = 13;//len作为全局变量传递,代表当前牌数
int main(int argc, char *argv[])
{ int i = 1;int ret;int ch2[13] = {1,2,3,4,5,6,7,8,9,10,11,12,13};//值代表在原牌堆的牌序int ch[13] = {0};//存放原牌堆的牌while(len != 0){//没有取完时重复操作一、二one_fun(ch2);ret = two_fun(ch2);//由于原数组中存的是原牌堆的牌序,所以返回值代表这次取出的牌在原牌堆的位置ch[ret-1] = i;//数组下标从0开始,ret-1得到对应位置i++; }//取出牌面从1~13,i在这里代表牌面大小printf("扑克牌最初的顺序为:\n");for(i = 0; i <13; i++){//这里13不可以写成len,len在前面循环结束后已经为零printf("%d ",ch[i]);}//输出最初的牌序puts("");return 0;
}
void one_fun(int *p)
{int i;int c = *p;//拿第一张牌for(i = 0; i < len-1; i++){//所有牌循环前移p[i] = p[i+1];}p[len-1] = c;//将第一张牌插入牌尾
}
int two_fun(int *p)
{int i;int c = *p;//记录第一张牌for(i = 1;i <= len-1; i++){//所有牌循环前移p[i-1] = p[i];}len--;//取牌后总牌数-1return c;//取牌操作
}
方法二(利用本质是约瑟夫问题求解):
#include <stdio.h>
int main()
{int i,j;int a[13];//存原牌堆排序int b[13];//取出的牌堆int c[13];//存原牌堆牌int count1 = 0;//判定当前位置是否需要取牌int count2 = 0;//统计取出牌数量for(i = 0;i < 13;i++){a[i] = i+1;}//赋值牌序i = 0;j = 0;while(count2 < 13){//当没有取完所有牌时循环if(a[i] != 0){count1++;}//如果没有被取过if(count1 == 2){//符合被取走条件b[j] = a[i];//记录取走的牌a[i] = 0;//标记已经被取走count1 = 0;//重置判断条件count2++;//取出牌数增加j++;}i++;//保证下一轮循环判断下一张牌if(i==13){//如果到牌尾,将判断位置重新置于牌头i = 0;}}printf("原本的排序为:\n");for(i = 0; i < 13; i++){for(j = 0; j < 13; j++){if(i+1 == b[j]){//数组b的值和i+1都代表该牌在原牌堆的顺序c[i] = j+1;//c[i]代表原牌堆的牌面大小,j+1代表顺序为b[j]牌的牌面大小printf("%d ",c[i]);}}}puts("");return 0;
}
运行结果:
1~13分别代表A、2、3、4、5、6、7、8、9、10、J、Q、K。
扑克牌最初的顺序为:
7 1 12 2 8 3 11 4 9 5 13 6 10
原本的排序为:
7 1 12 2 8 3 11 4 9 5 13 6 10