您的位置:首页 > 其它

利用.Net的stack泛型类实现迷宫

2010-11-25 10:00 232 查看
约定如下:
以如下迷宫介绍几个概念:
0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0
0 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0
0 0 0 1 1 0 0 0
0 0 0 0 1 1 0 0
0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0
其中红色的为外墙
黑色地为迷宫通道
蓝色的为内墙

迷宫的行数 列数为:8,8
迷宫内部墙单元个数(即为上图中蓝色元素的个数):25
迷宫内部内墙的单元行数列数:
1,2
1,3
1,4
1,5
1,6
2,3
2,4
2,5
2,6
3,1
3,4
3,5
3,6
4,1
4,2
4,5
4,6
5,1
5,2
5,3
5,6
6,1
6,2
6,3
6,4
入口的行数和列数:1,1
入口的行数和列数:6,6

代码如下:

迷宫类
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Drawing;
namespace ConsoleApplication2
{
class Maze
{
////迷宫入口
//public Point begin;
////迷宫出口
//public Point end;
public Stack<selemType> s;

//迷宫搜索移动的方向(point.x指行增量 point.y指列增量) 移动方向依次为东南西北
public Point[] direc = new Point[4] {new Point(0,1),new Point(1,0),new Point(0,-1),new Point(-1,0)};
//迷宫数组int[][]
public int[,] m;
//迷宫的行数和列数
public int x;
public int y;
//当前足迹 初始(在入口处)化为1
public int curstep = 1;

//栈的元素类型
public struct selemType
{
//通道在路径上的“序号”
public int ord;
//通道块在迷宫中的“坐标位置”
public Point seat;
//从此通道走向下一通道的方向(1-3表示东南西北)
public int di;
}

//输出迷宫 在控制台上打印
public void Print()
{
int i, j;
for (i = 0; i < x; i++)
{
for(j=0;j<y;j++)
{
Console.Write(m[i,j].ToString()+" ");
}
Console.WriteLine();

}
}
//初始化迷宫
public void Init()
{
//设定迷宫布局(墙值为0,通道为1)
int i, j, x1, x2;
Console.WriteLine("请输入迷宫的行数 列数并以“,”隔开(包括外墙)");
//接收输入的值
string c = Console.ReadLine();
//分割字符串
string[] d = c.Split(new char[]{','},3);
//将值付给迷宫行数和列数
x = Convert.ToInt32(d[0].ToString());
y = Convert.ToInt32(d[1].ToString());

//初始化迷宫
m = new int[x, y];

//定义外墙周边值为0
for (i = 0; i < y;i++ )
{
m[0, i] = 0;//上边外墙
m[x - 1, i] = 0;//下边外墙
}
for (i= 0; i< x-1; i++)
{
m[i, 0] = 0;//左边外墙
m[i, y-1] = 0;//右边外墙
}
//除外墙外其余地方设置为通道 值设置为1
for (i = 1; i < x - 1;i++ )
{
for (j = 1; j < y - 1; j++)
m[i, j] = 1;
}

//设置迷宫内部墙单元个数
Console.WriteLine("设置迷宫内部墙单元个数:");
c = Console.ReadLine();
j = Convert.ToInt32(c);

//迷宫内部内墙的单元为0
for (i = 0; i < j; i++)
{
Console.WriteLine("请输入迷宫内部内墙的单元行数 列数并以“,”隔开");
c = Console.ReadLine();
//分割字符串
d = c.Split(new char[] { ',' }, 3);
//将值付给迷宫内部内墙的单元行数 列数
x1 = Convert.ToInt32(d[0].ToString());
x2 = Convert.ToInt32(d[1].ToString());
//迷宫内部内墙的单元设为0
m[x1, x2] = 0;

}

//输出初始化的迷宫
Console.WriteLine("输出初始化的迷宫如下:");
Print();

}
//判断迷宫m的b点是否为通道
public bool pass(Point b)
{
if (m[b.X, b.Y] == 1)
return true;
else
return false;
}

//使迷宫m的b点的值变为足迹curstep
public void footPrint(Point b)
{
m[b.X, b.Y] = curstep;
}

//依据当前位置b及移动方向di 修改b为下一个位置
public void nextPos(ref Point b, int di)
{
b.X += direc[di].X;
b.Y += direc[di].Y;
}
//使迷宫m的b点的值变为-1 (标记为经试探由此不能到达终点的路径)
public void markPrint(Point b)
{
m[b.X,b.Y] =-1;
}
//迷宫寻路核心算法
//若迷宫存在从出口到入口的通道,就求一条存放在栈中(从栈底到栈顶),并返回True;否者返回false
public bool mazePath(Point start, Point end)
{
//当前位置设在入口
Point curPos = start;

//实例化一个selemType
selemType elem=new selemType() ;

//声明一个栈并初始化
s = new Stack<selemType>();

//核心算法 核心部分
do
{
//当前位置可以通过,即是未曾走到过的通道块
if (pass(curPos))
{
//留下足迹 (使迷宫的当前位置为curstep)
elem.ord = curstep;
//栈元素的位置为当前位置
elem.seat = curPos;
//从当前位置出发,下一个位置向东
elem.di = 0;
// 入栈当前元素
s.Push(elem);
//足迹加1
curstep++;
//到达终点 返回true结束
if (curPos.X == end.X && curPos.Y == end.Y)
return true;
//由当前位置及移动方向,确定下一个位置,仍付给curPos
nextPos(ref curPos,elem.di);
}
//当前位置不能通过
else
{
//栈不为空
if (s.Count != 0)
{
//退栈到 前一个位置
s.Pop();
//足迹减 1
curstep--;
//前一个位置处于最后一个方向且栈为空
while (elem.di == 3 && s.Count != 0)
{
//在前一位置留下其不能到达终点的标记-1
markPrint(elem.seat);
//再退回一步
s.Pop();
//足迹减1
curstep--;
}
//
if(elem.di<3)
{
//换下一个方向搜索
elem.di++;
//入栈给位置的下一个方向
s.Push(elem);
//足迹加1
curstep++;
//确定当前位置
curPos = elem.seat;
//由当前位置及移动方向,确定下一个位置,仍付给curPos
nextPos(ref curPos,elem.di);
}
}
}
} while (s.Count != 0);

return false;
}

}
}

测试程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace ConsoleApplication2
{
class Program
{

static void Main(string[] args)
{
Maze a=new Maze();
a.Init();
Point begin, end;
//输入入口的行数和列数
Console.WriteLine("输入入口的行数和列数并以“,”隔开");
string c = Console.ReadLine();
//分割字符串
string[] d = c.Split(new char[] { ',' }, 3);
begin = new Point();
//将值付给迷宫内部内墙的单元行数 列数
begin.X = Convert.ToInt32(d[0].ToString());
begin.Y = Convert.ToInt32(d[1].ToString());

//输入出口口的行数和列数
Console.WriteLine("输出口的行数和列数并以“,”隔开");
c = Console.ReadLine();
//分割字符串
d = c.Split(new char[] { ',' }, 3);
//将值付给迷宫内部内墙的单元行数 列数
end = new Point();
end.X = Convert.ToInt32(d[0].ToString());
end.Y = Convert.ToInt32(d[1].ToString());
if (a.mazePath(begin, end))
{
Console.WriteLine("迷宫的其中一个路径如下:");
foreach (var ob in a.s)
{
Console.Write("({0},{1})<----------",ob.seat.X,ob.seat.Y);
}
}
else
{
Console.WriteLine("迷宫的无出路!!!");
}
Console.ReadKey();

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: