题目:
炸弹人:现有一个特殊的关卡:游戏者只有一枚炸弹,且炸弹杀伤距离超长,可以消灭杀伤范围内所有敌人。请问炸弹放在哪个位置才可以消灭最多的敌人(炸弹只能放在空地上)。
输入样例:
13 13
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#…#…G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.###
##G…G…#
#G#.#G###.#G#
#…G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############
输出样例:
将炸弹放置在(9,9),最多可消灭8个敌人
书中给的代码:
#include<stdio.h>
int main(){
char a[20][21];//假设这里的地图大小不超过20*20
int i,j,x,y,n,m,p,q,sum,map =0;
scanf("%d%d",&n,&m);//读入n和m,n表示有多少行字符,m表示每行有多少列
//读入n行字符
for(i =0;i <=n-1;i++){
scanf("%s",a[i]);
}
//用两重循环枚举地图中的每一点
for(i =0;i <=n-1;i++){
for(j =0;j <=m-1;j++){//首先判断这个点是不是平地,是平地才可以被放置炸弹
if(a[i][j] =='.'){
sum =0;//sum用来计数(可以消灭的敌人数),所以需要初始化为零
//将当前坐标i,j复制到两个新变量x、y中,以便向上下左右四个方向分别统计可以消灭的敌人数
//向上统计可以消灭的敌人数
x =i;
y =j;
while(a[x][y] !='#'){//判断是不是墙,如果不是墙就继续
//如果当前点是敌人,则进行计数
if(a[x][y] =='G'){
sum++;
}
//x--的作用是继续向上统计
x--;
}
//向下统计可以消灭的敌人数
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
//x++的作用是继续向下统计
x++;
}
//向左统计可以消灭的敌人数
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
//y--的作用是继续向左统计
y--;
}
//向左统计可以消灭的敌人数
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
//y++的作用是继续向右统计
y++;
}
//更新map的值
if(sum >map){
map =sum;//如果当前点所能消灭的敌人的总数大于map,则更新map
//并用p和q记录当前点的坐标
p =i;
q =j;
}
}
}
}
printf("将炸弹放置在(%d,%d),最多可消灭%d个敌人\n",p,q,map);
getchar();getchar();
return 0;
}
该代码中首先用一个二维字符数组来存储这个地图,并将地图模型化。墙用表示;敌人用表示;空地用.表示。在读入地图时代码中选择使用for循环加%s的方式,即输入字符串到a[i]行,从a[i]行的首地址开始存放;如果我们不选择用这种方式存放地图,而选择使用两层for循环加%c一个字符一个字符的存放呢?
那首先,我们先来看以一下C语言二维字符数组的一些相关知识以及%s和%c的区别。
二维字符数组一般用于存储和处理多个字符串,二维字符数组中的每一行均可存储表示一个字符串。
二维字符数组的定义:
二维字符数组的定义格式为:char 数组名[第一维大小][第二维大小];
如:
char a[3][10];//定义了一个3行10列的二维字符数组a
【例 1】 分析以下程序,输出其运行结果。
#include<stdio.h>
int main (){
char a[3][7] ={"Apple","Orange","Pear"};
int i;
for(i =0;i <3;i++){
printf ("%s\n",a[i]);
}
return 0;
}
该数组各元素中的值如下所示:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
a[0] | A | p | p | l | e | \0 | \0 |
a[1] | O | r | a | n | g | e | \0 |
a[2] | P | e | a | r | \0 | \0 | \0 |
printf ("%s\n",c[0]); //输出Apple
printf ("%s\n",c[1]); //输出Orange
printf ("%s\n",c[2]); //输出Pear
运行结果:
以下均是对二维字符数组元素的合法引用:
char a[][7]={“Apple”,“Orange”,“Pear”};
- printf ("%c",a[1][4]); //输出2行5列元素’g’字符
- scanf ("%c",&a[2][3]);//存放一个字符到3行4列元素中
- a[2][0]=‘P’; //把字符赋值给3行1列元素
- printf ("%s",a[1]);//a[1]为第2行的数组名(首元素地址)输出Orange
- scanf ("%s",a[2]);//存放字符串到a[2]行,从a[2]行的首地址开始存放
字符数组的输入除了使用scanf外,还可以使用getchar或gets;其输出除了使用printf外,还可以使用putchar或puts。
scanf输入与printf输出:scanf和printf对字符类型有%c和%s两种格式,其中%c用来输入单个字符,%s用来输入一个字符串并存在字符数组里;%c格式能够识别空格与换行符并将其输入,而%s通过换行符或空格来识别一个字符串的结束。
#include<stdio.h>
int main(){
char a[10];
scanf("%s",a);//scanf中%s输入通过空格或者换行识别字符串的结束
printf("%s",a);
return 0;
}
运行结果:
#include<stdio.h>
int main(){
char c1,c2,c3;
scanf("%c%c%c",&c1,&c2,&c3);
printf("%c %c %c\n",c1,c2,c3);
return 0;
}
运行结果:
#include<stdio.h>
int main(){
char c1,c2,c3;
scanf("%c %c %c",&c1,&c2,&c3);
printf("%c %c %c\n",c1, c2, c3);
return 0;
}
运行结果:
以上两种情况,都输入a b c,但运行结果却不一样。因为示例1中,scanf的%c格式可以识别空格和换行并将其输入。那示例2为什么又可以了呢?因为scanf里“ ”内的东西表示格式。
getchar输入与putchar输出:getchar与putchar分别用来输入和输出单个字符,都能够识别空格和换行。
#include<stdio.h>
int main(){
char a[5][5];
for(int i =0;i <3;i++){
for(int j =0;j <3;j++){
a[i][j] =getchar();//这里的作用与下句一样
//scanf("%c",&a[i][j]);
}
getchar();//为了把输入中每行末尾的换行符吸收掉
}
printf("----------------------\n");
for(int i =0;i <3;i++){
for(int j =0;j <3;j++){
putchar(a[i][j]);//这里的作用与下句一样
//printf("%c",a[i][j]);
}
putchar('\n');
}
return 0;
}
运行结果:
gets输入与puts输出:gets用来输入一行字符串(注意:gets识别换行符\n作为输入结束,因此scanf完一个整数后,如果要使用gets,需要先用getchar接收整数后的换行符),并将其存放于一维数组或二维数组中的一维中;puts用来输出一行字符串,即将一维数组(或二维数组的一维)在界面上输出,并紧跟一个换行
#include<stdio.h>
int main(){
char a1[20];
char a2[5][10];
int i;
printf("输入字符串存入一维数组中:\n");
gets(a1);
printf("输入3个字符串分别存入二维数组的一维中:\n");
for (i = 0; i < 3; i++){
gets(a2[i]);
}
printf("一维数组a1:\n");
puts(a1);
printf("二维数组a2:\n");
for (i = 0; i < 3; i++){
puts(a2[i]);
}
return 0;
}
运行结果:
现在,我们已经了解了%s和%d的输入输出区别,我们再用两层for循环加%c一个字符一个字符的存放炸弹人的地图试试。
#include<stdio.h>
int main(){
char a[20][21];
int i,j,x,y,n,m,p,q,sum,map =0;
scanf("%d%d",&n,&m);
getchar();//吸收在输入样例中的n,m时后面敲入的回车,否则会被%c识别并存入地图中
for(i =0;i <n;i++){
for(j =0;j <m;j++){
scanf("%c",&a[i][j]);//这里的作用与下一句一样
//a[i][j] =getchar();
}
getchar();
}
for(i =0;i <n;i++){
for(j =0;j <m;j++){
if(a[i][j] =='.'){
sum =0;
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
x--;
}
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
x++;
}
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
y--;
}
x =i;
y =j;
while(a[x][y] !='#'){
if(a[x][y] =='G'){
sum++;
}
y++;
}
if(sum >map){
map =sum;
p =i;
q =j;
}
}
}
}
printf("将炸弹放置在(%d,%d),最多可消灭%d个敌人\n",p,q,map);
getchar();getchar();
return 0;
}
运行结果: