虽然说昨天应该继续引擎方面的东西,然而我实现逆向A*路径搜索算法的过程中,又遇到了C#的问题,于是又回到了C#语言方面来了....昨天半夜还没写完就睡了...
问题告急:
- 如何读取和写入文件
- 字符串和数字的相互转换
- 实现了一个可以很方便引用的矩阵
- 实现了==运算符的重载
下面分别讨论吧(当然我只说了我需求中的一些操作,至于其他操作,各位自寻啦~~~~~):
2.1 字符串转数字
这里为什么不按照顺序写呢,因为文件读写操作里要用到这个,再三考虑,我决定不按常理出牌。
字符串转数字非常简单,看代码:
int x = int.Parse(str);
这里str是string类的。我需要转换为 int 的,所以用的是 int.Parse,其他数值类型使用方法相同。
字符串转数字还有一个方法叫做Convert,自寻~~~
2.2 数字转字符串
数字转换为字符串也是支持格式化和流两种方式,我输出的时候对格式是由需求的,所以用的格式化的方式进行输出
string str = string.Format("{0,5}{1,5}\n", x, y);
解释下{0,5}这个东西,他的形式为
{ 参数的序号 , 参数的长度 : 参数的格式 }
就是说 0 是后面序号为 0 的参数,那么这里就是 x,
逗号后面接字符串的长度,我设置为5
1.1 文件的读取
文件方面的操作,和C++的流很像,名字也一样,也叫作流,但是写起来很方便,这也归功于VS2013比较强大的自动补全。
文件操作需要引用IO类库
using System.IO;
判定文件是否存在:
if( ! System.IO.File.Exists( "filename.txt") ) return false;
然后创建文件流,流读取对象
FileStream file = new FileStream("filename.txt", FileMode.Open, FileAccess.Read);
StreamReader reader;
if (file.CanRead)
reader = new StreamReader( file );
else
{
file.Close();
return false;
}
string strLine = reader.ReadLine(); // 读取一行
string[] strs = strLine.Split(' '); // 拆分
int x = int.Parse(strs[0]);
int y = int.Parse(strs[1]);
读取搞定了,别忘了关闭文件和读取流
reader.Close();
file.Close();
1.2 文件的写入
FileStream dataFile = new FileStream(fileName, FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(dataFile);
写入数据,并关闭流
string str = “output”;
sw.Write(str);
sw.Close();
dataFile.Close();
3 很方便的矩阵
那其实就是重载了 [] 运算符
public int this[Coord2 coordIn]
{
get { return data[coordIn.x, coordIn.y]; }
set { data[coordIn.x, coordIn.y] = value;}
}
对于我的类,重载 [] 运算符,使其接受我自定义的坐标数据,大大简化了我的代码,提高了可读性。
这个定义最关键的是形式
public int this[Coord2 coordIn]
以及 get 、set 、value 三个关键字;
get 表示获取该类数据时所返回的,因而引用自定义类的对象数据时,是这样操作的:
cost[checkNode]
即可获取类中data位置(x,y)的数据
而 set 则是赋值的操作了,value 是赋值时等号右边的值,赋值的操作为:
cost[checkNode] = 10;
4. ==运算符的重载
这个是个纠结的东西,参考
https://msdn.microsoft.com/zh-cn/library/ms173147(VS.80).aspx
就是说 == 、!= 、 Equals(两个,一个重定义,一个正常定义)、GetHashCode 这四个东西是绑定的,动其一则动全部
public static bool operator !=(Coord2 a, Coord2 b)
{
return !(a == b);
}
public static bool operator ==(Coord2 a, Coord2 b) /// 我其实只想重载这个
{
if (System.Object.ReferenceEquals(a, b)) return true; /// 这个比较是显式的比较是否为引用相同
if (null == (object)a || null == (object)b) return false; /// 这里一定要 (object),否则无限迭代
return (a.x == b.x && a.y == b.y);
}
public bool Equals(Coord2 a)
{
if (null == a) return false;
return (a.x == x && a.y == y);
}
public override bool Equals(System.Object obj) /// 对底层的方法进行重新定义
{
if (null == obj) return false;
Coord2 inst = obj as Coord2;
if (null == (System.Object)inst) return false;
return (inst.x == x && inst.y == y);
}
public override int GetHashCode()/// 方法不唯一
{
return (x ^ y);
}
多嘴一句,如果这个类不是基类,而是有父类的,那么在返回时还需要考虑 base.Equals,详细见上面的参考链接
最最最后了,学习是要有实践的学习的,所以我也不是光练练代码段的问题,所以呢,我把A*逆向路径搜索算法给实现了,
A*逆向算法功能:
一个2维地图上,1表示障碍物,0表示能通过,从这个地图上的某一个点到另外一个点的最短路径怎么知道呢?A*逆向来帮你。
地图文件说明:
TXT文件,格式为
{
X范围 Y范围
地图数据2维矩阵
}
对X和Y范围做说明:如果X取值是0~5,那么这里是X范围是6,同时地图数据的必须为6列
程序说明:
利用这两天所学知识,把算法实现了,输出了最终的估价矩阵以及最优路径,分别在程序生成的 CostMapOut.txt 和 PathOut.txt 两个文件中;程序的调用方式为(cmd中,切换到程序路径):
PathSearch mapFileName.txt
没有实现文件搜索,所以程序和文件要在同一路径下。
没有实现起始节点和终止节点的输入,需要在程序里修改 beginNode和EndNode 的值。
没有实现起始节点和终止节点的测试,所以请保证 beginNode 和 EndNode 在地图上的值均为 0。
Node的( x, y) 为坐标值,所以对应到矩阵上为 (列,行),不要混淆,程序里全部都是按照坐标的方式引用的,不是矩阵
坐标的范围均为 0~xMax-1,设置 Node 的坐标时注意
文件包说明:
程序是我在另一台电脑上写的,所以代码是重新敲的,没写注释,需要看注释的看 whole.jpg ,图片里有,map.txt 就是我测试时的地图数据文件。
不过,通过这次经历我明显的感觉到高级语言的优势了,这个程序我用MATLAB做了一次,花了3个小时左右就搞定了,而C#连学带做3个晚上(当然学花了很多时间
),对于这种算法的验证来说,没有什么实时性要求,MATLAB确实很适合
昨天结束,哇咔咔~~~