魔术师发牌问题

来源:互联网 发布:数据分析的道与术 编辑:程序博客网 时间:2024/04/26 15:49

一,问题描述:魔术手中有13张牌,都是黑桃的,第一张牌翻过来是黑桃A,也就是1,因为他正确了,所以放在桌面上,第二张牌我们必须翻出2,但是魔术师会数两张牌,第一张放在牌的最低端,第二张翻出来刚好是2,又把它放在桌面上,接着魔术师会数三张牌,按顺序数,第一张放在牌的最低端,第二张放在牌的最低端,第三张翻开来,刚好是3,放在桌面上,以此类推把所有的牌都数完了,刚好是从1到13,即为1、2、3、4、5、6、7、8、9、10、J、Q、K这十三张按顺序排放。怎么用编程的思想来解决这个问题,使得怎样才可以保证按这个顺序拿牌会得出相应的结果。

二,解决方案:循环链表

三,代码分析:

#include <stdio.h>#include <stdlib.h>#define CardNumber 13typedef struct node{int data;struct node *next;}sqlist, *linklist;linklist CreateLinkList(){linklist head = NULL;linklist s, r;int i;r = head;for(i=1; i<=CardNumber; i++){     s = (linklist)malloc(sizeof(sqlist)); s->data = 0;  if(head == NULL)    head = s; else    r->next = s; r = s;}r->next = head;return head;}//发牌顺序计算void Magician(linklist head){linklist p;int j;int Countnumber = 2;p = head;p->data = 1;  //第一张牌放1while(1){      for(j=0; j<Countnumber; j++)  {       p = p->next;   if(p->data != 0)      //该位置有牌的话,则下一个位置   {        p->next;j--;   }  }      if(p->data == 0)      //该位置有牌的话,则下一个位置   {        p->data = Countnumber;        Countnumber ++;                if(Countnumber == 14)     break;   }  } } //销毁工作void DestoryList(linklist* list){linklist ptr = *list;linklist buff[CardNumber];int i = 0;while(i < CardNumber){    buff[i++] = ptr;ptr = ptr->next;}for(i=0; i<CardNumber; ++i)   free(buff[i]);   *list = 0;} int main(){linklist p;int i;p = CreateLinkList();Magician(p);printf("按下面的顺序排列:\n");for(i=0; i<CardNumber; i++){     printf("黑桃%d", p->data); p = p->next;}DestoryList(&p);return 0;}
四,具体分析:
1,第一个代码段
     #define CardNumber 13 即为定义所有牌的数量为13张牌,这个是全局的,
2,第二个代码段,结构体定义
    typedef struct node   定义一个循环链表的结构体,数据为data, 定义链表指针node
3,建立链表
    linklist CreateLinkList();  13个元素的单循环链表,在for循环里进循环分配,首先给s分配内存,将s结点中的数据分配为0,判定head头结点是否为空,为空则将s结点赋为头结点,否则,则将s指向r的下一个结点,最后将尾结点指向头结点。
4,Magician函数设计
    该函数完成的是发牌顺序的计算,Countnumber为每次发牌存放的那个顺序的数字,因为第一张牌是1,所以第二个数字为2,即为Countnumbei = 2;接着进入while循环,再进入里面的for循环,首先第一个位置已经为1,即p->data=1,在for循环里,p指向下一个结点,该位置有牌的话则进行下一个位置,如果该位置没有牌,此处进行了两次循环,此时p指向了第三个地方,则进入下一个for循环,此时将Countnumber里面的数字放在p里,同时Countnumber加1,即为3,接着进入while循环,此时第一个for循环要进行三次,所有p要往下指向第三个,同时将3赋值给p->data,同理,再进行四次for循环,Countnumbei为4,依次往下进行,最后结果即为:
     1 8 2 5 10 3 12 11 9 4 7 6 13
5,销毁工作,释放内存和变量
     void DestoryList(linklist* list)里面进行此工作
6,main函数
     main中主要是进行上面函数的工作结果,然后讲链表中的数据依次遍历出来,告诉大家这个原始牌是怎么放的,从而可以得出那样的发牌效果。记得在最后要释放内存。


1 0
原创粉丝点击