一步一步开发Game服务器(五)地图寻路
目前大多数使用的寻路算法有哪些?
目前市面上大部分游戏的寻路算法是A*,或者B*。
A*通常所说的是最优算法也就是寻找最短路径。B*碰撞式算法也就是,也就是不断的去碰撞能走就走,不管是不是绕路。当然以上都是我的理解。
我这里只描述一下A*算法的一部分。
通常A*算法分为四方向和八方向计算。
现目前的游戏方式来看不管是2D还是2.5D,还是3D,几乎都采用8方向方式,也有游戏是采用360°点位方式。
本文重点剖析8方向的。
先来看一个效果图
图中你看到的图案表示非阻挡地区,其余是阻挡地区。
绿色的线是表示寻路走过路线。
寻路步骤
1. 从起点A开始, 把它作为待处理的方格存入一个"开启列表", 开启列表就是一个等待检查方格的列表.
2. 寻找起点A周围可以到达的方格, 将它们放入"开启列表", 并设置它们的"父方格"为A.
3. 从"开启列表"中删除起点 A, 并将起点 A 加入"关闭列表", "关闭列表"中存放的都是不需要再次检查的方格
原谅我盗用了园友的图。
图中浅绿色描边的方块表示已经加入 "开启列表" 等待检查. 淡蓝色描边的起点 A 表示已经放入 "关闭列表" , 它不需要再执行检查.
从 "开启列表" 中找出相对最靠谱的方块, 什么是最靠谱? 它们通过公式 F=G+H 来计算.
废话不多说了,直接来源码
源码来之园友,但是稍作修改。修改1,原本算法不支持复杂地形图。修改2,原本算法foreach List列表,改为for循环,倒入循环。因为每一次的寻路下一个节点的时候8方向都是上一个节点。修改3,修改单例模式。
来一张大图看看目前我的地形图
源码
public class FindWayManager { static readonly FindWayManager instance = new FindWayManager(); public static FindWayManager Instance { get { return instance; } } /// <summary> /// 阻挡点配置,, /// </summary> ; //从开启列表查找F值最小的节点 private Point GetMinFFromOpenList(List<Point> Open_List) { Point Pmin = null; int count = Open_List.Count; ; i >= ; i--) { if (Pmin == null || Pmin.G + Pmin.H > Open_List[i].G + Open_List[i].H) Pmin = Open_List[i]; } return Pmin; } //判断关闭列表是否包含一个坐标的点 private bool IsInCloseList(int x, int y, List<Point> Close_List) { ) { return false; } int count = Close_List.Count; ; i >= ; i--) { if (Close_List[i].X == x && Close_List[i].Y == y) return true; } return false; } //从关闭列表返回对应坐标的点 private Point GetPointFromCloseList(int x, int y, List<Point> Close_List) { int count = Close_List.Count; ; i >= ; i--) { if (Close_List[i].X == x && Close_List[i].Y == y) return Close_List[i]; } return null; } //判断开启列表是否包含一个坐标的点 private bool IsInOpenList(int x, int y, List<Point> Open_List) { int count = Open_List.Count; ; i >= ; i--) { if (Open_List[i].X == x && Open_List[i].Y == y) return true; } return false; } //从开启列表返回对应坐标的点 private Point GetPointFromOpenList(int x, int y, List<Point> Open_List) { int count = Open_List.Count; ; i >= ; i--) { if (Open_List[i].X == x && Open_List[i].Y == y) return Open_List[i]; } return null; } //计算某个点的G值 private int GetG(Point p) { ; ; ; } //计算某个点的H值 private int GetH(Point p, Point pb) { return Math.Abs(p.X - pb.X) + Math.Abs(p.Y - pb.Y); } //检查当前节点附近的节点 private void CheckP8(Point p0, byte[,] map, Point pa, Point pb, List<Point> Open_List, List<Point> Close_List) { //这里的循环其实就是8方向判断 ; xt <= p0.X + ; xt++) { ; yt <= p0.Y + ; yt++) { //排除超过边界和等于自身的点 && xt < map.GetLongLength() && yt >= && yt < map.GetLongLength()) && !(xt == p0.X && yt == p0.Y)) { //排除障碍点和关闭列表中的点 if (map[yt, xt] != BlockConst && !IsInCloseList(xt, yt, Close_List)) { Point pt = GetPointFromOpenList(xt, yt, Open_List); if (pt != null) { //如果节点在开启列表中更新带价值 ; ; ; if (G_new < pt.G) { //Open_List.Remove(pt); pt.Next = p0; pt.G = G_new; //Open_List.Add(pt); } } else { //不在开启列表中,如果不存在创建添加到开启列表中 pt = new Point(); pt.X = xt; pt.Y = yt; pt.Next = p0; pt.G = GetG(pt); pt.H = GetH(pt, pb); Open_List.Add(pt); } } } } } } public Point FindWay(byte[,] r, int sx, int sz, int ex, int ez) { //定义出发位置 Point pa = new Point(); pa.X = sx; pa.Y = sz; //定义目的地 Point pb = new Point(); pb.X = ex; pb.Y = ez; //如果点超出范围,或者是阻挡点 < pb.X && pb.X < r.GetLength() && < pa.X && pa.X < r.GetLength() && < pb.Y && pb.Y < r.GetLength() && < pa.Y && pa.Y < r.GetLength() && !CheckBlocking(r, pa) && !CheckBlocking(r, pb)) { //开启列表 List<Point> Open_List = new List<Point>(); //关闭列表 List<Point> Close_List = new List<Point>(); Open_List.Add(pa); )) { Point p0 = GetMinFFromOpenList(Open_List); if (p0 == null) return null; Open_List.Remove(p0); Close_List.Add(p0); CheckP8(p0, r, pa, pb, Open_List, Close_List); } Point p = GetPointFromOpenList(pb.X, pb.Y, Open_List); return Reverse(p); } return null; } Point Reverse(Point point) { //新节点 Point newNode = null; //当前节点 Point current = point; while (current != null) { //取当前节点的下一个,放入临时节点中 Point temp = current.Next; //将当前节点的下一个设置为新节点 //(第一次将设置为null,也对着呢,因为第一个节点将作为尾节点) current.Next = newNode; //把当前节点给新节点 newNode = current; //把临时节点给当前节点(就是取当前节点的下一个而已) current = temp; } //将最后的新节点给头节点 return newNode; } public bool CheckBlocking(byte[,] r, Point point) { return CheckBlocking(r, point.X, point.Y); } public bool CheckBlocking(byte[,] r, int x, int y) { return r[y, x] == BlockConst; } public void PrintMap(byte[,] r) { Console.Clear(); Console.ForegroundColor = ConsoleColor.Gray; ; y < r.GetLongLength(); y++)//Y轴 { ; x < r.GetLongLength(); x++)//X轴 { Console.Write(r[y, x]); } Console.Write("\n"); } } public void PrintWay(byte[,] r, Point way) { Console.ForegroundColor = ConsoleColor.Green; while (way != null) { Console.CursorLeft = way.X; Console.CursorTop = way.Y; Console.Write("); System.Threading.Thread.Sleep(); way = way.Next; } Console.ForegroundColor = ConsoleColor.Gray; } bool check(int x, int y, Point way) { Point f = way; while (f != null) { if (f.X == x && f.Y == y) { return true; } f = f.Next; } return false; } } public class Point { //坐标点 public int Y { get; set; } //坐标点 public int X { get; set; } //从起点到当前点的代价 public int G { get; set; } //从终点到当前点的代价 public int H { get; set; } public Point() { } public Point Next { get; set; } }
由于地图阻挡点配置是由工具决定的,所以我根据我这里的方式来创建测试代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Serialization; namespace ConsoleApplication1 { [XmlRootAttribute("SceneInfo_Server")] [Serializable] public class MapBlockConfig { public MapBlockConfig() { } [XmlAttribute("MapID")] public int MapID { get; set; } [XmlElement("WalkSetting")] public WalkSetting Walk { get; set; } [Serializable] public class WalkSetting { public WalkSetting() { } [XmlAttribute("RZLEN")] public int Rzlen { get; set; } [XmlAttribute("RXLEN")] public int Rxlen { get; set; } [XmlAttribute("STARTX")] public int Startx { get; set; } [XmlAttribute("STARTY")] public int Starty { get; set; } [XmlAttribute("STARTZ")] public int Startz { get; set; } [XmlAttribute("BLOCKINFO")] public String Blockinfo { get; set; } } } }
阻挡配置
<?xml version="1.0" encoding="utf-8"?> <SceneInfo_Server xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" MapID="3501"> <WalkSetting RZLEN="120" RXLEN="120" STARTX="0" STARTY="200" STARTZ="0" BLOCKINFO="111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000011111111111111111111111111111111111111111111111111111111111111111111111111110000000000011111111111111111111110000000000001111111111111111111111111111111111111111100000000001111111111111111111111000000000000001111111111111111111100000000000000011111111111111111111111111111111111111000000000000111111111111111111110000000000000000111111111111111111000000000000000011111111111111111111111111111111111100000000000000011111111111111111110000000000000000111111111111111110000000000000000011111111111111111111111111111111111000000000000000001111111111111111100000000000000000011111111111111100000000000000000011111111111111111111111111111111110000000000000000000111111111111111100000000000000000011111111111111000000000000000000011111111111111111111111111111111100000000000000000000001111111111111100000000000000000001111111111111100000000000000000011111111111111111111111111111111100000000000000000000000111111111111100000000000000000001111111111111110000000000000000011111111111111111111111111111111100000000000000000000000011111111111110000000000000000001111111111111100000000000000000111111111111111111111111111111111100000000000000000000000001111111111110000000000000000001111111111110000000000000000000111111111111111111111111111111111100000000000000000000000001111111000000000000000000000001111111111100000000000000000001111111111111111111111111111111111100000000000000000000000000000000000000000000000000000001111111110000000000000000000011111111111111111111111111111111111100000000000000000000000000000000000000000000000000000001111111100000000000000000000111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111100000000000000000000000001111111000000000000000000000000000000000000000000000011111111111111111111111111111111111111111100000000000000000000000001111111000000000000000000000000000000000000000000000111111111111111111111111111111111111111111100000000000000000000000001111111000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111100000000000000011111111111111100000000000000000000000000000000000000000111111111111111111111111111111111111111111111111100000000000000011111111111111111000000000000000000000000000000000000011111111111111111111111111111111111111111111111111100000000000000111111111111111111100000000000000000000010000000000000111111111111111111111111111111111111111111111111111100000000000000111111111111111111111000000000000000000111000000000001111111111111111111111111111111111111111111111111111100000000000001111111111111111111111100000000000000001111100000000001111111111111111111111111111111111111111111111111111100000000000001111111111111111111111111000000000000011111100000000001111111111111111111111111111111111111111111111111111100000000000001111111111111111111111111111111111100111111100000000001111111111111111111111111111111111111111111111111111100000000000111111111111111111111111111111111111111111111100000000001111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111110000000001111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111110000000001111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111111000000001111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111110000000001111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111110000000001111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111110000000001111111111111111111111111111111111111111111111111111000000000000011111111111111111111111111111111111111111111110000000001111111111111111111111111111111111111111111111111111000000000000011111111111111111111111111111111111111111111111000000000111111111111111111111111111111111111111111111111111000000000000011111111111111100001111111111111111111111111111000000000001111111111111111111111111111111111111111111111111000000000000011111111111111000000000000000001111111111111111100000000000011111111111111111111111111111111111111111111111000000000000011111111111110000000000000000000000000011111111110000000000000011111111111111111111111111111111111111111111000000000000011111111111000000000000000000000000000001111111111100000000000000111111111111111111111111111111111111111111000000000000011111111110000000000000000000000000000001111111111100000000000000001111111111111111111111111111111111111111100000000000011111111100000000000000000000000000000000111111111100000000000000000011111111111111111111111111111111111111100000000000011111110000000000000000000000000000000000111111111100000000000000000000111111111111111111111111111111111111100000000000011111110000000000000000000000000000000000111111111100000000000000000000001111111111111111111111111111111111100000000000011111100000000000000000000000000000000000111111111100000000000000000000000011111111111111111111111111111111100000000000011111100000000000000000000000000000000000111111111100000000000000000000000000111111111111111111111111111111100000000000011111100000011000000000000000000000000000111111111100000000000000000000000000111111111111111111111111111111100000000000011111100000111110000000000000000000000000111111111100000000000000000000000000111111111111111111111111111111100000000000011111100000111111000000000000000000000000111111111100000000000000000000000000011111111111111111111111111111100000000000111111100000001111000000000000000000000000111111111100000000000000000000000000011111111111111111111111111111100000000000111111000000000001000000000000000000000000111111111100000000000000000000000000001111111111111111111111111111100000000000111111000000000000000000000000000000000000111111111100000000000000000000000000001111111111111111111111111111100000000000111111000000000000000000000000000000000000111111111100000000000000000000000000000111111111111000000000000111100000000000111111000000000000000000000000000000010001111111111100000000000000000000000000000111111111111000000000000111100000000000111111000000000010000000000000000000111111111111111100000000000000000000000000000011111111111000000000000111100000000001111111000001111111111111111111111111111111111111111100000000000000000000000000000011111111111000000000000111100000000001111110000000111111111111111111111111111111111111111100000000000000000000000000000011111111111000000000000111100000000001111111000000111111111111111111111111111111111100000000000000000000000000000000000001111111111000000000011111100000000001111111000000111111111111111111111111111111111000000000000000000000000000000000000001111111111000000000011111100000000001111111000000111111111111111111111111111111111000000000000000011100000000000000000001111111111000000000011111110000000001111111100000111111111111111111111111111111111000000000000000111111100000000000000001111111111000000000011111110000000000111111100000111111111111111111111111111111111000000000000000111111111100000000000001111111111000000000011111110000000000111111100000011111111111111111111111111111110000000000000000111111111100000000000001111111111000000000111111110000000000111111110000001111111111111111111111111111110000000000000001111111111100000000000001111111111000000000111111110000000000011111110000000111111111111111111111111111110000000000000001111111111000000000000001111111111000000001111111110000000000011111110000000011111111111111111111111111100000000000000011111111111000000000000001111111111000000001111111111000000000111111110000000001111111111111111111111111100000000000000011111111111000000000000001111111111000000000111111111000000000111111111000000000111111111111111111111111100000000000000011111111110000000000000001111111111000000000111111111000000000011111111000000000111111111111111111111111000000000000000111111111110000000000000001111111111000000000111111111000000000011111111000000000011111111111111111111111000000000000000111111111110000000000000001111111111000000000111111111000000000011111111100000000011111111111111111111111000000000000000111111111100000000000000001111111111000000000111111111000000000001111111100000000011111111111111111111110000000000000001111111111100000000000000001111111111000000000111111111000000000001111111100000000011111111111111111111000000000000000001111111111100000000000000001111111111000000000111111111000000000001111111110000000011111111111111111100000000000000000001111111111000000000000000001111111111000000000111111111000000000000011111110000000011111111111111110000000000000000000011111111111000000000000000001111111111000000000111111111000000000000011111110000000011111111111111000000000000000000000011111111110000000000000000001111111111000000000111111111000000000000001111111000000011111111111100000000000000000000000011111111110000000000000000001111111111000000000111111111000000000000000111111000000000000000000000000000000000000000000011111111110000000000000000001111111111000000000111111111000000000000000111111000000000000000000000000000000000000000000001111111111000000000000000001111111111000000000111111111000000000000000111111000000000000000000000000000000000000000000001111111111000000000000000001111111111000000000111111111000000000000000111111000000000000000000000000000000000000000000000111111111000000000000000011111111111000000000111111111000000000000000111111000000000000000000000000000000000000000000000111111111100000000000000111111111111000000000111111111000000000000000111110000000000000000000000000000000000000000000000111111111100000000000001111111111111000000000111111111000000000000000111110000000000000000000000000000000000000000000000011111111100000000000001111111111111000000000111111111000000000000000111110000000000000000000000000000000000000000000000011111111110000001111111111111111111000000000111111111000000000000000111110000000000000000000000000000000000000000000000001111111110000001111111111111111111000000000111111111000000000000000111110000000000000000000000000000000000000000000000001111111111000001111111111111111111000000000111111111100000000000001111110000000000000000000000000000000000000000000000001111111111111111111111111111111111000000000011111110000000000000111111100000000000000000000000000000000000100000000000000111111111111111111111111111111111000000000001111100000000000001111111100000000000000000000000000000000001111000000000000111111111111111111111111111111111000000000001110000000000000001111111100000000000000000000000000000000111111111000000000111111111111111111111111111111111000000000000100000000000000001111111100000000000000000000000000000001111111111110000000111111111111111111111111111111111000000000000000000000010000111111111100000000000000000000000000000011111111111111110000111111111111111111111111111111111000000000000000000000111111111111111111111110000000000000000000000111111111111111111111111111111111111111111111111111111000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" /> </SceneInfo_Server>
测试代码
ConsoleApplication1.MapBlockConfig block = new ConsoleApplication1.MapBlockConfig(); System.Xml.Serialization.XmlSerializer xml = new System.Xml.Serialization.XmlSerializer(block.GetType()); System.IO.FileStream fs = new System.IO.FileStream("3501.block.xml", System.IO.FileMode.Open); block = (ConsoleApplication1.MapBlockConfig)xml.Deserialize(fs); fs.Dispose(); R = new byte[block.Walk.Rzlen, block.Walk.Rxlen]; ; z < block.Walk.Rzlen; z++) { ; x < block.Walk.Rxlen; x++) { char item = block.Walk.Blockinfo[block.Walk.Rxlen * z + x]; R[z, x] = Convert.ToByte(item + ""); } } List<int[]> ss = new List<int[]>();//{ { 7, 60, 55, 55 } }; ss.Add(, , , }); ss.Add(, , , }); ss.Add(, , , }); Random ran = new Random(); Console.ReadLine(); FindWayManager.Instance.PrintMap(R); Console.ReadLine(); while (true) { FindWayManager.Instance.PrintMap(R); Point way = null; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); int index = ran.Next(ss.Count); int[] points = ss[index]; way = FindWayManager.Instance.FindWay(R, points[], points[], points[], points[]); watch.Stop(); Console.Title = "寻路用时:" + (watch.ElapsedMilliseconds); FindWayManager.Instance.PrintWay(R, way); System.Threading.Thread.Sleep(); } Console.ReadLine();
效果图请参考上面的。
特别声明:感谢园友提供的思路和源码。我只是稍作修改。
看几张性能分析图
原本的对园友的代码优化和修改,就是基于这个性能分析结果得来。
再一次的测试发现如果把关闭列表用 Dictionary<string, Point> Close_List = new Dictionary<string, Point>();性能还能再次提升。
但是如果把openlist也改为 Dictionary<string, Point> 性能却不如从前了。以上四张图都是程序运行一段时间稳定后截图。期待大神,有更优化的算法~!
一步一步开发Game服务器(五)地图寻路的更多相关文章
- 一步一步开发Game服务器(四)地图线程
时隔这么久 才再一次的回归正题继续讲解游戏服务器开发. 开始讲解前有一个问题需要修正.之前讲的线程和定时器线程的时候是分开的. 但是真正地图线程与之前的线程模型是有区别的. 为什么会有区别呢?一个地图 ...
- 一步一步开发Game服务器(三)加载脚本和服务器热更新(二)完整版
上一篇文章我介绍了如果动态加载dll文件来更新程序 一步一步开发Game服务器(三)加载脚本和服务器热更新 可是在使用过程中,也许有很多会发现,动态加载dll其实不方便,应为需要预先编译代码为dll文 ...
- 一步一步开发Game服务器(一)
什么是服务器?对于很多人来说也许只是简单成为在服务器端运行的程序的确如此,服务器通常意义就是说在服务器端运行的程序而已.那么我们怎么理解和分析游戏服务器哪? 传统意义上来说,程序运行后,正常流程, 启 ...
- 跟我一步一步开发自己的Openfire插件
http://www.blogjava.net/hoojo/archive/2013/03/07/396146.html 跟我一步一步开发自己的Openfire插件 这篇是简单插件开发,下篇聊天记录插 ...
- 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)
前言 Hi,大家好,我是Rector 时间飞逝,一个星期又过去了,今天还是星期五,Rector在图享网继续跟大家分享系列文本:一步一步创建ASP.NET MVC5程序[Repository+Autof ...
- 一步一步实现HTTP服务器-开篇
缘起 翻开清单,一条条计划一直列在那里,一天又一天,不知道什么时候写下了它,也知不道什么时候完成它,它一直在那静静的等待着. 静下心来,反思自己,才发现自己是多么的无知,多么的没有毅力.设定了无数目标 ...
- 一步一步构建手机WebApp开发——页面布局篇
继上一篇:一步一步构建手机WebApp开发——环境搭建篇过后,我相信很多朋友都想看看实战案例,这一次的教程是页面布局篇,先上图: 如上图所示,此篇教程便是教初学者如何快速布局这样的页面.废话少说,直接 ...
- xmppmini 项目详解:一步一步从原理跟我学实用 xmpp 技术开发 2.登录的实现
第二章登录的实现 金庸<倚天屠龙记> 张三丰缓缓摇头,说道:“少林派累积千年,方得达成这等绝技,决非一蹴而至,就算是绝顶聪明之人,也无法自创.”他顿了一顿,又道:“我当年在少林寺中住过,只 ...
- 如何一步一步用DDD设计一个电商网站(五)—— 停下脚步,重新出发
阅读目录 前言 单元测试 纠正错误,重新出发 结语 一.前言 实际编码已经写了2篇了,在这过程中非常感谢有听到观点不同的声音,借着这个契机,今天这篇就把大家提出的建议一个个的过一遍,重新整理,重新出发 ...
- 一步一步来做WebQQ机器人-(五)(发送消息||完结)
× 本篇主要是: 发送QQ消息(to:好友,群),以及对小黄鸡抓包利用它的语言库 本文是WebQQ流程的最后一章 最后一章内容不多但我还是啰嗦,可能对大部分人都已知晓的流程方法我也会介绍一下 前面几个 ...
随机推荐
- 关于微软HttpClient使用,避免踩坑
最近公司对于WebApi的场景使用也越来越加大了,随之而来就是Api的客户端工具我们使用哪个?我们最常用的估计就是HttpClient,在微软类库中命名空间地址:System.Net.Http,是一个 ...
- 算法与数据结构(十七) 基数排序(Swift 3.0版)
前面几篇博客我们已经陆陆续续的为大家介绍了7种排序方式,今天博客的主题依然与排序算法相关.今天这篇博客就来聊聊基数排序,基数排序算法是不稳定的排序算法,在排序数字较小的情况下,基数排序算法的效率还是比 ...
- Mac OS、Ubuntu 安装及使用 Consul
Consul 概念(摘录): Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发现的方案,比如 Airbnb 的 SmartStac ...
- C#向PPT文档插入图片以及导出图片
PowerPoint演示文稿是我们日常工作中常用的办公软件之一,而图片则是PowerPoint文档的重要组成部分,那么如何向幻灯片插入图片以及导出图片呢?本文我将给大家分享如何使用一个免费版Power ...
- 代码的坏味道(14)——重复代码(Duplicate Code)
坏味道--重复代码(Duplicate Code) 重复代码堪称为代码坏味道之首.消除重复代码总是有利无害的. 特征 两个代码片段看上去几乎一样. 问题原因 重复代码通常发生在多个程序员同时在同一程序 ...
- 为什么很多SaaS企业级产品都熬不过第一年
因工作缘由,笔者与周边数位SaaS企业级应用的创始人.运营负责人有过深入接触,发现一个有趣的现象:刚起步时,蓝图远志.规划清晰,但是一路下来,却异常艰难,有些甚至熬不过第一年,就关门歇业. 2015年 ...
- Mach-O 的动态链接(Lazy Bind 机制)
➠更多技术干货请戳:听云博客 动态链接 要解决空间浪费和更新困难这两个问题最简单的方法就是把程序的模块相互分割开来,形成独立的文件,而不再将它们静态的链接在一起.简单地讲,就是不对那些组成程序的目标文 ...
- OpenGL ES: Array Texture初体验
[TOC] Array Texture这个东西的意思是,一个纹理对象,可以存储不止一张图片信息,就是说是是一个数组,每个元素都是一张图片.这样免了频繁地去切换当前需要bind的纹理,而且可以节省系统资 ...
- Openstack Periodic Task
Openstack Periodic Task 周期性任务在各个模块的manager.py(computer,scheduler,cell,network)中添加. 添加方法:在模块manager类实 ...
- Xamarin.Android之ActionBar与菜单
一.选项卡 如今很多应用都会使用碎片以便在同一个活动中能够显示多个不同的视图.在Android 3.0 以上的版本中,我们已经可以使用ActionBar提供的Tab来实现这种效果,而不需要我们自己去实 ...