鱼C论坛

 找回密码
 立即注册
查看: 2125|回复: 14

[已解决]s1e31我写的子函数为什么不进入执行呢?

[复制链接]
发表于 2022-12-25 20:57:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 顶级太阳 于 2022-12-25 20:59 编辑

s1e31动动手题目:
实现一个洗牌程序。所谓洗牌程序,就是将所有的扑克牌放入一个数组中,要求把数组内的扑克牌顺序随机打乱,然后输出。
要求实现的输出内容如下:
191919jl9664zv165vl6o2.png
我写的代码如下:
  1. //洗牌、发牌、显示分模块

  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. //洗牌:在54个元素的全为0数组里填入1-54的数字
  5. void shuffle(int poker[])
  6. {
  7.         int i,j,m;
  8.         printf("洗牌进行中。。。");  //测试程度进度用,临时测试用,现有程序没有运行到这一行。why?
  9.         for(i=0;i<54;i++)
  10.         {
  11.         pos_1:        j=(rand()*54)/1;
  12.                 for(m=0;m<i;m++)
  13.                 {
  14.                         if(j=poker[m])goto pos_1;   //与已有值遍历进行比较,如果已经有填入,重新抽取随机数
  15.                 }
  16.                 poker[i]=j;
  17.                 printf("%d",i+1);  //显示进行到第几张扑克 ,临时测试用
  18.         }
  19. }

  20. //发牌deal:轮流将poket交给不同player的分发

  21. void deal(int poket[],int player1[],int player2[],int player3[])
  22. {
  23.         int i,j;
  24.         for(i=0;i<52;i++)
  25.         {
  26.                 j=0;
  27.                 switch(i%3)
  28.                 {
  29.                         case 0: player1[i]=poket[i];break;
  30.                         case 1: player2[i]=poket[i];break;
  31.                         case 2: player3[i]=poket[i];j++; break;

  32.                 }
  33.        
  34.         }       
  35. }

  36. //显示show:显示每个人手里的扑克内容
  37. void show(char name,int player[])
  38. {
  39.         char poket[54][10]={"方1","方2","方3","方4","方5","方6","方7","方8","方9","方10","方J","方Q","方K","梅1","梅2","梅3","梅4","梅5","梅6","梅7","梅8","梅9","梅10","梅J","梅Q","梅K","红1","红2","红3","红4","红5","红6","红7","红8","红9","红10","红J","红","红K","黑1","黑2","黑3","黑4","黑5","黑6","黑7","黑8","黑9","黑10","黑J","黑Q","黑K","小王","大王"};
  40.         printf("%s手上的牌是:",&name);
  41.         for(int i=0;i<14;i++)
  42.         {
  43.                
  44.                 printf("%s",poket[player[i]]);
  45.        
  46.         }
  47.         printf("\n");
  48. }
  49. int main()
  50. {
  51.           int player1[14],player2[14],player3[14];
  52.         char name1,name2,name3,yorn;
  53.         int poker[54]={0};
  54.        
  55.         printf("请输入1号玩家的名字:");
  56.         scanf("%s",&name1);
  57.         printf("请输入2号玩家的名字:");
  58.         scanf("%s",&name2);
  59.         printf("请输入3号玩家的名字:");
  60.         scanf("%s",&name3);
  61. step:   printf("方=方角,梅=梅花,红=红桃,黑=黑桃\n");     //现在程序运行到了这,往下的洗牌函数不运行了,为什么?
  62.         shuffle(poker);  //洗牌
  63.         deal(poker,player1,player2,player3);  //发牌

  64.        

  65.         show(name1,player1);//亮牌
  66.         show(name2,player2);  //亮牌
  67.         show(name3,player3);  //亮牌

  68.         printf("重新洗牌(Y/N)?");
  69.         if(getchar()=='Y') goto step;
  70.         return 0;
  71. }
复制代码


通过改错,已经编译成功,不报错了。然后尝试运行,现在屏幕显示运行到了主程序step这一步了,按照程序应该开始洗牌函数了。为了查看是不是开始洗牌,我在函数的第一行进行了输出,但是运行的时候没有出现这一个输出。运行程序长时间不退出,也没有反映。请教,这是什么原因,我错在哪里?
最佳答案
2022-12-26 08:44:47
现在这个程序已经可以完全正常运行了:
  1. //洗牌、发牌、显示分模块

  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. //洗牌:在54个元素的全为0数组里填入1-54的数字
  5. void shuffle(int poker[])
  6. {
  7.         int i,j,m;
  8.         for (i=0;i<54;++i) //改了算法,我们应该要有初始的数组
  9.                 poker[i]=i;
  10.         printf("洗牌进行中。。。\n");  //测试程度进度用,临时测试用,现有程序没有运行到这一行。why?
  11.         for(i=1;i<54;i++) //这种洗牌算法真的很简单,从前往后,随机选数,当前位置和随机选到的位置互换就好
  12.         {
  13.                 j=rand()%i;
  14.                 m=poker[i];
  15.                 poker[i]=poker[j];
  16.                 poker[j]=m;
  17.         }
  18. }

  19. //发牌deal:轮流将poket交给不同player的分发

  20. void deal(int poket[],int player1[],int player2[],int player3[])
  21. {
  22.         int i,j,p1=0,p2=0,p3=0; //p1p2p3分别发了多少牌,你这样做有问题
  23.         for(i=0;i<42;i++) //每人到底几张?
  24.         {
  25.                 j=0;
  26.                 switch(i%3)
  27.                 {
  28.                         case 0: player1[p1++]=poket[i];break;
  29.                         case 1: player2[p2++]=poket[i];break;
  30.                         case 2: player3[p3++]=poket[i];j++; break;

  31.                 }
  32.         
  33.         }     
  34. }

  35. //显示show:显示每个人手里的扑克内容
  36. void show(char name[],int player[]) //name应为数组
  37. {
  38.         const char *poket[54]={"方1","方2","方3","方4","方5","方6","方7","方8","方9","方10","方J","方Q","方K","梅1","梅2","梅3","梅4","梅5","梅6","梅7","梅8","梅9","梅10","梅J","梅Q","梅K","红1","红2","红3","红4","红5","红6","红7","红8","红9","红10","红J","红","红K","黑1","黑2","黑3","黑4","黑5","黑6","黑7","黑8","黑9","黑10","黑J","黑Q","黑K","小王","大王"};
  39.    
  40.         printf("%s手上的牌是:",name); //不需要 &
  41.         for(int i=0;i<14;i++)
  42.         {
  43.                 printf("%s ",poket[player[i]]);
  44.         
  45.         }
  46.         printf("\n");
  47. }
  48. int main()
  49. {
  50.           int player1[14],player2[14],player3[14];
  51.         char name1[15]={},name2[15]={},name3[15]={},yorn; //这里
  52.         int poker[54]={0};
  53.         
  54.         printf("请输入1号玩家的名字:");
  55.         scanf("%s",&name1);
  56.         printf("请输入2号玩家的名字:");
  57.         scanf("%s",&name2);
  58.         printf("请输入3号玩家的名字:");
  59.         scanf("%s",&name3);
  60. step:   printf("方=方角,梅=梅花,红=红桃,黑=黑桃\n");     //现在程序运行到了这,往下的洗牌函数不运行了,为什么?
  61.         shuffle(poker);  //洗牌
  62.         deal(poker,player1,player2,player3);  //发牌

  63.         

  64.         show(name1,player1); //亮牌
  65.         show(name2,player2);  //亮牌
  66.         show(name3,player3);  //亮牌

  67.         printf("重新洗牌(Y/N)?");
  68.         getchar(); //过滤 \n
  69.         if(getchar()=='Y') goto step;
  70.         return 0;
  71. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-12-25 21:12:01 | 显示全部楼层
先把编译器的警告开到最大看看

  1. sh-5.1$ gcc -g -Wall -o main main.c
  2. main.c: In function ‘shuffle’:
  3. main.c:15:28: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
  4.    15 |                         if(j=poker[m])goto pos_1;   //与已有值遍历进行比较,如果已经有填入,重新抽取随机数
  5.       |                            ^
  6. main.c: In function ‘main’:
  7. main.c:72:28: error: expected ‘;’ before ‘;’
  8.    72 |         show(name1,player1);//亮牌
  9.       |                            ^~
  10.       |                            ;
  11. main.c:57:32: warning: unused variable ‘yorn’ [-Wunused-variable]
  12.    57 |         char name1,name2,name3,yorn;
  13.       |                                ^~~~
  14. sh-5.1$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-25 21:49:55 | 显示全部楼层
问题有点多,先这样吧

  1. //洗牌、发牌、显示分模块

  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>

  5. //洗牌:在54个元素的全为0数组里填入1-54的数字
  6. void shuffle(int poker[]) {
  7.     int i, j, m;
  8.     printf("洗牌进行中。。。"); //测试程度进度用,临时测试用,现有程序没有运行到这一行。why?
  9.     for(i = 0; i < 54; i++) {
  10.     pos_1:
  11.         //j = (rand() * 54) / 1;      // 除以 1  ?
  12.                                     // 什么意思?
  13.         j = (rand() % 54) + 1;
  14.         for(m = 0; m < i; m++) {
  15.             // if(j=poker[m])goto pos_1;
  16.             // //与已有值遍历进行比较,如果已经有填入,重新抽取随机数
  17.             if(j == poker[m])
  18.                 goto pos_1; //与已有值遍历进行比较,如果已经有填入,重新抽取随机数
  19.         }
  20.         poker[i] = j;
  21.         printf("%d", i + 1); //显示进行到第几张扑克 ,临时测试用
  22.     }
  23. }

  24. #if 0
  25. //发牌deal:轮流将poket交给不同player的分发
  26. void deal(int poket[], int player1[], int player2[], int player3[]) {
  27.     int i, j;
  28.     for(i = 0; i < 52; i++) {
  29.         j = 0;
  30.         // 错
  31.         /*
  32.         switch(i % 3) {
  33.             case 0:
  34.                 player1[i] = poket[i];
  35.                 break;
  36.             case 1:
  37.                 player2[i] = poket[i];
  38.                 break;
  39.             case 2:
  40.                 player3[i] = poket[i];
  41.                 j++;
  42.                 break;
  43.         }
  44.         */
  45.     }
  46. }
  47. #else
  48. void deal(int poket[], int player1[], int player2[], int player3[]) {
  49.     int *player[3] = {player1, player2, player3};
  50.     //for(size_t i = 0; i < 52; ++i)  *player[i % 3]++ = poket[i];
  51.     for(size_t i = 0; i < 42; ++i)  *player[i % 3]++ = poket[i];    // 最简单的改法了
  52.                                                                     // 不然了
  53.                                                                     // 54 无法平分3份
  54. }
  55. #endif

  56. //显示show:显示每个人手里的扑克内容
  57. //void show(char name, int player[]) {
  58. void show(const char *name, int player[]) {
  59.     char poket[54][10] = {
  60.         "方1",  "方2", "方3", "方4",  "方5",  "方6", "方7", "方8",  "方9",
  61.         "方10", "方J", "方Q", "方K",  "梅1",  "梅2", "梅3", "梅4",  "梅5",
  62.         "梅6",  "梅7", "梅8", "梅9",  "梅10", "梅J", "梅Q", "梅K",  "红1",
  63.         "红2",  "红3", "红4", "红5",  "红6",  "红7", "红8", "红9",  "红10",
  64.         "红J",  "红",  "红K", "黑1",  "黑2",  "黑3", "黑4", "黑5",  "黑6",
  65.         "黑7",  "黑8", "黑9", "黑10", "黑J",  "黑Q", "黑K", "小王", "大王"};
  66.     //printf("%s手上的牌是:", &name);
  67.     printf("%s手上的牌是:", name);
  68.     for(int i = 0; i < 14; i++) {
  69.         // printf("%s", poket[player[i]]);      // 你上面弄到的player取值范围是什么?
  70.                                                 // 1 到 54 吧?
  71.                                                 // 用 54 直接索引这个数组?
  72.         printf("%s", poket[player[i] - 1]);
  73.     }
  74.     printf("\n");
  75. }

  76. // 错的离谱
  77. /*
  78. int main() {
  79.     int player1[14], player2[14], player3[14];
  80.     // char name1,name2,name3,yorn;
  81.     char name1, name2, name3;
  82.     int poker[54] = {0};

  83.     printf("请输入1号玩家的名字:");
  84.     scanf("%s", &name1);            // ???
  85.     printf("请输入2号玩家的名字:");
  86.     scanf("%s", &name2);            // 这什么操作?
  87.     printf("请输入3号玩家的名字:");
  88.     scanf("%s", &name3);            // 这?
  89. step:
  90.     printf(
  91.         "方=方角,梅=梅花,红=红桃,黑=黑桃\n"); //现在程序运行到了这,往下的洗牌函数不运行了,为什么?
  92.     shuffle(poker);                         //洗牌
  93.     deal(poker, player1, player2, player3); //发牌

  94.     // show(name1,player1);//亮牌
  95.     show(name1, player1); //亮牌
  96.     show(name2, player2); //亮牌
  97.     show(name3, player3); //亮牌

  98.     printf("重新洗牌(Y/N)?");
  99.     if(getchar() == 'Y')
  100.         goto step;
  101.     return 0;
  102. }
  103. */

  104. int main(void) {
  105.     srand(time(NULL));      // 连srand也没有,你这随机数"随机"吗?
  106.     int player1[14], player2[14], player3[14];      // 14 + 14 + 14 等于几?
  107.                                                     // 42 对吧?
  108.                                                     // 54 张牌,42 个位置,有什么问题?
  109.     // char name1,name2,name3,yorn;
  110.     char name1[20], name2[20], name3[20];
  111.     //int poker[54] = {0};

  112.     printf("请输入1号玩家的名字:");
  113.     scanf("%s", name1);
  114.     printf("请输入2号玩家的名字:");
  115.     scanf("%s", name2);
  116.     printf("请输入3号玩家的名字:");
  117.     scanf("%s", name3);
  118. step:
  119.     printf("方=方角,梅=梅花,红=红桃,黑=黑桃\n"); //现在程序运行到了这,往下的洗牌函数不运行了,为什么?

  120.     int poker[54] = {0};    // 放到这里就全0了
  121.     // 这个函数要执行的条件是什么?
  122.     // poker全0对不对?
  123.     shuffle(poker);                         //洗牌
  124.     deal(poker, player1, player2, player3); //发牌


  125.     // 行也不换?
  126.     printf("\n");

  127.     // show(name1,player1);//亮牌
  128.     show(name1, player1); //亮牌
  129.     show(name2, player2); //亮牌
  130.     show(name3, player3); //亮牌


  131.     // 这
  132.     getchar();      // '\n'

  133.     printf("重新洗牌(Y/N)?");
  134.     if(getchar() == 'Y')
  135.         goto step;      // 从这里转上去之后,poker还是全0吗?
  136.     return 0;
  137. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 08:17:55 | 显示全部楼层
你其实已经洗牌过了,可能是后面输出了个 \r 之类的
  1. //洗牌、发牌、显示分模块

  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. //洗牌:在54个元素的全为0数组里填入1-54的数字
  5. void shuffle(int poker[])
  6. {
  7.         int i,j,m;
  8.         printf("洗牌进行中。。。\n");  //测试程度进度用,临时测试用,现有程序没有运行到这一行。why?
  9.         for(i=0;i<54;i++)
  10.         {
  11.         pos_1:        j=(rand()*54)/1;
  12.                 for(m=0;m<i;m++)
  13.                 {
  14.                         if(j=poker[m])goto pos_1;   //与已有值遍历进行比较,如果已经有填入,重新抽取随机数
  15.                 }
  16.                 poker[i]=j;
  17.                 printf("%d",i+1);  //显示进行到第几张扑克 ,临时测试用
  18.         }
  19. }

  20. //发牌deal:轮流将poket交给不同player的分发

  21. void deal(int poket[],int player1[],int player2[],int player3[])
  22. {
  23.         int i,j;
  24.         for(i=0;i<52;i++)
  25.         {
  26.                 j=0;
  27.                 switch(i%3)
  28.                 {
  29.                         case 0: player1[i]=poket[i];break;
  30.                         case 1: player2[i]=poket[i];break;
  31.                         case 2: player3[i]=poket[i];j++; break;

  32.                 }
  33.         
  34.         }        
  35. }

  36. //显示show:显示每个人手里的扑克内容
  37. void show(char name,int player[])
  38. {
  39.         char poket[54][10]={"方1","方2","方3","方4","方5","方6","方7","方8","方9","方10","方J","方Q","方K","梅1","梅2","梅3","梅4","梅5","梅6","梅7","梅8","梅9","梅10","梅J","梅Q","梅K","红1","红2","红3","红4","红5","红6","红7","红8","红9","红10","红J","红","红K","黑1","黑2","黑3","黑4","黑5","黑6","黑7","黑8","黑9","黑10","黑J","黑Q","黑K","小王","大王"};
  40.         printf("%s手上的牌是:",&name);
  41.         for(int i=0;i<14;i++)
  42.         {
  43.                
  44.                 printf("%s",poket[player[i]]);
  45.         
  46.         }
  47.         printf("\n");
  48. }
  49. int main()
  50. {
  51.           int player1[14],player2[14],player3[14];
  52.         char name1,name2,name3,yorn;
  53.         int poker[54]={0};
  54.         
  55.         printf("请输入1号玩家的名字:");
  56.         scanf("%s",&name1);
  57.         printf("请输入2号玩家的名字:");
  58.         scanf("%s",&name2);
  59.         printf("请输入3号玩家的名字:");
  60.         scanf("%s",&name3);
  61. step:   printf("方=方角,梅=梅花,红=红桃,黑=黑桃\n");     //现在程序运行到了这,往下的洗牌函数不运行了,为什么?
  62.         shuffle(poker);  //洗牌
  63.         deal(poker,player1,player2,player3);  //发牌

  64.         

  65.         show(name1,player1); //亮牌
  66.         show(name2,player2);  //亮牌
  67.         show(name3,player3);  //亮牌

  68.         printf("重新洗牌(Y/N)?");
  69.         if(getchar()=='Y') goto step;
  70.         return 0;
  71. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 08:44:47 | 显示全部楼层    本楼为最佳答案   
现在这个程序已经可以完全正常运行了:
  1. //洗牌、发牌、显示分模块

  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. //洗牌:在54个元素的全为0数组里填入1-54的数字
  5. void shuffle(int poker[])
  6. {
  7.         int i,j,m;
  8.         for (i=0;i<54;++i) //改了算法,我们应该要有初始的数组
  9.                 poker[i]=i;
  10.         printf("洗牌进行中。。。\n");  //测试程度进度用,临时测试用,现有程序没有运行到这一行。why?
  11.         for(i=1;i<54;i++) //这种洗牌算法真的很简单,从前往后,随机选数,当前位置和随机选到的位置互换就好
  12.         {
  13.                 j=rand()%i;
  14.                 m=poker[i];
  15.                 poker[i]=poker[j];
  16.                 poker[j]=m;
  17.         }
  18. }

  19. //发牌deal:轮流将poket交给不同player的分发

  20. void deal(int poket[],int player1[],int player2[],int player3[])
  21. {
  22.         int i,j,p1=0,p2=0,p3=0; //p1p2p3分别发了多少牌,你这样做有问题
  23.         for(i=0;i<42;i++) //每人到底几张?
  24.         {
  25.                 j=0;
  26.                 switch(i%3)
  27.                 {
  28.                         case 0: player1[p1++]=poket[i];break;
  29.                         case 1: player2[p2++]=poket[i];break;
  30.                         case 2: player3[p3++]=poket[i];j++; break;

  31.                 }
  32.         
  33.         }     
  34. }

  35. //显示show:显示每个人手里的扑克内容
  36. void show(char name[],int player[]) //name应为数组
  37. {
  38.         const char *poket[54]={"方1","方2","方3","方4","方5","方6","方7","方8","方9","方10","方J","方Q","方K","梅1","梅2","梅3","梅4","梅5","梅6","梅7","梅8","梅9","梅10","梅J","梅Q","梅K","红1","红2","红3","红4","红5","红6","红7","红8","红9","红10","红J","红","红K","黑1","黑2","黑3","黑4","黑5","黑6","黑7","黑8","黑9","黑10","黑J","黑Q","黑K","小王","大王"};
  39.    
  40.         printf("%s手上的牌是:",name); //不需要 &
  41.         for(int i=0;i<14;i++)
  42.         {
  43.                 printf("%s ",poket[player[i]]);
  44.         
  45.         }
  46.         printf("\n");
  47. }
  48. int main()
  49. {
  50.           int player1[14],player2[14],player3[14];
  51.         char name1[15]={},name2[15]={},name3[15]={},yorn; //这里
  52.         int poker[54]={0};
  53.         
  54.         printf("请输入1号玩家的名字:");
  55.         scanf("%s",&name1);
  56.         printf("请输入2号玩家的名字:");
  57.         scanf("%s",&name2);
  58.         printf("请输入3号玩家的名字:");
  59.         scanf("%s",&name3);
  60. step:   printf("方=方角,梅=梅花,红=红桃,黑=黑桃\n");     //现在程序运行到了这,往下的洗牌函数不运行了,为什么?
  61.         shuffle(poker);  //洗牌
  62.         deal(poker,player1,player2,player3);  //发牌

  63.         

  64.         show(name1,player1); //亮牌
  65.         show(name2,player2);  //亮牌
  66.         show(name3,player3);  //亮牌

  67.         printf("重新洗牌(Y/N)?");
  68.         getchar(); //过滤 \n
  69.         if(getchar()=='Y') goto step;
  70.         return 0;
  71. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 08:46:21 | 显示全部楼层
人造人 发表于 2022-12-25 21:49
问题有点多,先这样吧

这样实现shuffle函数的算法效率未免很低
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-12-26 15:23:45 | 显示全部楼层
人造人 发表于 2022-12-25 21:49
问题有点多,先这样吧

第13行 j=(rand()*54)/1, 我考虑的是取0~54之间的随机数,除以1是想要取这个数的整数部分。
第19行,确实是个人习惯,一直不习惯=与==的区别,比较和定义之间不同。
第33行,发牌阶段确实我写错了。我的想法是,用牌的数量除以3,这样每一次会指向不同的case,达到轮流交给不同人的目的,player应该用【j】,而不是【i】。
第73行,我考虑的是用player里面存的整数来取poket这个数组内相应的数值。

多说一句,这一程序我是这样考虑的,在洗牌阶段,通过随机数将54个数值存入poker数组,形成一个杂乱的整数数组。在发牌阶段,将这个数组里的数值分给3个对应不同人的整数数组。在显示阶段,将数组里的整数对应到基本字符数组poket数组上。这样做的目的是减少内存占用。过程中一直用整数数组,只是最后用一下字符型数组。

第114行,主程序我没考虑随机数的问题,在这里加入一个srand什么意思呢?我考虑的取随机数只是在洗牌shuffle的子函数里。跟这个主函数没有关系的。
第115行,是我算错了。从小不玩扑克,真的不知道54张牌,3个人玩,一人几张。当时现算的,脑子一抽算错了。一人应该18张,不知道当时怎么算的了,算的结果好像还剩了2张。哈哈哈哈,抱歉。
第131行,我翻回去看了,我是在设置这个数组的时候置0的,在我程序第58行。在你给的这个位置我没有置0呀。
第152行,我在洗牌程序里做随机数,没有必要在主程序里一定是0,在主程序里完全置0没有意义。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 16:07:18 | 显示全部楼层
第13行 j=(rand()*54)/1, 我考虑的是取0~54之间的随机数,除以1是想要取这个数的整数部分。
那也不对吧?
假设这个rand()返回的是 1234
1234 * 54 = 66636
除以 1 就不能理解了,一个整数乘以一个整数会出现小数部分吗?
再说了,除以1怎么就取整数部分了?


  1. sh-5.1$ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. void print(void) {
  5.     for(size_t i = 0; i < 10; ++i) {
  6.         printf("%d ", rand());
  7.     }
  8.     printf("\n");
  9. }

  10. int main(void) {
  11.     print();
  12.     return 0;
  13. }
  14. sh-5.1$ gcc -g -Wall -o main main.c
  15. sh-5.1$ ./main
  16. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
  17. sh-5.1$ ./main
  18. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
  19. sh-5.1$ ./main
  20. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
  21. sh-5.1$ ./main
  22. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
  23. sh-5.1$ ./main
  24. 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421
  25. sh-5.1$
复制代码


随机不?
rand 叫伪随机
所以,百度 srand 函数

  1. sh-5.1$ cat main.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>

  5. void print(void) {
  6.     for(size_t i = 0; i < 10; ++i) {
  7.         srand(time(NULL));
  8.         printf("%d ", rand());
  9.     }
  10.     printf("\n");
  11. }

  12. int main(void) {
  13.     print();
  14.     return 0;
  15. }
  16. sh-5.1$ gcc -g -Wall -o main main.c
  17. sh-5.1$ ./main
  18. 496724219 496724219 496724219 496724219 496724219 496724219 496724219 496724219 496724219 496724219
  19. sh-5.1$ ./main
  20. 1265208624 1265208624 1265208624 1265208624 1265208624 1265208624 1265208624 1265208624 1265208624 1265208624
  21. sh-5.1$ ./main
  22. 2035418005 2035418005 2035418005 2035418005 2035418005 2035418005 2035418005 2035418005 2035418005 2035418005
  23. sh-5.1$ ./main
  24. 671787692 671787692 671787692 671787692 671787692 671787692 671787692 671787692 671787692 671787692
  25. sh-5.1$ ./main
  26. 1436671818 1436671818 1436671818 1436671818 1436671818 1436671818 1436671818 1436671818 1436671818 1436671818
  27. sh-5.1$
复制代码


那么,srand 函数应该放在哪里呢?
放在这里对吧?
我可见过这样做的同学,而且还不少了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-12-26 16:11:01 | 显示全部楼层
人造人 发表于 2022-12-26 16:07
第13行 j=(rand()*54)/1, 我考虑的是取0~54之间的随机数,除以1是想要取这个数的整数部分。
那也不对吧? ...

谢谢,我继续加强一下伪随机数的部分。但是rand()的结果不应该是0~1之间的么?为什么会出现1234那么大?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 16:21:58 | 显示全部楼层
顶级太阳 发表于 2022-12-26 16:11
谢谢,我继续加强一下伪随机数的部分。但是rand()的结果不应该是0~1之间的么?为什么会出现1234那么大 ...

那么就再百度 rand 函数
你看一下 rand 函数的声明

  1. int rand(void);
复制代码


还有我的代码里面

  1. printf("%d ", rand());
复制代码


看清楚,是 %d
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 16:23:21 | 显示全部楼层
顶级太阳 发表于 2022-12-26 16:11
谢谢,我继续加强一下伪随机数的部分。但是rand()的结果不应该是0~1之间的么?为什么会出现1234那么大 ...

这样的话,我就能理解你的这个表达式了
j=(rand()*54)/1
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-12-26 19:24:42 | 显示全部楼层
人造人 发表于 2022-12-26 16:07
第13行 j=(rand()*54)/1, 我考虑的是取0~54之间的随机数,除以1是想要取这个数的整数部分。
那也不对吧? ...

百度好半天,看明白了,rand()的结果是0~32767之间的一个随机值。所以为了获得某一个数以下的随机整数,需要对获得的随机数取余。比如这个题目里54张扑克,要取随机一个0~54之间的数,就需要用rand()%54,这样获得的就是54以内的一个整数。谢谢。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-12-26 19:28:29 | 显示全部楼层
zhangjinxuan 发表于 2022-12-26 08:46
这样实现shuffle函数的算法效率未免很低


我考虑的每一张扑克都重新随机抽取,然后逐个比较的shuffle算法是错误的,有可能造成运算时间特别长。你的算法确实简单,一共运行53次就可以结束。谢谢。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 19:38:04 | 显示全部楼层
顶级太阳 发表于 2022-12-26 19:24
百度好半天,看明白了,rand()的结果是0~32767之间的一个随机值。所以为了获得某一个数以下的随机整数 ...

比如这个题目里54张扑克,要取随机一个0~54之间的数,就需要用rand()%54
要得到 0~54 之间的数,应该 rand() % 55

比如这个题目里54张扑克,要取随机一个0~   53    之间的数,就需要用rand()%54

你的问题就是对边界值上马马虎虎的,然后就数组越界访问了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-12-26 20:09:12 | 显示全部楼层
顶级太阳 发表于 2022-12-26 19:28
我考虑的每一张扑克都重新随机抽取,然后逐个比较的shuffle算法是错误的,有可能造成运算时间特别长。 ...

^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-22 19:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表