云南大学软件学院数据结构实验报告四.docx
《云南大学软件学院数据结构实验报告四.docx》由会员分享,可在线阅读,更多相关《云南大学软件学院数据结构实验报告四.docx(15页珍藏版)》请在冰豆网上搜索。
![云南大学软件学院数据结构实验报告四.docx](https://file1.bdocx.com/fileroot1/2022-12/12/f8f0b5db-3171-4828-b5a5-3f348e2c0192/f8f0b5db-3171-4828-b5a5-3f348e2c01921.gif)
云南大学软件学院数据结构实验报告四
(本实验项目方案受“教育部人才培养模式创新实验区(X3108005)”项目资助)
实验难度:
A□B√C□
序号
学号
姓名
成绩
1
2
指导教师
(签名)
学 期:
2012秋季学期
任课教师:
实验题目:
迷宫
小组长:
云南大学软件学院2010学年秋季学期
《数据结构实验》成绩考核表
学号:
姓名:
本人承担角色:
学号:
姓名:
本人承担角色:
评分项目
评分指标
分值
得分
实验构思(10%)
1.实验目的明确
5
2.实验内容理解透彻、对实验所涉及到的知识点分析到位
5
实验设计(15%)
1.有对基本数据结构的抽象数据类型定义
5
2.实验方案设计完整,数据结构、算法选择合理
5
3.算法结构和程序功能模块之间逻辑清晰、有相应的流程图
5
实验实现(25%)
1.代码编写规范、风格统一、注释清楚易读
5
2.程序运行正常,测试结果正确
15
3.界面友好、易于操作、有较强的容错性
5
实验报告撰写(10%)
1.内容详实无缺漏,文字流畅、图表清楚
5
2.实验结果分析客观、详细,实验体会真实可信,对原实验方案的改进和对实验内容的发散性思考
5
个人工作量(30%)
1.个人完成工作量
15
2.个人技术水平
10
3.团队合作精神
5
实验运作(10%)
1.有一定用户群
5
2.应用前景分析
5
综合得分:
(满分100分)
指导教师:
(注:
此表在难度为C时使用,每个成员一份。
)
(下面的内容由学生填写,格式统一为,字体:
楷体,行距:
固定行距18,字号:
小四,个人报告按下面每一项的百分比打分。
难度A满分70分,难度B满分90分)
一、【实验构思(Conceive)】(10%)
1.创建四个文件,stack.h头文件、queue.h头文件、maze.h头文件和main.cpp主文件
2.栈文件用于在移动玩家位置过程中,将移动的方向保存到栈中。
然后在修改玩家位置时,用出栈的元素判断前方是地图的哪边。
然后将这个元素保存到队列中,等玩家走出迷宫后,输出走过的路径。
3.maze头文件:
(1)迷宫(二位数组)中的元素数据类型为自己构造的maze类型。
里面有二位数组的位置y(行),x(列)、有substance为char类型、有left、right、up、down四个方位,表示二位数组中的绝对坐标关系。
(2)maze*JudgeRight(maze*player,maze*playerF)这个函数是用于传入玩家当前位置和前方位置,来返回右手边的地址。
(3)maze*JudgeFront(maze*player,char&go)这个函数利用玩家的当前位置,和刚刚直走以后的方向,来返回前方的地址。
(4)maze*GoToFront(maze*player,maze*playerF,structstack&S)这个函数是传入玩家的当前位置,前方位置,然后修改当前位置的地址,并返回。
其中还要把移动的方向压入栈中。
5.主文件里面创建10X10的二维数组来表示迷宫,并且初始化迷宫中的元素,确立其绝对坐标,确立绝对的邻居关系。
接下来利用迷宫口诀:
“伸出右手,摸着墙顺着走”,即“如果右手边不是墙,则,右转后直走;如果右手边是墙,前方没墙,则直走;右手边是墙,前方有墙,则左转”,做一个循环,如果玩家到了'u'才结束。
其中有入栈,出栈,入队的操作。
迷宫走出来以后,利用岀队函数输出玩家走过的路径。
二、【实验设计(Design)】(20%)
1.可以直接利用实验三(魔王语言)中的栈和队列头文件。
栈文件用于在maze.h头文件中的一个函数:
maze*GoToFront(maze*&player,maze*&playerF,structstack&S)
这个函数是在移动玩家位置过程中,将移动的方向保存到栈中。
然后在修改玩家的前方位置时,用出栈的元素判断前方是地图的哪边。
然后将这个元素保存到队列中,等玩家走出迷宫后,输出走过的路径。
2.maze头文件:
(1)迷宫(二位数组)中的元素数据类型为自己构造的maze类型。
里面有二位数组的位置y(行),x(列),这样表示的方便是能直观利用坐标。
元素中还有substance为char类型,其中有'w'表示墙、'e'表示空、'p'表示玩家、'u'表示出口。
还有left、right、up、down四个方位,表示二位数组中的绝对坐标关系。
(5)maze*JudgeRight(maze*player,maze*playerF)函数:
在里面定义一个maze型指针playerR,然后判断:
如果前方就坐标的下方,那么playerR是坐标中的左方;如果前方就坐标的上方,那么playerR是坐标中的右方;如果前方就坐标的左方,那么playerR是坐标中的上方;如果前方就坐标的右方,那么playerR是坐标中的下方。
然后返回playerR。
(6)maze*JudgeFront(maze*player,char&go)函数:
在里面定义一个maze型指针playerF,传入go(表示刚刚直走的方向),如果上走,palyerF修改成player的上方;如果下走,palyerF修改成player的下方;如果左走,palyerF修改成player的左方;如果右走,palyerF修改成player的右方;返回palyerF。
(7)maze*GoToFront(maze*player,maze*playerF,structstack&S)
直走函数:
根据前方的坐标减去玩家当前坐标,然后得出x,y的值。
如果x为1,向右走;x为-1,向左走;y为1,向下走;y为-1,向上走;然后将所走的方向用char表示成'U','D','L','R'压住栈中。
将玩家的前方赋值给变化后的位置,返回变化后的玩家位置。
3.主文件里面创建10X10的二维数组来表示迷宫,并且初始化迷宫中的元素,确立其绝对坐标,确立绝对的邻居关系。
首先是定义二维数组:
mazemazeArr[10][10](非指针类型);
初始化:
(1)访问二维数组的每一个元素,确立它的绝对坐标(x,y)、其中如果遇到边缘(x==0||y==0||x==9||y==9)时,将其中表示成墙,否则先表示成空。
(2)大量坐标中的元素初始化后,再局部修改,将部分空的地方变成墙。
将(1,1)表示成玩家的初始化位置'p',(8,8)表示成出口'u'。
(3)之后就是定义二位数组的绝对上下左右关系。
特别注意的是如果是二位数组的边缘,那么要注意将边缘中某些方向指针修改成指向NULL的情况。
比如:
当x为0时,表示的是二维数组的第一列,那么将第一列所有元素的左指针都指向NULL,然后再修改其右,上,下指针。
如果x,y都不为0,那么表示的是迷宫的内部(非边缘)。
那么,按照坐标关系,下指针指向(y+1,x)的地址;上指针指向(y-1,x)的地址;右指针指向(y,x+1)的地址;左指针指向(y,x-1)的地址;
(4)接下来利用迷宫口诀:
“伸出右手,摸着墙顺着走”,即“如果右手边不是墙,则,右转后直走;如果右手边是墙,前方没墙,则直走;右手边是墙,前方有墙,则左转”,做一个循环,如果玩家到了'u'才结束。
其中有入栈,出栈,入队的操作。
其中,左转就是3次右转;直走之前将player的substance修改为空,再传直走函数,之后再判断前飞,再来判断右方,然后入队。
而在每次大循环开始前,将玩家的当前位置中的substance修改成'p'。
(5)迷宫走出来以后,利用岀队函数输出玩家走过的路径。
三、【实现描述(Implement)】(30%)
1.二位数组中每个元素的数据结构:
typedefstructmazeS{
charsubstance;
intx,y;
mazeS*left,*right,*up,*down;
}maze;
2.判断玩家的右手边地址函数:
maze*JudgeRight(maze*player,maze*playerF){
maze*playerR;
if(playerF==player->down)
playerR=player->left;
if(playerF==player->up)
playerR=player->right;
if(playerF==player->left)
playerR=player->up;
if(playerF==player->right)
playerR=player->down;
returnplayerR;
}
3.判断前方
maze*JudgeFront(maze*player,char&go){
maze*playerF;
if(go=='U')
playerF=player->up;
if(go=='D')
playerF=player->down;
if(go=='L')
playerF=player->left;
if(go=='R')
playerF=player->right;
returnplayerF;
}
4.直走函数:
maze*GoToFront(maze*&player,maze*&playerF,structstack&S){
chargo;
inty,x;
y=playerF->y-player->y;
x=playerF->x-player->x;
if(y==-1)
go='U';
if(y==1)
go='D';
if(x==-1)
go='L';
if(x==1)
go='R';
PushStack(S,go);
player=playerF;
returnplayer;
}
5.走迷宫的实现:
chargo;
structlinkQueueQ;
InitQueue(Q);
structstackS;
InitStack(S);
maze*player=&mazeArr[1][1];
maze*playerF=player->right;
maze*playerR=JudgeRight(player,playerF);
//开始走迷宫,并做记录
while
(1){
if(player->substance=='u')break;
else{
player->substance='p';
if(playerR->substance=='w'){
if(playerF->substance=='w'){
//左转=右转3次
for(inti=0;i<3;i++){
playerF=playerR;
playerR=JudgeRight(player,playerF);
}
continue;
}
}else{
playerF=playerR;
playerR=JudgeRight(player,playerF);
}
//直走
player->substance='e';
player=GoToFront(player,playerF,S);
PopStack(S,go);
playerF=JudgeFront(player,go);
playerR=JudgeRight(player,playerF);
EnQueue(Q,go);
}
}
五、【测试结果(Testing)】(10%)
实验测试结果均为正确:
测试的输入
测试结果截图
按照课本中的地图
修改(3,5)变为墙
(6,3)变成空
六、【实验总结】(10%)
总结:
这次的实验遇到了三个问题:
一是在修改二位数组的4方向指针的时候,遇到程序崩溃问题,原因是那些指针指向了错误的地址。
然后修改了一下迷宫边缘那些块的4个方向地址,运行才正确。
二是认识了一点,在maze.h文件中已经包含了stack.h,然后main.cpp文件中包含maze.h以后,就不用在main.cpp文件中预读stack.h文件了,不然会导致很多编译错误,其实就是一处错误。
三是通过传递函数,来修改指针指向的地址,目前还没找到方法。
只有通过引用来修改其指向的值,而不能修改地址值。
七、【项目运作描述(Operate)】(10%)
本次试验,可以做进一步改进,就是在输出玩家所走过的路径后,进行dos下的游戏。
玩家输出方向键后,判断方向。
修改二维数组中的相应值就可以了。
利用刷屏技术,实现娱乐的性质。
八、【代码】(10%)
Stack.h和Queue.h头文件代码不再给出,下面是maze.h和mian.cpp文件的代码:
#include"stack.h"
#include"stdlib.h"
#include"stdio.h"
//定义迷宫二位数组中的数据类型结构
typedefstructmazeS{
charsubstance;
intx,y;
mazeS*left,*right,*up,*down;
}maze;
//判断玩家的右手边地址
maze*JudgeRight(maze*player,maze*playerF){
maze*playerR;
if(playerF==player->down)
playerR=player->left;
if(playerF==player->up)
playerR=player->right;
if(playerF==player->left)
playerR=player->up;
if(playerF==player->right)
playerR=player->down;
returnplayerR;
}
//判断玩家的右手边地址
maze*JudgeFront(maze*player,char&go){
maze*playerF;
if(go=='U')
playerF=player->up;
if(go=='D')
playerF=player->down;
if(go=='L')
playerF=player->left;
if(go=='R')
playerF=player->right;
returnplayerF;
}
//直走函数
maze*GoToFront(maze*&player,maze*&playerF,structstack&S){
chargo;
inty,x;
y=playerF->y-player->y;
x=playerF->x-player->x;
if(y==-1)
go='U';
if(y==1)
go='D';
if(x==-1)
go='L';
if(x==1)
go='R';
PushStack(S,go);
player=playerF;
returnplayer;
}
第二个文件:
queue.h主文件代码如下:
#include
#include"queue.h"
#include"maze.h"
#include
#include"stdio.h"
usingnamespacestd;
voidmain(){
mazemazeArr[10][10];
/******************************数组的初始化********************************/
//定义坐标(x,y)并初始化边缘为墙,将内部赋值成空气
for(inti=0;i<10;i++){
for(intj=0;j<10;j++){
if(i==0||i==9||j==0||j==9)
mazeArr[i][j].substance='w';
elsemazeArr[i][j].substance='e';
mazeArr[i][j].x=j;
mazeArr[i][j].y=i;
}
}
//修改内部某些为墙
mazeArr[1][3].substance='w';
mazeArr[1][7].substance='w';
mazeArr[2][3].substance='w';
mazeArr[2][7].substance='w';
mazeArr[3][5].substance='w';
mazeArr[3][6].substance='w';
//实验结果二的修改地图
mazeArr[3][6].substance='e';
mazeArr[5][3].substance='w';
mazeArr[4][2].substance='w';
mazeArr[4][3].substance='w';
mazeArr[4][4].substance='w';
mazeArr[5][4].substance='w';
mazeArr[6][2].substance='w';
mazeArr[6][6].substance='w';
mazeArr[7][2].substance='w';
mazeArr[7][3].substance='w';
mazeArr[7][4].substance='w';
mazeArr[7][6].substance='w';
mazeArr[7][7].substance='w';
mazeArr[8][1].substance='w';
//定义其他标记
mazeArr[1][1].substance='p';
mazeArr[8][8].substance='u';
//定义数组中方向的关系
for(inty=0;y<10;y++){
for(intx=0;x<10;x++){
if(x!
=0&&y!
=0){
mazeArr[y][x].down=&mazeArr[y+1][x];
mazeArr[y][x].up=&mazeArr[y-1][x];
mazeArr[y][x].right=&mazeArr[y][x+1];
mazeArr[y][x].left=&mazeArr[y][x-1];
}
elseif(x==0){
mazeArr[y][x].left=NULL;
mazeArr[y][x].right=&mazeArr[y][x+1];
if(y>0&&y<9){
mazeArr[y][x].up=&mazeArr[y-1][x];
mazeArr[y][x].down=&mazeArr[y+1][x];
}
}
elseif(x==9){
mazeArr[y][x].right=NULL;
mazeArr[y][x].left=&mazeArr[y][x-1];
if(y>0&&y<9){
mazeArr[y][x].up=&mazeArr[y-1][x];
mazeArr[y][x].down=&mazeArr[y+1][x];
}
}
elseif(y==0){
mazeArr[y][x].up=NULL;
mazeArr[y][x].down=&mazeArr[y+1][x];
if(x>0&&x<9){
mazeArr[y][x].left=&mazeArr[y][x-1];
mazeArr[y][x].right=&mazeArr[y][x+1];
}
}
elseif(y==9){
mazeArr[y][x].down=NULL;
mazeArr[y][x].up=&mazeArr[y-1][x];
if(x>0&&x<9){
mazeArr[y][x].left=&mazeArr[y][x-1];
mazeArr[y][x].right=&mazeArr[y][x+1];
}
}
}
}
/*for(inty=1;y<=8;y++){
for(intx=0;x<8;x++){
cout<substance<<"";
}
cout<}*/
/******************************定义玩家指针********************************/
chargo;
structlinkQueueQ;
InitQueue(Q);
structstackS;
InitStack(S);
maze*player=&mazeArr[1][1];
maze*playerF=player->right;
maze*playerR=JudgeRight(player,playerF);
//开始走迷宫,并做记录
while
(1){
if(player->substance=='u')break;
else{
player->substance='p';
if(playerR->substance=='w'){
if(playerF->substance=='w'){
//左转=右转3