例11.13
口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中先后取出3个球,问得到3种不同色的球的可能取法,打印出每种排列的情况。
球只能是5种色之一,而且要判断各球是否同色,应该用枚举类型变量处理。
设取出的球为i、j、k。根据题意,i、j、k分别是5种色球之一,并要求i≠j≠k。可以用穷举法,即一种可能一种可能地试,看哪一组符合条件。
算法可用图11.27表示。
用n累计得到3种不同色球的次数。外循环使第1个球i从red变到black。中循环使第2个球j也从red变到black。如果i和j同色则不可取,只有i、j不同色(i≠j)时才需要继续找第3个球,此时第3个球k也有5种可能(red到black),但要求第3个球不能与第1个球或第2个球同色,即k≠i,k≠j。满足此条件就得到3种不同色的球。输出这种3色组合方案。然后使n加1。外循环全部执行完后,全部方案就已输出完了。最后输出总数n。
下面的问题是如何实现图10.28中的“输出一种取法”。这里有一个问题:如何输出“red”、“blue”……等单词。不能写成printf("%s",red)来输出“red”字符串。可以采用图11.28的方法。
为了输出3个球的颜色,显然应经过3次循环,第1次输出i的颜色,第2次输出j的颜色,第3次输出k的颜色。在3次循环中先后将i、j、k赋予pri。然后根据pri的值输出颜色信息。在第1次循环时,pri的值为i,如果i的值为red,则输出字符串“red”,其他的类推。
程序如下:
main()
{enum color {red,yellow,blue,white,black};
enum color i,j,k,pri;
int n,loop;
n=0;
for (i=red;i<=black;i++)
for (j=red;j<=black;j++)
if (i!=j)
{ for (k=red;k<=black;k++)
if ((k!=i) && (k!=j))
{n=n+1;
printf("%-4d",n);
for (loop=1;loop<=3;loop++)
{switch (loop)
{case 1,pri=i;break;
case 2,pri=j;break;
case 3,pri=k;break;
default:break;
}
switch (pri)
{case red:printf("%-10s","red"); break;
case yellow,printf("%-10s","yellow"); break;
case blue,printf("%-10s","blue"); break;
case white,printf("%-10s","white"); break;
case black,printf("%-10s","black"); break;
default,break;
}
}
printf("\n");
}
}
printf("\ntotal:%5d\n",n);
}
运行结果如下:
1redyellowblue
2redyellowwhite
3redyellowblack
…………
58blackwhitered
59blackwhiteyellow
60blackwhiteblue
total:60
有人说,不用枚举变量而用常数0代表“红”,1代表“黄”……不也可以吗?是的,完全可以。但显然用枚举变量更直观,因为枚举元素都选用了令人“见名知意”的标识符,而且枚举变量的值限制在定义时规定的几个枚举元素范围内,如果赋予它一个其他的值,就会出现出错信息,便于检查。