/**
* main.c
* 推箱子3.0
*
* Created by LongMa on 15/8/3.
* Copyright (c) 2015年 itcast. All rights reserved
* 功能:
1.各种小bug已解决,比如 推到边缘后小人不再推自己绕到边缘也判定成功的bug……
2.现在可以手动改地图的长,宽了!
* 3.四面都可能又出口,已解决
* 4.箱子推出去才算结束。已解决。
问题:
1.地图尚不能自己生成
2.多个return 0;有没有影响?
* 3.0旨在实现 可手动修改地图大小的目标,done!
* @param map 宏定义 行和列,修改宏定义值,再修改迷宫的大小
*
* @return 成功/失败
*/
#include
#include
#include
#define iLength 8
#define jLength 9
/**
* 打印地图
*
* @param map 存放地图的数组
*/
void printMap(char map[iLength][jLength])
{
for(int i =0; i < iLength;i++)
{
printf("%s\n",map[i]);/* 按行,字符串输出法,简单! */
}
}
/**
* 通过指针实现 交换map数组中两个不同元素中的值
*
* @param map 存放地图的数组
* @param i 原位置行坐标
* @param j 原位置列坐标
* @param iC 下一位置行坐标
* @param jC 下一位置列坐标
*/
void exchange (char map[iLength][jLength],int i, int j, int iC,int jC)
{
char *p= &map[i][j],*pC = &map[iC][jC];
*p = *p ^ *pC;
*pC = *p ^ *pC;
*p = *p ^ *pC;
}
/**
* 判断用户是否把箱子推到角落无法再推了
*
* @param map 存放地图的数组
* @param cX 箱子 行坐标
* @param cY 箱子 列坐标
*
* @return 1:推死了 0:没有推死
*/
int endOrnot(char map[iLength][jLength],int cX,int cY)
{
if ( ( '#' == map[cX - 1][cY] && ('#' == map[cX][cY - 1] || '#' == map[cX][cY + 1]) )
||( '#' == map[cX + 1][cY] && ('#' == map[cX][cY - 1] || '#' == map[cX][cY + 1]) )
)
{
printf("推箱子失败!");
return 1;
}else
{
return 0;
}
}
/**
* 判定推成功时,进行的操作,输出地图和鼓励!
*
* @param map 地图
* @param cX 箱子行坐标
* @param cY 箱子列坐标
* @param bX 小人横坐标
* @param bY 小人列坐标
* @param flagBs 计算步数
*/
void success(char map[iLength][jLength], int cX, int cY, int bX, int bY,int flagBs)
{
map[cX][cY] = map[bX][bY];
map[bX][bY] = ' ';
printMap(map);
printf("哇,只运动了 %d 下就结束了?!\n恭喜您,已获得“终极快男”荣誉称号!",flagBs);
// return 0;//没有意义,要去掉!被调函数返回值 并不能结束主调函数中的循环!
}
/**
* main函数
*
* @param argc 返回 int型 数据
* @param argv 返回 指针数组变量
*
* @return 0
*/
int main(int argc, const char * argv[])
{
/* 1.定义地图并输出,定义 小人和箱子位置 */
char map[iLength][jLength] = {/* ?jLength列是因为要存储‘\0’, iLength也可以?巧了?万一map【0】【iLength】存的不是'\0',程序就失败了 */
"## ###",
"#0 # ##",
"# x ###",
" # ##",
" ##",
" # ",
"## ",
"## #####"
};
char mapBeifen[iLength][jLength] = {/* 备份原始地图,以供推死箱子继续游戏时,刷新地图用 */
"## ###",
"#0 # ##",
"# x ###",
" # ##",
" ##",
" # ",
"## ",
"## #####"
};
int flagBushu = 0;/* 计算用了多少步. */
int justify = 0; /* 标记箱子是否被推死了 */
/* botX,botY: 小人行列坐标, chestX,chestY: 箱子行列坐标 */
int botX = 1, botY = 1, chestX = 2, chestY = 3;/* 初值易错,不是 2 2 3 4 哦!小心,下标从零开始! */
char ctl;/* 接收用户输入的移动按键 */
char answer;/* 按下q后存储玩家回答 */
char restart = 'y';/* 箱子被推死时,接收用户是否重新玩的回答 */
char (*p)[jLength];
p = map;/* p为了刷新地图,新建的指针变量 */
printf("地图如下:\n");
printMap(map);
/* 2.循环 提示玩家输入按键“w:上,s:下,a:左,d:右\n” */
while(2)//或者用 chest != '\0'
{
//* 3.提示并接收按键并 判断(重点,写成单独函数) 是否可以移动或推箱子 */
printf("请按下一个键控制小人移动:w 往上,s 往下,a 往左,d 往右\n");
scanf("%c",&ctl);
flagBushu++;/* 加步数 */
rewind(stdin);/* 清除缓冲区,消除 '\n'对下一次输入的影响。 */
/* switch变量必须用 括号 括起来!规定向下x轴和向右y轴为正方向。xy方向必须这样,因为是按a【i】【j】对应a【x】【y】。
按w时,向上,i变化,不是j!故x设置成列向,y行向!
①每次在switch最后判断箱子是否被推死,推死了提示用户是否重新开始玩。是就刷新地图和参数。否则跳出循环,提示结束。
②遇到路,交换路与小人的位置;更新小人坐标。
③遇到箱子且在推的方向上箱子下一个位置为路(不同方向的出口(左上 有口怎么办?),设置不同解决方案),
则小人和箱子移动(交换箱子与路。再交换小人与路,注意更新它俩的坐标)
④判定 是否 输入的为q、Q,是的话做 是否退出 判定并执行。
*/
switch (ctl)
{
case 'q':
case 'Q':
printf("真的要退出吗?再配淫家玩一会嘛!\n狠心退出请再次按 q ,取消请按其他键。");
scanf("%c",&answer);
rewind(stdin);
if(answer == 'q')
{
printf("臣妾恭送皇上!");
return 0;
}
break;
case 'a':
case 'A':
if(map[botX][botY - 1] == ' ')/* 情况② */
{
exchange (map,botX, botY, botX, botY - 1);
botY --;
}else if(botX == chestX && (botY - 1) == chestY)/* 情况3 */
{
if(map[chestX][chestY - 1] == ' ')
{
exchange (map,chestX, chestY, chestX, chestY - 1);
chestY --;
exchange (map,botX, botY, botX, botY - 1);
botY --;
}else if(0 == chestY) //判定箱子是否在边界,是的话跳出循环,结束
{
success(map, chestX, chestY, botX, botY, flagBushu);
return 0;
}
}
break;
case 'd':
case 'D':
if(map[botX][botY + 1] == ' ')
{
exchange (map,botX, botY, botX, botY + 1);
botY ++;
}else if(botX == chestX && (botY + 1) == chestY)
{
if(map[chestX][chestY + 1] == ' ')
{
exchange (map,chestX, chestY, chestX, chestY + 1);
chestY ++;
exchange (map,botX, botY, botX, botY + 1);
botY ++;
}else if(7 == chestY)
{
success(map, chestX, chestY, botX, botY, flagBushu);
return 0;
}
}
break;
case 'w':
case 'W':
if(map[botX - 1][botY] == ' ')
{
exchange (map,botX, botY, botX - 1, botY);
botX --;
}else if((botX - 1) == chestX && botY == chestY)
{
if (map[chestX - 1][chestY] == ' ')
{
exchange (map,chestX, chestY, chestX - 1, chestY);
chestX --;
exchange (map,botX, botY, botX - 1, botY);
botX --;
}else if (0 == chestX)
{
success(map, chestX, chestY, botX, botY, flagBushu);
return 0;
}
}
break;
case 's':
case 'S':
if(map[botX + 1][botY] == ' ')
{
exchange (map,botX, botY, botX + 1, botY);
botX ++;
}else if((botX + 1) == chestX && botY == chestY)
{
if(map[chestX + 1][chestY] == ' ')
{
exchange (map,chestX + 1, chestY, chestX, chestY);
chestX ++;
exchange (map,botX, botY, botX + 1, botY);
botX ++;
}else if (7 == chestX)
{
success(map, chestX, chestY, botX, botY, flagBushu);
return 0;
}
}
break;
default :
break;/* break;能省去? key:不能!*/
}
/* 4.刷新地图 */
printMap(map);
justify = endOrnot(map, chestX, chestY);/* 判定是否推死了 */
if ( 1 == justify)
{
printf("是否重新来一盘?y/n");
scanf("%c",&restart);
rewind(stdin);
rewind(stdin);/* 多个scanf语句必须加上 */
while ('n' !=restart && 'y' != restart)/* 输错时,提示重新输入 */
{
printf("您的输入错误,请重新输入,继续y/退出n:");
scanf("%c",&restart);
rewind(stdin);
}
if ('y' == restart)/* 重新玩 */
{
/* 初始化地图和参数 */
memcpy(map, mapBeifen, sizeof(mapBeifen));
printf("地图如下:\n");
printMap(map);
flagBushu = 0;
justify = 0;
botX = 1, botY = 1, chestX = 2, chestY = 3;
restart = 'n';
}else/* 退出 */
{
printf("臣妾恭送圣驾~~~\n");
return 0;
}
}
}
/* 5.若箱子遇到出口,输入成功信息 */
//return 0;已经都在while循环里
}