相信不少读者都看过央视的《水浒》吧,林冲、武松、李逵等英雄好汉的音容笑貌仿佛还浮现在我的眼前,那么108将中你最喜欢谁呢?我做了一个小程序来让电脑猜测你的心思,程序界面如图所示。
为了简化问题,我选择了其中的27将,将他们分成3组,每组9人。如果你最喜欢其中的一个(比如史进),他在第一组出现了,那么就按下按钮“第一组”。然后这27将会重新排列顺序,你再找史进在哪一组,比如发现他在第二组,就按下按钮“第二组”,画面中的人物次序会再次打乱,再找史进所在组别……最多3次,电脑将会猜出你心中的英雄!
知道了玩法,下面我将介绍程序是如何实现的:
一、猜测的奥妙——推算原理
猜测的原理其实也不复杂,我们来模拟一下猜测的过程大家就清楚了。程序初始化时是把1~27将随机打乱分别放入PageControl控件的三个选项卡中,每个选项卡放9张图片。点击一次按钮后其实不是盲目地将顺序打乱,而是进行了筛选,把有用的图片(就是点选的那组的9张图片)筛选出来平均分配到PageControl控件的三个选项卡中,再把不需要的图片集中起来平均分配到PageControl控件的三个选项卡中,最后在各个选项卡中把有用的、无用的图片随机打乱再次重新排列显示出来,从而完成猜测。用表1来说明:点击按钮的次数 选项卡1 选项卡2 选项卡3 1 3 3 3 2 1 1 1 3 0 0 0
具体讲,当第一次按下按钮时,表示你相中的图片在其中一个选项卡的9张图片内。于是把这9张图片均分成3份,每份3张,分别送入3个选项卡,其余的图片就不做考虑了。当第二次按下按钮时,表示你相中的图片在其中一个选项卡的3张图片内,于是把这3张图片均分成3份,每份1张,分别送入3个选项卡,当第三次按下按钮时,表示你相中的图片在其中一个选项卡的1张图片内,毫无疑问,这张图片就是你相中的图片,于是程序把这张图片显示出来。
打乱重排的算法
在程序中的很多地方要涉及打乱顺序重排的问题,下面我们就来先简单介绍一下打乱是如何实现的。
这里要实现的方法是比较简单的,也就是多次把数组的不同位置的值互换,就像读小学时老师让两个同学互换位置一样,老师不断随机抽两个同学互换位置,最后同学们的座位就都重新排了一遍。
举个例子:int i,temp1,temp2,a[2],b[27]
for(i=1;i<=27;i++)//先对数组赋初值
b[i]=i;
randomize();
for(i=1;i<=500;i++)//i的大小决定打乱的程度,循环次数越多,打乱程度越高
{
temp1=random(27)+1;
temp2=random(27)+1;
a[1]=b[temp1];
b[temp1]=b[temp[2];
b[temp2]=a[1];
}
//输出
ListBox1->Clear();
for(i=1;i<=27;i++)
ListBox1->Items->Add(IntToStr(b[i]));
如上例所示,经过打乱,b[27]数组将不再是旧时容颜。
二、实现的关键——筛选算法的介绍
在整个实现的过程中,如何在每一次打乱后对人物进行筛选是程序的关键所在,处理不好,程序就不会有结果。而且筛选很容易把你搅得头晕脑胀,所以涉及的各个数组之间的关系一定要先理顺,先用一个例子来解释如何进行筛选。以点击按钮的次数是第一次并且点击的按钮是Button1为例加以介绍,其思路如下:
初始:
第一次执行按钮事件并且按下的是Button1时(表a的数组就是关键数组):
把表a打乱后平均拆分为3组分别送入内存缓冲区
把表b和表c打乱后也平均拆分为3组分别送入内存缓冲区(非重要的数组),然后将它们进行组合,分别把有用的和无用的搭配重新组合为三张表并显示出来:
把全部的筛选过程表述出来:
1.初始化:
把a[1-27]打乱并将
a[1-9] 赋给first[1-9]
a[10-18] 赋给second[1-9]
a[19-27] 赋给third[1-9]
2.第一次按钮事件(假设选中的是第二个选项卡)
second[1-9]打乱后赋给temp1[1-3]、temp2[1-3]、temp3[1-3]
a[1-9]+a[19-27]赋给temp4[1-18] 并打乱
temp1[1-3]+temp4[1-6]赋给first[1-9]并打乱
temp2[1-3]+temp4[7-12]赋给second[1-9] 并打乱
temp3[1-3]+temp4[13-18]赋给third[1-9] 并打乱
3.第二次按钮事件(假设选中的是第二个选项卡)
temp2[1-3]打乱后赋给temp5[1]、 temp6[1] 、temp7[1]
temp1[1-3]+temp3[1-3]+temp4[1-18]赋给temp8[1-24]并打乱
temp5[1]+temp8[1-8]赋给first[1-9] 并打乱
temp5[2]+temp8[9-16]赋给second[1-9] 并打乱
temp5[3]+temp8[17-24]赋给third[1-9] 并打乱
4.第三次按钮事件(如果选中的是第二个选项卡)
把temp5[2]所对应的图片显示出来即可。
最后分别把表a—表c打乱后显示出来即可。 进行二次、多次筛选的方法都一样,只是要注意相中的好汉在哪个数组里面,千万别搞错就行了。
三、小结
最后的工作就比较简单了。可以设计一个友好的界面,然后在程序启动的时候对数组赋初值,并显示出来;对每个按钮分别先进行次数判断,然后进行前面讲述的处理,不断筛选直到剩下惟一的好汉后就可以显示在界面的正下方了。
……