1.问题引入
我们对“扑克牌”这个词并不陌生,作为一种娱乐活动被大众所熟知。那么,每一局结束后,除了人工洗牌,我们接触到的软件、小程序中如何实现的“洗牌”呢?其实,洗扑克牌的原理与乱数排列是相同的,都是将一组数字(如 1~N)打乱重新排列,只不过洗扑克牌多了一个花色判断的过程。
2.问题分析
一想到“随机”,大部分人想到的是利用产生随机数的方式 随机产生1~N的乱序数字并将之存入数组中,之后对后续产生的乱序数字存入数组前先检查阵列中是否已有重复的数字,如果数组中有这个数就不存入数组,再重新产生下一个数。在糟糕的情况下,如果多次产生的乱序数字都与数组中的数字重复,那么则会导致程序的执行速度变得缓慢,影响代码运行效率,因此这并不是一个很好的办法,如何进行改进呢?
我们以1-52的数字的乱数排序进行分析。首先,我们可以将数组按顺序从1-52依次填入,然后采用一个循环访问数组并随机产生1-52的乱序数,之后将产生的乱序数当作索引取出数组值,并与目前访问到的数组值交换 ,这样就不会产生重复的数字。也就是通过交换数组对应的值,即满足产生的数是乱序的,也提到了代码运行效率。
那么,如何判断牌的花色呢?我们只需要借助除法就可以解决这个问题,取商数判断花色,取余数判断数字。
3.代码实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 52
int main() {
int poker[N + 1];
int i, j, tmp, remain;
//初始化阵列(数组)
for(i = 1; i <= N; i++){
poker[i] = i;
}
srand(time(0));//刷新每次产生的随机数
//洗牌
for(i = 1; i <= N; i++){
j = rand() % 52 + 1; //从序号1开始产生52个随机数
tmp = poker[i];
poker[i] = poker[j];
poker[j] = tmp;
}
for(i = 1; i <= N; i++){
// 判断花色
switch((poker[i]-1) / 13){
case 0:
printf("黑桃");
break;
case 1:
printf("红心");
break;
case 2:
printf("方块");
break;
case 3:
printf("梅花");
break;
}
// 扑克牌数字
remain = poker[i] % 13;
switch(remain){
case 0:
printf("K ");
break;
case 12:
printf("Q ");
break;
case 11:
printf("J ");
break;
default:
printf("%d ", remain); break;
}
if(i % 13 == 0){
printf("\n");
}
}
return 0;
}
4.运行效果
写在最后:
读两遍下来,如果仍然有不清楚的地方,可以再来一遍。
如果你有其他感到困惑的问题,欢迎留言。