?? findpath.cs
字號(hào):
using System;
using System.Drawing;
using System.Collections.Generic;
namespace Skyiv.Ben.PushBox.Common
{
/// <summary>
/// 尋找最短路線(xiàn)
/// </summary>
static class FindPath
{
static Size[] offsets = { new Size(0, 1), new Size(1, 0), new Size(0, -1), new Size(-1, 0) };
static Direction[] directions = { Direction.South, Direction.East, Direction.North, Direction.West };
/// <summary>
/// 尋找最短路線(xiàn)
/// </summary>
/// <param name="map">地圖</param>
/// <param name="from">出發(fā)點(diǎn)</param>
/// <param name="to">目的地</param>
/// <returns>最短路線(xiàn)</returns>
public static Queue<Direction> Seek(byte[,] map, Point from, Point to)
{
Queue<Direction> moveQueue = new Queue<Direction>(); // 路線(xiàn)
int value; // 與離目的地距離相關(guān)的一個(gè)量,變化規(guī)律: ... => 2 => 1 => 3 => 2 => 1 => 3 => 2 => 1
if (Seek(map, to, out value)) // 找到了一條路線(xiàn)
{
Point here = from; // 出發(fā)點(diǎn)(即工人的位置)
Point nbr = new Point(); // 四周的鄰居
for (value = (value + 1) % 3 + 1; here != to; value = (value + 1) % 3 + 1) // 逐步走向目的地
{
for (int i = 0; i < offsets.Length; i++)
{
nbr = Fcl.Add(here, offsets[i]); // 開(kāi)始尋找四周的鄰居
if (Block.Value(map[nbr.Y, nbr.X]) == value) // 就往這個(gè)方向走
{
moveQueue.Enqueue(directions[i]); // 路線(xiàn)向目的地延伸一步
break;
}
}
here = nbr; // 繼續(xù)前進(jìn)
}
}
Block.CleanAllMark(map); // 清除所有標(biāo)志,恢復(fù)現(xiàn)場(chǎng)
return moveQueue; // 所尋找的路線(xiàn),如果無(wú)法到達(dá)目的地則為該路線(xiàn)的長(zhǎng)度為零
}
/// <summary>
/// 尋找最短路線(xiàn),使用廣度優(yōu)先搜索
/// </summary>
/// <param name="map">地圖</param>
/// <param name="to">目的地</param>
/// <param name="value">輸出:搜索完成時(shí)標(biāo)記的值</param>
/// <returns>是否成功</returns>
static bool Seek(byte[,] map, Point to, out int value)
{
Queue<Point> q = new Queue<Point>();
Block.Mark(ref map[to.Y, to.X], 1); // 從目的地開(kāi)始往回尋找出發(fā)點(diǎn),目的地標(biāo)記為1
Point nbr = Point.Empty; // 四周的鄰居
for (; ; )
{
value = Block.Value(map[to.Y, to.X]) % 3 + 1; // 與離目的地距離相關(guān)的一個(gè)量,用作標(biāo)記,變化規(guī)律:
for (int i = 0; i < offsets.Length; i++) // 1 => 2 => 3 => 1 => 2 => 3 => 1 => 2 => 3 => ...
{
nbr = Fcl.Add(to, offsets[i]); // 開(kāi)始尋找四周的鄰居
if (Block.IsMan(map[nbr.Y, nbr.X])) break; // 到達(dá)出發(fā)點(diǎn)(即工人的位置)
if (Block.IsBlank(map[nbr.Y, nbr.X])) // 可以走的路
{
Block.Mark(ref map[nbr.Y, nbr.X], value); // 標(biāo)記,防止以后再走這條路
q.Enqueue(nbr); // 加入隊(duì)列,等待以后繼續(xù)尋找
}
}
if (Block.IsMan(map[nbr.Y, nbr.X])) break; // 到達(dá)出發(fā)點(diǎn)
if (q.Count == 0) return false; // 無(wú)法到達(dá)出發(fā)點(diǎn)
to = q.Dequeue(); // 出隊(duì),繼續(xù)尋找,這是廣度優(yōu)先搜索,因?yàn)榍懊嬉呀?jīng)把四周能夠走的路全部加入隊(duì)列中了.
}
return true; // 找到一條路線(xiàn)
}
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -