本节所用基础:
分支和循环语句
二维数组
用三个简单的推理题打开C语言推理的思路
问题1
5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的结果;
❀思路分析
1.将每位选手的每种可能获得名次的情况都遍历一遍。
即假设A的名次有五种可能,第一名到第五名,
(将选手的名次赋给选手同名的变量a。)
B的名次有五种可能…
2.在每种的可能情况下,结合现实筛选有效项。
(1)每个名次只能有一个人,每个人只能有一个名次。
即第五名不可能同时为A和B和…
A不可能既是第一名又是第五名…
即五位选手的名次只能有 第一、第二、第三、第四、第五。每种名次出现一次的情况
实现操作((A+B+C+D+F)==(1+2+3+4+5))&&((A*B*C*D*F) ==(1*2*3*4*5))
(2)判断每位选手说的话只有一半对。
例如:A说“B第二,我第三”只有一半对
实现操作((b == 2)+(a == 3))== 1
判断两个语句的真假值,
如果对一半,两句一真一假,1+0=1.
如果全队,两句全真,1+1 = 2.
如果全错,两句全假。0+0=0.
#include<stdio.h>
int main()
{
int a, b, c, d, e; //a,b,c,d,e分别代表选手A,B,C,D,E。用for循环来全排列全部选手的全部名次可能
for (a = 1; a <= 5; a++) //A选手的名次可能为1~5
{
for (b = 1; b <= 5; b++) //B选手的名次可能为1~5
{
for (c = 1; c <= 5; c++) //C选手的名次可能为1~5
{
for (d = 1; d <= 5; d++) //D选手的名次可能为1~5
{
for (e = 1; e <= 5; e++) //E选手的名次可能为1~5
{
if (((a*b*c*d*e == 120) && (a + b + c + d + e == 15)) && (((a == 3) +(b == 2)) == 1) && ((((b == 2) + (e == 4)) == 1) && (((c == 1) + (d == 2)) == 1) && (((c == 5) + (d == 3)) == 1) && (((e == 4) + (a == 1)) == 1)))
{
printf("A的名次为:%d\nB的名次为:%d\nC的名次为:%d\nD的名次为:%d\nE的名次为:%d \n", a, b, c, d, e);
}
}
}
}
}
}
system("pause");
return 0;
}
问题2
某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯//的一个。以下为4个嫌疑犯的供词。
A说:不是我。
B说:是C。
C说:是D。
D说:C在胡说
已知3个人说了真话,1个人说的是假话。
现在请根据这些信息,写一个程序来确定到底谁是凶手。
❀思路分析
1.让杀手变量从A到D遍历一遍
在每种可能情况下判断是否符合条件
2.判断四句话的真假
实现操作((killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D')) == 3
四条语句都有真假值,只有三真一假时,语句相加结果为3.
#include<stdio.h>
int main()
{
char killer; //定义这个杀手变量
for (killer = 'A'; killer <= 'D'; killer++) //循环,使杀手这个变量从A到D依次赋值过
{
if (((killer != 'A') + (killer == 'C') + (killer == 'D') + (killer != 'D')) == 3) //满足条件三真一假时成立
printf("凶手就是\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n猜到了吗?\n\n\n\n\n\n\n\n%c干掉他!\n", killer);
}
system("pause");
return 0;
}
问题3
在屏幕上打印杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
规律,每一位为上一行该列+上一行该列的前一列
❀思路分析
1.先打印如题的直角杨辉三角,打印好后调整形状。
(1)定义二维数组,存放杨辉三角中的数值
观察杨辉三角,发现第一列(j == 0)和对角线上(i == j)的数字都为1,(用i表示行序号,j表示列序号)
且杨辉三角的数字只分布在数组的左下角。
实现操作if ((i == j)||(j == 0)) { yang[i][j] = 1; //先打印数组的第一列和对角线一列,因为他们全为1 }
(2)每一位为上一行该列+上一行该列的前一列,如图所示
实现操作yang[i][j] = yang[i - 1][j] + yang[i - 1][j - 1];
2.调整空格,使直角三角形打印出金字塔型
(1)观察每行第一个元素前的空格,依次减小
实现操作printf("%*d", 20- 2*i, yang[i][0]);
20-2i为随显示修改的结果,并非固定表达,注:表达式中与20-2*i对应
(2)随后输出的数打够空格,调整位置即可。
实现操作printf(" %d ", yang[i][j]);
#include <stdio.h>
#define N 10 //宏定义一个常量,可改变数字以改变杨辉三角显示的行数
int main()
{
//赋值
int i = 0, j =0;int yang[N][N] = { 0 };
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if ((i == j)||(j == 0))
{
yang[i][j] = 1; //先赋值数组的第一列和对角线一列,因为他们全为1
}
else
{
yang[i][j] = yang[i - 1][j] + yang[i - 1][j - 1]; /*赋值,每一个元素的值为 他对应列上一行的元素+他对应列的前一列的上一行的元素。例如题目所显示的直角形杨辉三角*/
}
}
}
//打印
for (i = 0; i < N; i++)
{
printf("%*d", 20- 2*i, yang[i][0]); /*打印杨辉三角每一行的第一个元素,前需空格随行数依次减小,20-2*i为随显示修改的结果,并非固定表达,注:表达式中*与20-2*i对应*/
for (j = 1; j <= i; j++)
{
printf(" %d ", yang[i][j]); //打印该行其余数字,只需固定空格即可
}
printf("\n");
}
system("pause");
return 0;
}
❤关于“%*d”
printf("%*d", 20- 2*i, yang[i][0]);
其中表示%*d
中的*,是一个标志符号,用来表示跳过它相应的数据。
例如printf("%*d", 4, 6);