载入中,请稍候……

连连看算法

Admin 于 2008-08-25 06:09:55 发表其它

订阅: http://www.miniboke.com/Feed/Article_3.aspx
引用: http://www.miniboke.com/Trackback/TjTvNmQOMUuvzffoZMnv.aspx (UTF-8)
U盘小偷c++源码 < 连连看算法 > 日期范围计算

2折的时候输出路径时取最短路径

 

  1. using System;  
  2. using System.Drawing;  
  3. using System.Collections;  
  4.   
  5. namespace LLK.AI  
  6. {  
  7.     /**//// <summary>  
  8.     /// 连连看的连线算法  
  9.     /// 作者:随飞  
  10.     /// 编写日期:2005-6-6  
  11.     /// 首先是 x to x ,这个是横向比较直连  
  12.     /// 然后是 y to y ,这个是竖向比较直连  
  13.     ///   
  14.     /// 然后是 1个折点  
  15.     /// 算法很简单;比如  
  16.     /// 7x3的  
  17.     /// 0001000  
  18.     /// 0000000  
  19.     /// 0000001  
  20.     ///   
  21.     /// p1 是 3,0  
  22.     /// p2 是 6,2  
  23.     ///   
  24.     /// 那么折点是  
  25.     /// 000100x  
  26.     /// 0000000  
  27.     /// 000x001  
  28.     /// 折点1是 6,0 ,折点2是 3,2  
  29.     /// 注意这个值和p1,p2的比较,是不是很简单,折点出来了,就可以比较x/y直线了,如果成立则通过.  
  30.     ///   
  31.     /// 2折就复杂一点,在上面都不成立后,  
  32.     /// 一次根据上下左右分别按1折算法再比较即可.  
  33.     /// </summary>  
  34.       
  35.     public class TestPath  
  36.     {  
  37.         int pathPointCount = 0;  
  38.         ArrayList PathRecord = new ArrayList();  
  39.         int[,] map = null//地图  
  40.         Point startPos;    //起点  
  41.         Point endPos;    //终点  
  42.           
  43.         public TestPath(){;}  
  44.   
  45.         public TestPath(Point StartPos,Point EndPos,int[,] Map)  
  46.         {  
  47.             this.startPos = StartPos;  
  48.             this.endPos = EndPos;  
  49.             this.map = Map;  
  50.         }  
  51.   
  52.   
  53.         private void EmptyPathRecord()  
  54.         {  
  55.             PathRecord.Clear();  
  56.             PathRecord.TrimToSize();  
  57.             PathRecord.Add(this.startPos);  
  58.             PathRecord.Add(this.endPos);  
  59.         }  
  60.   
  61.         private bool IsEmptyPoint(Point p)  
  62.         {  
  63.             return this.map[p.X,p.Y]==0;  
  64.         }  
  65.   
  66.         private bool CheckHorizontal(Point p1,Point p2)  
  67.         {  
  68.             return this.CheckHorizontal(p1,p2,false);  
  69.         }  
  70.   
  71.         private bool CheckHorizontal(Point p1,Point p2, bool isAddPath)  
  72.         {  
  73.             //检查水平,x位移,y相同  
  74.   
  75.             Point sp = p1.X<p2.X?p1:p2;  
  76.             Point ep = p2.X<p1.X?p1:p2;  
  77.   
  78.             for(int x =sp.X+1;x<ep.X;x++)  
  79.             {  
  80.                 //允许记录  
  81.                 if(isAddPath)  
  82.                 {  
  83.                     this.PathRecord.Add(new Point(x,p1.Y));  
  84.                 }  
  85.                 //不可通过  
  86.                 if(map[x,p1.Y]!=0)  
  87.                     return false;  
  88.             }  
  89.   
  90.             return true;  
  91.         }  
  92.   
  93.         private bool CheckVertical(Point p1,Point p2)  
  94.         {  
  95.             return CheckVertical(p1,p2,false);  
  96.         }  
  97.   
  98.         private bool CheckVertical(Point p1,Point p2, bool isAddPath)  
  99.         {  
  100.             //检查垂直,y位移,x相同  
  101.   
  102.             Point sp = p1.Y<p2.Y?p1:p2;  
  103.             Point ep = p2.Y<p1.Y?p1:p2;  
  104.   
  105.             for(int y =sp.Y+1; y<ep.Y; y++)  
  106.             {  
  107.                 //允许记录  
  108.                 if(isAddPath)  
  109.                 {  
  110.                     this.PathRecord.Add(new Point(p1.X,y));  
  111.                 }  
  112.                 //不可通过  
  113.                 if(map[p1.X,y]!=0)  
  114.                     return false;  
  115.             }  
  116.   
  117.             return true;  
  118.         }  
  119.   
  120.         private bool CheckOneCorner(Point p1,Point p2)  
  121.         {  
  122.             return CheckOneCorner(p1,p2,true,true);  
  123.         }  
  124.         private bool CheckOneCorner(Point p1,Point p2, bool isAddPath, bool isClear)  
  125.         {  
  126.             //计算夹角  
  127.   
  128.             //取起始x  
  129.             Point CrossStart;  
  130.             Point CrossEnd;  
  131.   
  132.             if(p1.X<p2.X)  
  133.             {  
  134.                 CrossStart = p1;  
  135.                 CrossEnd = p2;  
  136.             }  
  137.             else  
  138.             {  
  139.                 CrossStart = p2;  
  140.                 CrossEnd = p1;  
  141.             }  
  142.           
  143.             //交叉点X  
  144.             //正向  
  145.             Point CrossX ;  
  146.             //交叉点Y  
  147.             //反向  
  148.             Point CrossY ;  
  149.   
  150.             if(CrossStart.Y<CrossEnd.Y)  
  151.             {  
  152.                 CrossX = new Point(  
  153.                     Math.Max(CrossStart.X,CrossEnd.X),  
  154.                     Math.Min(CrossStart.Y,CrossEnd.Y)  
  155.                     );  
  156.                 CrossY = new Point(  
  157.                     Math.Min(CrossStart.X,CrossEnd.X),  
  158.                     Math.Max(CrossStart.Y,CrossEnd.Y)  
  159.                     );  
  160.             }  
  161.             else  
  162.             {  
  163.                 CrossX = new Point(  
  164.                     Math.Min(CrossStart.X,CrossEnd.X),  
  165.                     Math.Min(CrossStart.Y,CrossEnd.Y)  
  166.                     );  
  167.                 CrossY = new Point(  
  168.                     Math.Max(CrossStart.X,CrossEnd.X),  
  169.                     Math.Max(CrossStart.Y,CrossEnd.Y)  
  170.                     );  
  171.             }  
  172.   
  173.             //检查交叉点是否为可通过  
  174.             if(!this.IsEmptyPoint(CrossX) && !this.IsEmptyPoint(CrossY))  
  175.                 return false;  
  176.   
  177.             //检查交叉点X  
  178.             if(this.IsEmptyPoint(CrossX))  
  179.             {  
  180.                 //检查横位  
  181.                 if(CrossStart.Y<CrossEnd.Y)  
  182.                 {  
  183.                     //方向为~|  
  184.                     if(this.CheckHorizontal(CrossStart,CrossX) && this.CheckVertical(CrossX,CrossEnd))  
  185.                     {      
  186.                         //允许清空  
  187.                         if(isClear)  
  188.                         {  
  189.                             this.EmptyPathRecord();  
  190.                         }  
  191.                         //允许记录  
  192.                         if(isAddPath)  
  193.                         {  
  194.                             this.PathRecord.Add(CrossX);//记录当前交叉点  
  195.                         }                              
  196.                         return (this.CheckHorizontal(CrossStart,CrossX,true) && this.CheckVertical(CrossX,CrossEnd,true));                           
  197.                     }  
  198.                     //不跳出,留下一点检测  
  199.                 }  
  200.                 else  
  201.                 {  
  202.                     //方向为|~  
  203.                     if(this.CheckHorizontal(CrossX,CrossEnd) && this.CheckVertical(CrossX,CrossStart))  
  204.                     {  
  205.                         //允许清空  
  206.                         if(isClear)  
  207.                         {  
  208.                             this.EmptyPathRecord();  
  209.                         }  
  210.                         //允许记录  
  211.                         if(isAddPath)  
  212.                         {  
  213.                             this.PathRecord.Add(CrossX);//记录当前交叉点  
  214.                         }  
  215.                         return (this.CheckHorizontal(CrossX,CrossEnd,true) && this.CheckVertical(CrossX,CrossStart,true));  
  216.                     }  
  217.                     //不跳出,留下一点检测  
  218.                 }   
  219.             }  
  220.   
  221.             //检查交叉点Y  
  222.             if(this.IsEmptyPoint(CrossY))  
  223.             {  
  224.                 //检查竖位              
  225.                 if(CrossStart.Y<CrossEnd.Y)  
  226.                 {  
  227.                     //方向为|_  
  228.                     if(this.CheckVertical(CrossStart,CrossY) && this.CheckHorizontal(CrossY,CrossEnd))  
  229.                     {  
  230.                         //允许清空  
  231.                         if(isClear)  
  232.                         {  
  233.                             this.EmptyPathRecord();  
  234.                         }  
  235.                         //允许记录  
  236.                         if(isAddPath)  
  237.                         {  
  238.                             this.PathRecord.Add(CrossY);//记录当前交叉点  
  239.                         }  
  240.                         return (this.CheckVertical(CrossStart,CrossY,true) && this.CheckHorizontal(CrossY,CrossEnd,true));  
  241.                     }  
  242.                 }  
  243.                 else  
  244.                 {  
  245.                     //方向_|  
  246.                     if(this.CheckVertical(CrossEnd,CrossY) && this.CheckHorizontal(CrossY,CrossStart))  
  247.                     {  
  248.                         //允许清空  
  249.                         if(isClear)  
  250.                         {  
  251.                             this.EmptyPathRecord();  
  252.                         }  
  253.                         //允许记录  
  254.                         if(isAddPath)  
  255.                         {  
  256.                             this.PathRecord.Add(CrossY);//记录当前交叉点  
  257.                         }  
  258.                         return (this.CheckVertical(CrossEnd,CrossY,true) && this.CheckHorizontal(CrossY,CrossStart,true));  
  259.                     }  
  260.                 }  
  261.   
  262.             }  
  263.             return false//全部不成立,留给2次折点检测  
  264.   
  265.         }  
  266.   
  267.         private bool CheckTwoCornerLeft(Point p1,Point p2,bool isAddPath)  
  268.         {  
  269.             //左  
  270.             //清空记录  
  271.             this.EmptyPathRecord();  
  272.             for(int x = p1.X -1; x>-1; x--)  
  273.             {  
  274.                 if(this.map[x,p1.Y]!=0)  
  275.                     return false;  
  276.                 //允许记录  
  277.                 if(isAddPath)  
  278.                 {  
  279.                     this.PathRecord.Add(new Point(x,p1.Y));  
  280.                 }  
  281.   
  282.                 //不允许清空  
  283.                 if(this.CheckOneCorner(new Point(x,p1.Y),p2,false,false))  
  284.                 {  
  285.                     return this.CheckOneCorner(new Point(x,p1.Y),p2,isAddPath,false);  
  286.                 }  
  287.             }  
  288.   
  289.             return false;  
  290.         }  
  291.   
  292.         private bool CheckTwoCornerRight(Point p1,Point p2,bool isAddPath)  
  293.         {  
  294.             //右  
  295.             //清空记录  
  296.             this.EmptyPathRecord();  
  297.             for(int x = p1.X +1; x<this.map.GetLength(0); x++)  
  298.             {  
  299.                 if(this.map[x,p1.Y]!=0)  
  300.                     return false;  
  301.                 //允许记录  
  302.                 if(isAddPath)  
  303.                 {  
  304.                     this.PathRecord.Add(new Point(x,p1.Y));  
  305.                 }  
  306.   
  307.                 //不允许清空  
  308.                 if(this.CheckOneCorner(new Point(x,p1.Y),p2,false,false))  
  309.                 {  
  310.                     return this.CheckOneCorner(new Point(x,p1.Y),p2,isAddPath,false);  
  311.                 }  
  312.             }   
  313.             return false;  
  314.         }  
  315.   
  316.         private bool CheckTwoCornerUp(Point p1,Point p2,bool isAddPath)  
  317.         {  
  318.             //上  
  319.             //清空记录  
  320.             this.EmptyPathRecord();  
  321.             for(int y = p1.Y -1; y>-1; y--)  
  322.             {  
  323.                 if(this.map[p1.X,y]!=0)  
  324.                     return false;  
  325.                 //允许记录  
  326.                 if(isAddPath)  
  327.                 {  
  328.                     this.PathRecord.Add(new Point(p1.X,y));  
  329.                 }  
  330.   
  331.                 //不允许清空  
  332.                 if(this.CheckOneCorner(new Point(p1.X,y),p2,false,false))  
  333.                 {  
  334.                     return this.CheckOneCorner(new Point(p1.X,y),p2,isAddPath,false);  
  335.                 }  
  336.             }  
  337.   
  338.             return false;  
  339.         }  
  340.   
  341.         private bool CheckTwoCornerDown(Point p1,Point p2,bool isAddPath)  
  342.         {  
  343.             //下  
  344.             //清空记录  
  345.             this.EmptyPathRecord();  
  346.             for(int y = p1.Y +1; y<this.map.GetLength(1); y++)  
  347.             {  
  348.                 if(this.map[p1.X,y]!=0)  
  349.                     return false;  
  350.                 //允许记录  
  351.                 if(isAddPath)  
  352.                 {  
  353.                     this.PathRecord.Add(new Point(p1.X,y));  
  354.                 }  
  355.   
  356.                 //不允许清空  
  357.                 if(this.CheckOneCorner(new Point(p1.X,y),p2,false,false))  
  358.                 {  
  359.                     return this.CheckOneCorner(new Point(p1.X,y),p2,isAddPath,false);  
  360.                 }  
  361.             }   
  362.             return false;  
  363.         }  
  364.   
  365.         private void CopyArrayListTo(ref ArrayList srcAl,ref ArrayList destAl)  
  366.         {  
  367.             destAl.Clear();  
  368.             destAl.TrimToSize();  
  369.   
  370.             foreach(Point p in srcAl)  
  371.             {  
  372.                 Point newPnt = new Point(p.X,p.Y);  
  373.                 destAl.Add(newPnt);  
  374.             }  
  375.         }  
  376.   
  377.         private bool CheckTwoCorner(Point p1,Point p2)  
  378.         {  
  379.   
  380.             //取起始x  
  381.             Point CrossStart;  
  382.             Point CrossEnd;  
  383.   
  384.             if(p1.X<p2.X)  
  385.             {  
  386.                 CrossStart = p1;  
  387.                 CrossEnd = p2;  
  388.             }  
  389.             else  
  390.             {  
  391.                 CrossStart = p2;  
  392.                 CrossEnd = p1;  
  393.             }  
  394.   
  395.             //这里为寻找最短路径的算法  
  396.             //方法很简单,因为当前的起点方向不确定,可以选择重复尝试能成功的起点  
  397.             //然后找到路径最少的  
  398.   
  399.             //测试4次,寻找最短的路径  
  400.   
  401.             ArrayList[] backFindPath = new ArrayList[4];  
  402.             bool isFind =false;  
  403.             int nextPathList=0;  
  404.             while(nextPathList<4)  
  405.             {  
  406.                 backFindPath[nextPathList] = null;   
  407.  
  408.         if(this.CheckTwoCornerUp(CrossStart,CrossEnd,false))  
  409.                 {  
  410.                     this.PathRecord.Clear();  
  411.  
  412.             this.CheckTwoCornerUp(CrossStart,CrossEnd,true);  
  413.                     backFindPath[nextPathList] = new ArrayList();  
  414.                     CopyArrayListTo(ref this.PathRecord,ref  
  415.  
  416.             backFindPath[nextPathList]);  
  417.                     isFind = true;  
  418.                     nextPathList ++;  
  419.                 }   
  420.  
  421.         if(this.CheckTwoCornerDown(CrossStart,CrossEnd,false))  
  422.                 {  
  423.                     this.PathRecord.Clear();  
  424.                     this.CheckTwoCornerDown(CrossStart,CrossEnd,true);  
  425.                     backFindPath[nextPathList] = new ArrayList();  
  426.                     CopyArrayListTo(ref this.PathRecord,ref backFindPath[nextPathList]);  
  427.                     isFind = true;  
  428.                     nextPathList ++;  
  429.                 }  
  430.   
  431.                 if(this.CheckTwoCornerLeft(CrossStart,CrossEnd,false))  
  432.                 {  
  433.                     this.PathRecord.Clear();  
  434.                     this.CheckTwoCornerLeft(CrossStart,CrossEnd,true);  
  435.                     backFindPath[nextPathList] = new ArrayList();  
  436.                     CopyArrayListTo(ref this.PathRecord,ref backFindPath[nextPathList]);  
  437.                     isFind = true;  
  438.                     nextPathList ++;  
  439.                 }  
  440.   
  441.                 if(this.CheckTwoCornerRight(CrossStart,CrossEnd,false))  
  442.                 {  
  443.                     this.PathRecord.Clear();  
  444.                     this.CheckTwoCornerRight(CrossStart,CrossEnd,true);  
  445.                     backFindPath[nextPathList] = new ArrayList();  
  446.                     CopyArrayListTo(ref this.PathRecord,ref backFindPath[nextPathList]);  
  447.                     isFind = true;  
  448.                     nextPathList ++;  
  449.                 }  
  450.   
  451.                 //没有结果  
  452.                 if(!isFind)  
  453.                     break;  
  454.             }  
  455.   
  456.             //有结果返回  
  457.             if(isFind)  
  458.             {  
  459.                 //检查起点最小数  
  460.                 int minCount = 0;  
  461.                 //记录位  
  462.                 int index = 0;  
  463.                 for(int i=0;i<4;i++)  
  464.                 {  
  465.                     if(backFindPath[i]!=null)  
  466.                     {  
  467.                         if(backFindPath[i].Count>0)  
  468.                         {  
  469.                             if(minCount==0)  
  470.                             {  
  471.                                 minCount=backFindPath[i].Count;  
  472.                                 index = i;  
  473.                             }  
  474.                             else if(backFindPath[i].Count<minCount)  
  475.                             {  
  476.                                 minCount = backFindPath[i].Count;  
  477.                                 index = i;  
  478.                             }  
  479.                         }  
  480.                     }  
  481.                 }  
  482.   
  483.                 //回复属性数据  
  484.                 this.PathRecord.Clear();  
  485.                 this.PathRecord.TrimToSize();  
  486.                 CopyArrayListTo(ref backFindPath[index],ref this.PathRecord);  
  487.                   
  488.                 return true;  
  489.             }  
  490.   
  491.             return false;  
  492.         }  
  493.   
  494.   
  495.         public bool Execute()  
  496.         {  
  497.             pathPointCount = -1;  
  498.             //检查目标位置是否一样  
  499.             if(this.startPos.X==this.endPos.X && this.startPos.Y==this.endPos.Y)  
  500.             {  
  501.                 pathPointCount = -1;  
  502.                 return false;  
  503.             }  
  504.   
  505.             //检查为同一横坐标  
  506.             if(this.startPos.Y==this.endPos.Y)  
  507.                 if(this.CheckHorizontal(this.startPos,this.endPos))  
  508.                 {  
  509.                     this.EmptyPathRecord();  
  510.                     pathPointCount = 1;  
  511.                     return (this.CheckHorizontal(this.startPos,this.endPos,true));  
  512.                 }  
  513.   
  514.             //检查为同一纵坐标  
  515.             if(this.startPos.X==this.endPos.X)  
  516.                 if(this.CheckVertical(this.startPos,this.endPos))  
  517.                 {  
  518.                     this.EmptyPathRecord();  
  519.                     pathPointCount = 1;  
  520.                     return (this.CheckVertical(this.startPos,this.endPos,true));  
  521.                 }  
  522.   
  523.             //检查一个折点  
  524.             if(this.CheckOneCorner(this.startPos,this.endPos))  
  525.             {  
  526.                 pathPointCount =2;  
  527.                 return true;  
  528.             }  
  529.   
  530.             //检查两个折点  
  531.             if(this.CheckTwoCorner(this.startPos,this.endPos))  
  532.             {  
  533.                 pathPointCount =3;  
  534.                 return true;  
  535.             }  
  536.   
  537.             return false;  
  538.         }  
  539.   
  540.         /**//// <summary>  
  541.         /// 起点坐标  
  542.         /// </summary>  
  543.         public Point StartPosition  
  544.         {  
  545.             get  
  546.             {  
  547.                 return this.startPos;  
  548.             }  
  549.             set  
  550.             {  
  551.                 this.startPos = value;  
  552.             }  
  553.         }  
  554.   
  555.         /**//// <summary>  
  556.         /// 终点坐标  
  557.         /// </summary>  
  558.         public Point EndPosition  
  559.         {  
  560.             get  
  561.             {  
  562.                 return this.endPos;  
  563.             }  
  564.             set  
  565.             {  
  566.                 this.endPos = value;  
  567.             }  
  568.         }  
  569.         /**//// <summary>  
  570.         /// 地图数据  
  571.         /// </summary>  
  572.         public int[,] MapData  
  573.         {  
  574.             get  
  575.             {  
  576.                 return this.map;  
  577.             }  
  578.             set  
  579.             {  
  580.                 this.map = value;  
  581.             }  
  582.         }  
  583.         /**//// <summary>  
  584.         /// 获取折点数  
  585.         /// </summary>  
  586.         public int PathPointCount  
  587.         {  
  588.             get  
  589.             {  
  590.                 return this.pathPointCount;  
  591.             }  
  592.         }  
  593.   
  594.         /**//// <summary>  
  595.         /// 获取路径表  
  596.         /// </summary>  
  597.         public Point[] PathPointList  
  598.         {  
  599.             get  
  600.             {  
  601.                 if(this.PathRecord.Count>=0)  
  602.                 {  
  603.                     Point[] tmpPointList = new Point[this.PathRecord.Count];  
  604.                     int i = 0;  
  605.                     foreach(Point p in this.PathRecord)  
  606.                     {  
  607.                         tmpPointList[i] = p;  
  608.                         i++;  
  609.                     }  
  610.                     return tmpPointList;  
  611.                 }  
  612.                 else  
  613.                 {  
  614.                     return null;  
  615.                 }  
  616.             }  
  617.         }  
  618.   
  619.         public ArrayList PathPointArray  
  620.         {  
  621.             get  
  622.             {  
  623.                 return this.PathRecord;  
  624.             }  
  625.         }  
  626.   
  627.     }  
  628. }  

测试用例:

 

  1. int[,] map = new int[14,10]  
  2.                 {  
  3.                     {0,0,0,0,0,0,0,0,0,0},  
  4.                     {0,2,0,3,1,0,0,0,0,0},  
  5.                     {0,0,0,0,1,0,0,0,0,0},  
  6.                     {0,1,1,1,1,1,1,1,1,0},  
  7.                     {0,0,0,0,1,0,0,0,0,0},  
  8.                     {0,0,0,0,1,0,0,0,0,0},  
  9.                     {0,0,0,0,1,0,0,0,0,0},  
  10.                     {0,0,0,0,1,0,0,0,0,0},  
  11.                     {0,0,0,0,1,0,0,0,0,0},  
  12.                     {0,0,0,0,1,0,0,0,0,0},  
  13.                     {0,1,1,1,1,1,1,1,1,0},  
  14.                     {0,0,0,0,1,0,0,0,0,0},  
  15.                     {0,0,0,0,1,0,0,0,0,0},  
  16.                     {0,0,0,0,0,0,0,0,0,0}  
  17.                 };  
  18.     AI_Engine.TestPathing TP = new AI_Engine.TestPathing();  
  19.     TP.StartPosition = new Point((int)numericUpDown1.Value,(int)numericUpDown2.Value);  
  20.     TP.EndPosition = new Point((int)numericUpDown3.Value,(int)numericUpDown4.Value);  
  21.     TP.MapData = this.map;  
  22.  
  23.     if(TP.Execute())  
  24.     {  
  25.         lbInfo.Text = "连通!";  
  26.         AddPathInfo(TP.PathPointList);//绘制路径  
  27.     }  
  28.     else  
  29.     {  
  30.         lbInfo.Text = "不通!";  
  31.     }  

Note:
map中0表示通道;1是障碍,2是起点,3是终点。

遍历map数组方法是

for(int y=0;y<10;y++)
for(int x=0;x<14;x++)
{
g.Draw ........ //绘制
}

被阅628次, 0投一票
  • 看完了要说点啥么?
  • 昵称 (不填说不了话)
  • 信箱地址 (不会被公开,但是不填也说不了话)
  • 网址 (这个不填也成)

Powered by MiniBoke v2.0.0.8 Build 0828

Copyright © 2008 迷你博客. All rights reserved.

粤ICP备07500939号