本来写这个游戏是为了做个迷宫求解的算法,结果被做成这个了;一直路径绘制还是用的寻路的算法,今天改了改,改成实际的连线路径,因为有2位说过寻路路径太不顺眼;
连连看.net到今天为止,我已经努力满足了大多数用过的朋友的要求,如果还有什么不满意的,只能说我尽力了;连连看的核心无非就是寻折点(这个不同于寻路),具体的实现可以看到关键的方法“CheckOneCorner”函数,它是寻找一个折点的目标,关于折点换算说出来是很简单的,还是看『
using System;
using System.Drawing;
using System.Collections;
namespace LLK.AI

{

/**//// <summary>
/// 连连看的连线算法
/// 作者:随飞
/// 编写日期:2005-6-6
/// 首先是 x to x ,这个是横向比较直连
/// 然后是 y to y ,这个是竖向比较直连
///
/// 然后是 1个折点
/// 算法很简单;比如
/// 7x3的
/// 0001000
/// 0000000
/// 0000001
///
/// p1 是 3,0
/// p2 是 6,2
///
/// 那么折点是
/// 000100x
/// 0000000
/// 000x001
/// 折点1是 6,0 ,折点2是 3,2
/// 注意这个值和p1,p2的比较,是不是很简单,折点出来了,就可以比较x/y直线了,如果成立则通过.
///
/// 2折就复杂一点,在上面都不成立后,
/// 一次根据上下左右分别按1折算法再比较即可.
/// </summary> 
public class TestPath



{
int pathPointCount = 0;

ArrayList PathRecord =
new ArrayList();
int[,] map =
null;
//地图

Point startPos;
//起点

Point endPos;
//终点

public TestPath()

{;}

public TestPath(Point StartPos,Point EndPos,
int[,] Map)



{
this.startPos = StartPos;
this.endPos = EndPos;
this.map = Map;

}


private void EmptyPathRecord()



{

PathRecord.Clear();

PathRecord.TrimToSize();

PathRecord.Add(
this.startPos);

PathRecord.Add(
this.endPos);

}

private bool IsEmptyPoint(Point p)



{
return this.map[p.X,p.Y]==0;

}

private bool CheckHorizontal(Point p1,Point p2)



{
return this.CheckHorizontal(p1,p2,
false);

}

private bool CheckHorizontal(Point p1,Point p2,
bool isAddPath)



{
//检查水平,x位移,y相同

Point sp = p1.X<p2.X?p1:p2;

Point ep = p2.X<p1.X?p1:p2;

for(
int x =sp.X+1;x<ep.X;x++)



{
//允许记录
if(isAddPath)



{
this.PathRecord.Add(
new Point(x,p1.Y));

}
//不可通过
if(map[x,p1.Y]!=0)
return false;

}

return true;

}

private bool CheckVertical(Point p1,Point p2)



{
return CheckVertical(p1,p2,
false);

}

private bool CheckVertical(Point p1,Point p2,
bool isAddPath)



{
//检查垂直,y位移,x相同

Point sp = p1.Y<p2.Y?p1:p2;

Point ep = p2.Y<p1.Y?p1:p2;

for(
int y =sp.Y+1; y<ep.Y; y++)



{
//允许记录
if(isAddPath)



{
this.PathRecord.Add(
new Point(p1.X,y));

}
//不可通过
if(map[p1.X,y]!=0)
return false;

}

return true;

}

private bool CheckOneCorner(Point p1,Point p2)



{
return CheckOneCorner(p1,p2,
true,
true);

}
private bool CheckOneCorner(Point p1,Point p2,
bool isAddPath,
bool isClear)



{
//计算夹角

//取起始x

Point CrossStart;

Point CrossEnd;

if(p1.X<p2.X)



{

CrossStart = p1;

CrossEnd = p2;

}
else 


{

CrossStart = p2;

CrossEnd = p1;

}

//交叉点X
//正向

Point CrossX ;
//交叉点Y
//反向

Point CrossY ;

if(CrossStart.Y<CrossEnd.Y)



{

CrossX =
new Point(

Math.Max(CrossStart.X,CrossEnd.X),

Math.Min(CrossStart.Y,CrossEnd.Y)

);

CrossY =
new Point(

Math.Min(CrossStart.X,CrossEnd.X),

Math.Max(CrossStart.Y,CrossEnd.Y)

);

}
else 


{

CrossX =
new Point(

Math.Min(CrossStart.X,CrossEnd.X),

Math.Min(CrossStart.Y,CrossEnd.Y)

);

CrossY =
new Point(

Math.Max(CrossStart.X,CrossEnd.X),

Math.Max(CrossStart.Y,CrossEnd.Y)

);

}

//检查交叉点是否为可通过
if(!
this.IsEmptyPoint(CrossX) && !
this.IsEmptyPoint(CrossY))
return false;

//检查交叉点X
if(
this.IsEmptyPoint(CrossX))



{
//检查横位
if(CrossStart.Y<CrossEnd.Y)



{
//方向为~|
if(
this.CheckHorizontal(CrossStart,CrossX) &&
this.CheckVertical(CrossX,CrossEnd))



{
//允许清空
if(isClear)



{
this.EmptyPathRecord();

}
//允许记录
if(isAddPath)



{
this.PathRecord.Add(CrossX);
//记录当前交叉点

}
return (
this.CheckHorizontal(CrossStart,CrossX,
true) &&
this.CheckVertical(CrossX,CrossEnd,
true));

}
//不跳出,留下一点检测

}
else 


{
//方向为|~
if(
this.CheckHorizontal(CrossX,CrossEnd) &&
this.CheckVertical(CrossX,CrossStart))



{
//允许清空
if(isClear)



{
this.EmptyPathRecord();

}
//允许记录
if(isAddPath)



{
this.PathRecord.Add(CrossX);
//记录当前交叉点

}
return (
this.CheckHorizontal(CrossX,CrossEnd,
true) &&
this.CheckVertical(CrossX,CrossStart,
true));

}
//不跳出,留下一点检测

}


}

//检查交叉点Y
if(
this.IsEmptyPoint(CrossY))



{
//检查竖位
if(CrossStart.Y<CrossEnd.Y)



{
//方向为|_
if(
this.CheckVertical(CrossStart,CrossY) &&
this.CheckHorizontal(CrossY,CrossEnd))



{
//允许清空
if(isClear)



{
this.EmptyPathRecord();

}
//允许记录
if(isAddPath)



{
this.PathRecord.Add(CrossY);
//记录当前交叉点

}
return (
this.CheckVertical(CrossStart,CrossY,
true) &&
this.CheckHorizontal(CrossY,CrossEnd,
true));

}

}
else 


{
//方向_|
if(
this.CheckVertical(CrossEnd,CrossY) &&
this.CheckHorizontal(CrossY,CrossStart))



{
//允许清空
if(isClear)



{
this.EmptyPathRecord();

}
//允许记录
if(isAddPath)



{
this.PathRecord.Add(CrossY);
//记录当前交叉点

}
return (
this.CheckVertical(CrossEnd,CrossY,
true) &&
this.CheckHorizontal(CrossY,CrossStart,
true));

}

}


}

return false;
//全部不成立,留给2次折点检测

}

private bool CheckTwoCornerLeft(Point p1,Point p2,
bool isAddPath)



{
//左
//清空记录
this.EmptyPathRecord();
for(
int x = p1.X -1; x>-1; x--)



{
if(
this.map[x,p1.Y]!=0)
return false;
//允许记录
if(isAddPath)



{
this.PathRecord.Add(
new Point(x,p1.Y));

}

//不允许清空
if(
this.CheckOneCorner(
new Point(x,p1.Y),p2,
false,
false))



{
return this.CheckOneCorner(
new Point(x,p1.Y),p2,isAddPath,
false);

}

}

return false;

}

private bool CheckTwoCornerRight(Point p1,Point p2,
bool isAddPath)



{
//右
//清空记录
this.EmptyPathRecord();
for(
int x = p1.X +1; x<
this.map.GetLength(0); x++)



{
if(
this.map[x,p1.Y]!=0)
return false;
//允许记录
if(isAddPath)



{
this.PathRecord.Add(
new Point(x,p1.Y));

}

//不允许清空
if(
this.CheckOneCorner(
new Point(x,p1.Y),p2,
false,
false))



{
return this.CheckOneCorner(
new Point(x,p1.Y),p2,isAddPath,
false);

}

}

return false;

}

private bool CheckTwoCornerUp(Point p1,Point p2,
bool isAddPath)



{
//上
//清空记录
this.EmptyPathRecord();
for(
int y = p1.Y -1; y>-1; y--)



{
if(
this.map[p1.X,y]!=0)
return false;
//允许记录
if(isAddPath)



{
this.PathRecord.Add(
new Point(p1.X,y));

}

//不允许清空
if(
this.CheckOneCorner(
new Point(p1.X,y),p2,
false,
false))



{
return this.CheckOneCorner(
new Point(p1.X,y),p2,isAddPath,
false);

}

}

return false;

}

private bool CheckTwoCornerDown(Point p1,Point p2,
bool isAddPath)



{
//下
//清空记录
this.EmptyPathRecord();
for(
int y = p1.Y +1; y<
this.map.GetLength(1); y++)



{
if(
this.map[p1.X,y]!=0)
return false;
//允许记录
if(isAddPath)



{
this.PathRecord.Add(
new Point(p1.X,y));

}

//不允许清空
if(
this.CheckOneCorner(
new Point(p1.X,y),p2,
false,
false))



{
return this.CheckOneCorner(
new Point(p1.X,y),p2,isAddPath,
false);

}

}

return false;

}

private void CopyArrayListTo(
ref ArrayList srcAl,
ref ArrayList destAl)



{

destAl.Clear();

destAl.TrimToSize();

foreach(Point p
in srcAl)



{

Point newPnt =
new Point(p.X,p.Y);

destAl.Add(newPnt);

}

}

private bool CheckTwoCorner(Point p1,Point p2)



{

//取起始x

Point CrossStart;

Point CrossEnd;

if(p1.X<p2.X)



{

CrossStart = p1;

CrossEnd = p2;

}
else 


{

CrossStart = p2;

CrossEnd = p1;

}

//这里为寻找最短路径的算法
//方法很简单,因为当前的起点方向不确定,可以选择重复尝试能成功的起点
//然后找到路径最少的

//测试4次,寻找最短的路径

ArrayList[] backFindPath =
new ArrayList[4];
bool isFind =
false;
int nextPathList=0;
while(nextPathList<4)



{

backFindPath[nextPathList] =
null;

if(
this.CheckTwoCornerUp(CrossStart,CrossEnd,
false))



{
this.PathRecord.Clear();
this.CheckTwoCornerUp(CrossStart,CrossEnd,
true);

backFindPath[nextPathList] =
new ArrayList();

CopyArrayListTo(
ref this.PathRecord,
ref backFindPath[nextPathList]);

isFind =
true;

nextPathList ++;

}

if(
this.CheckTwoCornerDown(CrossStart,CrossEnd,
false))



{
this.PathRecord.Clear();
this.CheckTwoCornerDown(CrossStart,CrossEnd,
true);

backFindPath[nextPathList] =
new ArrayList();

CopyArrayListTo(
ref this.PathRecord,
ref backFindPath[nextPathList]);

isFind =
true;

nextPathList ++;

}

if(
this.CheckTwoCornerLeft(CrossStart,CrossEnd,
false))



{
this.PathRecord.Clear();
this.CheckTwoCornerLeft(CrossStart,CrossEnd,
true);

backFindPath[nextPathList] =
new ArrayList();

CopyArrayListTo(
ref this.PathRecord,
ref backFindPath[nextPathList]);

isFind =
true;

nextPathList ++;

}

if(
this.CheckTwoCornerRight(CrossStart,CrossEnd,
false))



{
this.PathRecord.Clear();
this.CheckTwoCornerRight(CrossStart,CrossEnd,
true);

backFindPath[nextPathList] =
new ArrayList();

CopyArrayListTo(
ref this.PathRecord,
ref backFindPath[nextPathList]);

isFind =
true;

nextPathList ++;

}

//没有结果
if(!isFind)
break;

}

//有结果返回
if(isFind)



{
//检查起点最小数
int minCount = 0;
//记录位
int index = 0;
for(
int i=0;i<4;i++)



{
if(backFindPath[i]!=
null)



{
if(backFindPath[i].Count>0)



{
if(minCount==0)



{

minCount=backFindPath[i].Count;

index = i;

}
else if(backFindPath[i].Count<minCount)



{

minCount = backFindPath[i].Count;

index = i;

}

}

}

}

//回复属性数据
this.PathRecord.Clear();
this.PathRecord.TrimToSize();

CopyArrayListTo(
ref backFindPath[index],
ref this.PathRecord);

return true;

}

return false;

}


public bool Execute()



{

pathPointCount = -1;
//检查目标位置是否一样
if(
this.startPos.X==
this.endPos.X &&
this.startPos.Y==
this.endPos.Y)



{

pathPointCount = -1;
return false;

}

//检查为同一横坐标
if(
this.startPos.Y==
this.endPos.Y)
if(
this.CheckHorizontal(
this.startPos,
this.endPos))



{
this.EmptyPathRecord();

pathPointCount = 1;
return (
this.CheckHorizontal(
this.startPos,
this.endPos,
true));

}

//检查为同一纵坐标
if(
this.startPos.X==
this.endPos.X)
if(
this.CheckVertical(
this.startPos,
this.endPos))



{
this.EmptyPathRecord();

pathPointCount = 1;
return (
this.CheckVertical(
this.startPos,
this.endPos,
true));

}

//检查一个折点
if(
this.CheckOneCorner(
this.startPos,
this.endPos))



{

pathPointCount =2;
return true;

}

//检查两个折点
if(
this.CheckTwoCorner(
this.startPos,
this.endPos))



{

pathPointCount =3;
return true;

}

return false;

}


/**//// <summary>
/// 起点坐标
/// </summary>
public Point StartPosition



{
get 


{
return this.startPos;

}
set 


{
this.startPos = value;

}

}


/**//// <summary>
/// 终点坐标
/// </summary>
public Point EndPosition



{
get 


{
return this.endPos;

}
set 


{
this.endPos = value;

}

}

/**//// <summary>
/// 地图数据
/// </summary>
public int[,] MapData



{
get 


{
return this.map;

}
set 


{
this.map = value;

}

}

/**//// <summary>
/// 获取折点数
/// </summary>
public int PathPointCount



{
get 


{
return this.pathPointCount;

}

}


/**//// <summary>
/// 获取路径表
/// </summary>
public Point[] PathPointList



{
get 


{
if(
this.PathRecord.Count>=0)



{

Point[] tmpPointList =
new Point[
this.PathRecord.Count];
int i = 0;
foreach(Point p
in this.PathRecord)



{

tmpPointList[i] = p;

i++;

}
return tmpPointList;

}
else 


{
return null;

}

}

}

public ArrayList PathPointArray



{
get 


{
return this.PathRecord;

}

}


}

}
本文转自suifei博客园博客,原文链接:http://www.cnblogs.com/Chinasf/archive/2005/06/06/169153.html,如需转载请自行联系原作者