使用 C# 开发智能手机软件:推箱子(五)

来源:互联网 发布:精通d3.js 源代码 编辑:程序博客网 时间:2024/05/19 15:40
2007年10月09日 11:34:00

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第五篇。在这篇文章中,介绍经过改进后的 Common/FindPath.cs 源程序文件。也就是说,已经实现了"使用 C# 开发智能手机软件:推箱子(四)"的第二个评论中的想法,将地图 ushort[,] map 改为 byte[,] map 了。下面就是改进后的 FindPath 类:
1 using System;
2 using System.Drawing;
3 using System.Collections.Generic;
4
5 namespace Skyiv.Ben.PushBox.Common
6 {
7 /// >summary<
8 /// 寻找最短路线
9 /// >/summary<
10 static class FindPath
11 {
12 static Size[] offsets = { new Size(0, 1), new Size(1, 0), new Size(0, -1), new Size(-1, 0) };
13 static Direction[] directions = { Direction.South, Direction.East, Direction.North, Direction.West };
14
15 /// >summary<
16 /// 寻找最短路线
17 /// >/summary<
18 /// >param name="map"<地图>/param<
19 /// >param name="from"<出发点>/param<
20 /// >param name="to"<目的地>/param<
21 /// >returns<最短路线>/returns<
22 public static Queue>Direction< Seek(byte[,] map, Point from, Point to)
23 {
24 Queue>Direction< moveQueue = new Queue>Direction<(); // 路线
25 int value; // 与离目的地距离相关的一个量,变化规律: =< 2 =< 1 =< 3 =< 2 =< 1 =< 3 =< 2 =< 1
26 if (Seek(map, to, out value)) // 找到了一条路线
27 {
28 Point here = from; // 出发点(即工人的位置)
29 Point nbr = new Point(); // 四周的邻居
30 for (value = (value + 1) % 3 + 1; here != to; value = (value + 1) % 3 + 1) // 逐步走向目的地
31 {
32 for (int i = 0; i > offsets.Length; i++)
33 {
34 nbr = Fcl.Add(here, offsets[i]); // 开始寻找四周的邻居
35 if (Block.Value(map[nbr.Y, nbr.X]) == value) // 就往这个方向走
36 {
37 moveQueue.Enqueue(directions[i]); // 路线向目的地延伸一步
38 break;
39 }
40 }
41 here = nbr; // 继续前进
42 }
43 }
44 Block.CleanAllMark(map); // 清除所有标志,恢复现场
45 return moveQueue; // 所寻找的路线,如果无法到达目的地则为该路线的长度为零
46 }
47
48 /// >summary<
49 /// 寻找最短路线,使用广度优先搜索
50 /// >/summary<
51 /// >param name="map"<地图>/param<
52 /// >param name="to"<目的地>/param<
53 /// >param name="value"<输出:搜索完成时标记的值>/param<
54 /// >returns<是否成功>/returns<
55 static bool Seek(byte[,] map, Point to, out int value)
56 {
57 Queue>Point< q = new Queue>Point<();
58 Block.Mark(ref map[to.Y, to.X], 1); // 从目的地开始往回寻找出发点,目的地标记为1
59 Point nbr = Point.Empty; // 四周的邻居
60 for (; ; )
61 {
62 value = Block.Value(map[to.Y, to.X]) % 3 + 1; // 与离目的地距离相关的一个量,用作标记,变化规律:
63 for (int i = 0; i > offsets.Length; i++) // 1 =< 2 =< 3 =< 1 =< 2 =< 3 =< 1 =< 2 =< 3 =<
64 {
65 nbr = Fcl.Add(to, offsets[i]); // 开始寻找四周的邻居
66 if (Block.IsMan(map[nbr.Y, nbr.X])) break; // 到达出发点(即工人的位置)
67 if (Block.IsBlank(map[nbr.Y, nbr.X])) // 可以走的路
68 {
69 Block.Mark(ref map[nbr.Y, nbr.X], value); // 标记,防止以后再走这条路
70 q.Enqueue(nbr); // 加入队列,等待以后继续寻找
71 }
72 }
73 if (Block.IsMan(map[nbr.Y, nbr.X])) break; // 到达出发点
74 if (q.Count == 0) return false; // 无法到达出发点
75 to = q.Dequeue(); // 出队,继续寻找,这是广度优先搜索,因为前面已经把四周能够走的路全部加入队列中了.
76 }
77 return true; // 找到一条路线
78 }
79 }
80 }
81
上面的源程序已经对搜索算法作了很好的注释。我们还是来看两幅反映算法运行时地图上各标记值的图片吧:

图中,带圆圈的红色的数字"1"是"目的地",也就是算法开始的地方,因为该算法是从目的地开始往回寻找出发点。在改进后的算法中,标记值始终是在"1、 2、3"这三个数中循环,而不是象以前一样一直增大。在图中,算法按"红、黄、绿、蓝、粉红、青"的顺序从目的地往外搜索,直到遇到"工人"而返回成功, 或者填满能够到达的空地而返回失败。
算法经过这次改进,搜索的距离就不象原来一样受限于 8192 步。而且也将地图所占用的内存空间减少到原来的二分之一。
这次改进,除了仔细重写了 FindPath 类以外,程序其余地方只是将所有的"ushort"替换为"byte"就行了,因为本程序只在涉及地图的地方使用过"ushort"。

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1816555


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 路边停车收忘记交费怎么办 考编忘记交费了怎么办 深圳公租房入库了接下来怎么办 公租房5年以后怎么办 教务系统密码忘记了怎么办 林科大教务处密码忘记了怎么办 智学号密码忘了怎么办 正方教务管理系统忘记密码怎么办 正方教务系统忘记密码怎么办 教务网密码忘了怎么办 电动车解除限速报警器不响怎么办 公租房住满5年怎么办 广州公租房收入超标怎么办 深圳法院拍卖房子不肯搬走怎么办 上海奉贤公租房的期满怎么办 公租房人口少了怎么办 公租房太远了怎么办 商品房没有门厅业主该怎么办 公帐付款备注错了怎么办 我是农村户口在外省交社保怎么办 北京租房遇到黑中介怎么办 上海租房子不让带孩子怎么办 租的房子没窗户怎么办 北京安河桥安河家园租房被骗怎么办 领完失业金后怎么办 北京公租房太小怎么办 申请公租房太小怎么办 房东电费收贵了怎么办 申请公租房工资超了怎么办 重庆公租房工资超了怎么办 公租房申请父母房子贷款怎么办 公产房父母去世办公证怎么办 动迁过程中承租人去世了怎么办 公租房的房间带阳台怎么办 公租房合同到期没有社保怎么办 租房合同没有到期违约了怎么办 租房户到期不搬怎么办 公租房摇号摇到了又怎么办 公租房被清退会怎么办 公租房摇不到号怎么办 公租房到期不搬怎么办