★ 会写关系表达式和逻辑表达式对编程是至关重要的,这一步上不去,后面会步步上不去
★ 我们强调理性思维和理性实践,强化上机动手动脑,编出来调不出来,不算真本事;编出的程序正确与否,要经过上机实践的检验
★ 没有实践就没有提高能力的土壤
逻辑思维在程序设计中十分重要,应该重点加以介绍。为此,我们设计了“逻辑问题及其解法”一节。为了一开始就能吸引听众,首先给出一个疑案分析的例题。
[例题] 某地刑侦大队对涉及6个嫌疑人的一桩疑案进行分析:
(1)A、B至少有 1 人作案;
(2)A、E、F 3 人中至少有2人参与作案;
(3)A、D不可能是同案犯;
(4)B、C或同时作案,或都与本案无关;
(5)C、D中有且仅有 1 人作案;
(6)如果D没有参与作案,则E也不可能参与作案。
试编一程序,将作案人找出来。
我们借用上述这个题目,向学生讲解逻辑运算符、逻辑表达式和涉及逻辑问题的解题思路。
在介绍逻辑与、逻辑或和逻辑非三个运算符之后,立刻就用它们来写逻辑表达式,这里结合疑案分析中的6句话,利用真值表写出6个逻辑表达式:
CC1=(A||B); // A和B至少有1人作案
CC2=!(A&&D);//A和D不可能是同案犯
CC3=(A&&E) || (A&&F) || (E&&F);//A、E、F中至少有2人涉嫌作案
CC4=(B&&C) || (!B&&!C);//B和C或同时作案,或都与本案无关
CC5=(C&&!D)||(D&&!C);//C、D中有且仅有1人作案
CC6=D || !E;//如果D没有参与作案,则E也不可能参与作案
逻辑表达式的取值非“真”即“假”。在上述6个式子中,赋值号“=”右边的是逻辑表达式,左边的CC1、CC2、…CC6是布尔类型的变量,其值非0即1,也可以用整型数来定义。
将疑案分析中的6句话写成6个逻辑表达式是一种基本功,这是解决这一类问题的前提条件,学会这部分内容十分重要。
我们将案情分析的这6个表达式归纳成一条,称之为破案综合判断条件CC:
CC=CC1&&CC2&&CC3& &CC4&&CC5&&CC6
从上式看出,只有当CC1、CC2、…CC6每一条都为“真”,则CC才为“真”。从CC1到CC6是与A、B、C、D、E、F 中6 个人的所作所为有关,必须将6个人干过的事(作案与否)代至公式中去看是否能使CC为“真”,这当然又想到了要用“枚举”法。
在讲堂上,定义了6个整形变量:A、B、C、D、E、F,让变量取值为0表示不是作案人,为1表示是作案人。每个人都有两种可能:“是”或者“不是”,6个人作为整体,存在26种可能。按A、B、C、D、E、F的顺序,整体取值从000000,000001,…,111111,给出了一张64种可能的表,见表1。
实现这张表是枚举的一个基础,要用到6重循环,循环控制变量分别是A、B、C、D、E、F,初值均为0,终值均为1。A循环处在最外层,F循环处在最里层,形成一个套一个的嵌套关系。接着就可以讲多重循环的语句如何写,程序框图怎样画等问题。先让学生上机实现将000000到111111的表打出来,借此巩固多重循环的概念及编写方法,也是为了给进一步解析疑案搭一个台阶。为此,建议写一条输出语句:
cout << A << B << C << D <<E<<F<< endl; (1)
把它当作6重循环的循环体,就可以模拟产生从000000到111111的64种可能情况。
经过上述的讲解之后,解决了枚举A、B、C、D、E、F分别取值0或1的组合问题。要寻找哪些人是罪犯,就要改造(1)式,即让循环体包含如下两部分内容:
1.根据ABCDEF的值,计算 CC1到CC6的值
CC1=(A||B); // A和B至少有1人作案
CC2=!(A&&D);//A和D不可能是同案犯
CC3=(A&&E) || (A&&F) || (E&&F);//A、E、F中至少有2人涉嫌作案
CC4=(B&&C) || (!B&&!C);//B和C或同时作案,或都与本案无关
CC5=(C&&!D)||(D&&!C);//C、D中有且仅有1人作案
CC6=D || !E;//如果D没有参与作案,则E也不可能参与作案
2.分支结构,其中条件语句是
if(CC1+CC2+CC3+CC4 +CC5+CC6==6)
如果该条件成立,则从A到F依次输出该人作案与否的判断结果。
为了让程序输出更加直观,想到用如下格式:
cout << “A” << info[A] <<endl;
cout << “B” << info[B] << endl;
我们已知变量A(或B,或C,或D,或E,或F)有0或1两种取值,
info[0] ——“不是罪犯”
info[1] ——“是罪犯”
这可以用定义字符类型的二维数组来实现。因为数组要在后面讲,这里提前使用,要先向学生说明一下,事先有所接触对学生来说也是有益的。
这样,就可以给出一个使用6重循环枚举6人中哪些人是罪犯的程序,之后让学生上机实践,弄懂并掌握这个程序的编写思路和技巧。
在此基础上,我们提出有没有可能不使用6重循环,而只用单层循环就可奏效的程序,这就属于进一步深入讨论的问题了。
思路是,A、B、C、D、E、F的64种排列,对应十进制数0,1,…,63。让循环控制变量为n
n=0,1,…,63,
知道n,一定能用之分解出A、B、C、D、E、F的值。借此,介绍二进制数位的概念,介绍C++提供的右移一位的运算符“>>”和“按位与”运算符“&”。
这时在循环体中要增加从n分离出A、B、C、D、E、F的语句
F=n&1;
E=(n&2)>>1;
D=(n&4)>>2;
C=(n&8)>>3;
B=(n&16)>>4;
A=(n&32)>>5;
书上也给出了这个程序的清单让学生上机学习。
这部分之后,留了4道有些难度的习题,目的是训练学生将一些话写成关系表达式和逻辑表达式的能力,并用枚举法将之解出,这也是检查这部分内容教学效果的一种方式。
总的来说,这部分内容看似在解决一道涉及破案的逻辑分析题,实际上教学要达到的目标是提高学生的计算思维能力,从最底层来加大抽象思维能力和逻辑思维方法的训练力度。会写关系表达式和逻辑表达式对编程是至关重要的,这一步上不去,后面会步步上不去。从这一课开始,我们强调理性思维和理性实践,强化上机动手动脑,编出来调不出来,不算真本事;编出的程序正确与否,要经过上机实践的检验,强调实践是检验真理的惟一标准。没有实践就没有提高能力的土壤。