private bool check(myTree tree, myNode node) { bool c = true; foreach (myNode n in tree.nodes) { if (n.X == node.X && n.Y == node.Y) { c = false; } } return(c); }
// Start is called before the first frame update void Start() { /* * List<Transform> enemyList = new List<Transform>(); * for (int i = 0; i < 10; i++) { * GameObject empty = new GameObject(); * Transform newTransform = empty.transform; * newTransform.position = new Vector3(i, 0, 0); * enemyList.Add(newTransform); * } * KdTree<Transform> enemyKdTree = new KdTree<Transform>(); * enemyKdTree.AddAll(enemyList); * Transform now = enemyKdTree.FindClosest(new Vector3(5.2f, 0, 0)); * print(now.position);*/ //以上方法, 是參考 http://gyanendushekhar.com/2020/02/23/find-closest-enemy-in-unity-3d/ 使用 https://github.com/orifmilod/KdTree-Unity3D : Used in this example 的結構 List <myNode> nodeList = new List <myNode>(); //之後就 for(i彩帶 // for(j點 for (int i = 0; i < 10; i++) { GameObject one = new GameObject(); //要洗成 GameObject 的 component one.AddComponent <myNode>(); //加進去 myNode node = one.GetComponent <myNode>(); //再拿出來 //node.I = i; node.J = j; node.transform.position = new Vector3(i, 0, 0); //將來就有 tranform 可以做 KdTree的比較了... nodeList.Add(node); //這個 node有 tranform哦!!!! } KdTree <myNode> nodeKdTree = new KdTree <myNode>(); nodeKdTree.AddAll(nodeList); myNode nearest = nodeKdTree.FindClosest(new Vector3(4.2f, 0, 0)); print("hahaha" + nearest.transform.position); }
private void label38_Click(object sender, EventArgs e)//ids { myNode gool = new myNode(0, 0); bool isGool = pictureBox1.Location.X == pictureBox2.Location.X ? true : false; myNode root = new myNode(pictureBox1.Location.X, pictureBox1.Location.Y); root.level = 0; myTree IDS = new myTree(root); IDS.CurrentNode = root; int z = 367; bool b = true; int i = 0; for (int iz = 0; iz < z; iz++) { IDS.CurrentNode.Visited = true; List <myNode> newNodes = new List <myNode>(); pictureBox3.Location = new Point(IDS.CurrentNode.X, IDS.CurrentNode.Y); if (pictureBox3.Bounds.IntersectsWith(pictureBox2.Bounds)) { gool = IDS.CurrentNode; break; } myNode node1 = new myNode(IDS.CurrentNode.X + 10, IDS.CurrentNode.Y); pictureBox3.Location = new Point(node1.X, node1.Y); if (collision1()) { node1 = null; } else { node1.Parent = IDS.CurrentNode; node1.level = IDS.CurrentNode.level + 1; if (check(IDS, node1)) { IDS.nodes.Add(node1); } } newNodes.Add(node1); myNode node2 = new myNode(IDS.CurrentNode.X - 10, IDS.CurrentNode.Y); pictureBox3.Location = new Point(node2.X, node2.Y); if (collision1()) { node2 = null; } else { node2.Parent = IDS.CurrentNode; node2.level = IDS.CurrentNode.level + 1; if (check(IDS, node2)) { IDS.nodes.Add(node2); } } newNodes.Add(node2); myNode node3 = new myNode(IDS.CurrentNode.X, IDS.CurrentNode.Y + 10); pictureBox3.Location = new Point(node3.X, node3.Y); if (collision1()) { node3 = null; } else { node3.Parent = IDS.CurrentNode; node3.level = IDS.CurrentNode.level + 1; if (check(IDS, node3)) { IDS.nodes.Add(node3); } } newNodes.Add(node3); myNode node4 = new myNode(IDS.CurrentNode.X, IDS.CurrentNode.Y - 10); pictureBox3.Location = new Point(node4.X, node4.Y); if (collision1()) { node4 = null; } else { node4.Parent = IDS.CurrentNode; node4.level = IDS.CurrentNode.level + 1; if (check(IDS, node4)) { IDS.nodes.Add(node4); } } newNodes.Add(node4); IDS.CurrentNode = IDS.CurrentNode.expand(newNodes); IDS.CurrentNode = IDS.nodes[iz + 1]; if (i == z - 1 && i < IDS.nodes.Count) { ++z; iz = 0; } i++; } Stack path = new Stack(); while (b) { path.Push(gool); gool = gool.Parent; if (gool == root) { b = false; } break; } int time = 0; for (int iz = 0; iz < IDS.nodes.Count; iz++) { if (IDS.nodes[iz].Visited == true) { time++; } } int PathCost = path.Count; while (path.Count != 0) { myNode temp = (myNode)path.Pop(); pictureBox1.Location = new Point(temp.X, temp.Y); pictureBox1.Refresh(); System.Threading.Thread.Sleep(50); } if (b == true) { MessageBox.Show("Congratolation \n your path cost = " + (Math.Abs((PathCost + IDS.nodes.Count) * (z - IDS.nodes.Count))) + " \n your space = " + IDS.nodes.Count + "\n your time = " + time); } }
private void label36_Click(object sender, EventArgs e)//dls { myNode gool = new myNode(0, 0); bool isGool = pictureBox1.Location.X == pictureBox2.Location.X ? true : false; myNode root = new myNode(pictureBox1.Location.X, pictureBox1.Location.Y); root.level = 0; myTree DlS = new myTree(root); DlS.CurrentNode = root; for (int i = 0; i < 50; i++) { DlS.CurrentNode.Visited = true; List <myNode> newNodes = new List <myNode>(); pictureBox3.Location = new Point(DlS.CurrentNode.X, DlS.CurrentNode.Y); if (pictureBox3.Bounds.IntersectsWith(pictureBox2.Bounds)) { gool = DlS.CurrentNode; break; } myNode node1 = new myNode(DlS.CurrentNode.X + 10, DlS.CurrentNode.Y); pictureBox3.Location = new Point(node1.X, node1.Y); if (collision1()) { node1 = null; } else { node1.Parent = DlS.CurrentNode; node1.level = DlS.CurrentNode.level + 1; if (check(DlS, node1)) { DlS.nodes.Add(node1); } } newNodes.Add(node1); myNode node2 = new myNode(DlS.CurrentNode.X - 10, DlS.CurrentNode.Y); pictureBox3.Location = new Point(node2.X, node2.Y); if (collision1()) { node2 = null; } else { node2.Parent = DlS.CurrentNode; node2.level = DlS.CurrentNode.level + 1; if (check(DlS, node2)) { DlS.nodes.Add(node2); } } newNodes.Add(node2); myNode node3 = new myNode(DlS.CurrentNode.X, DlS.CurrentNode.Y + 10); pictureBox3.Location = new Point(node3.X, node3.Y); if (collision1()) { node3 = null; } else { node3.Parent = DlS.CurrentNode; node3.level = DlS.CurrentNode.level + 1; if (check(DlS, node3)) { DlS.nodes.Add(node3); } } newNodes.Add(node3); myNode node4 = new myNode(DlS.CurrentNode.X, DlS.CurrentNode.Y - 10); pictureBox3.Location = new Point(node4.X, node4.Y); if (collision1()) { node4 = null; } else { node4.Parent = DlS.CurrentNode; node4.level = DlS.CurrentNode.level + 1; if (check(DlS, node4)) { DlS.nodes.Add(node4); } } newNodes.Add(node4); DlS.CurrentNode.expand(newNodes); DlS.CurrentNode = DlS.nodes[i + 1]; } Stack path = new Stack(); bool b = true; while (b) { if (gool == root) { b = false; } MessageBox.Show("sorry can't reach the goal☺"); break; } int time = 0; for (int i = 0; i < DlS.nodes.Count; i++) { if (DlS.nodes[i].Visited == true) { time++; } } int PathCost = path.Count; while (path.Count != 0) { myNode temp = (myNode)path.Pop(); pictureBox1.Location = new Point(temp.X, temp.Y); pictureBox1.Refresh(); System.Threading.Thread.Sleep(50); } if (b == true) { MessageBox.Show("Congratolation \n your path cost = " + PathCost + " \n your space = " + DlS.nodes.Count + "\n your time = " + time); } }
private void label33_Click(object sender, EventArgs e)//bfs { myNode gool = new myNode(0, 0); bool isGool = pictureBox1.Location.X == pictureBox2.Location.X ? true : false; myNode root = new myNode(pictureBox1.Location.X, pictureBox1.Location.Y); root.level = 0; myTree BFS = new myTree(root); BFS.CurrentNode = root; //while (!isGool) //{ for (int i = 0; i < BFS.nodes.Count; i++) { BFS.CurrentNode.Visited = true; List <myNode> newNodes = new List <myNode>(); pictureBox3.Location = new Point(BFS.CurrentNode.X, BFS.CurrentNode.Y); if (pictureBox3.Bounds.IntersectsWith(pictureBox2.Bounds)) { gool = BFS.CurrentNode; break; } // EXBAND NEW NODES myNode node1 = new myNode(BFS.CurrentNode.X + 10, BFS.CurrentNode.Y); pictureBox3.Location = new Point(node1.X, node1.Y); // System.Threading.Thread.Sleep(600); if (collision1()) { node1 = null; } else { node1.Parent = BFS.CurrentNode; node1.level = BFS.CurrentNode.level + 1; //if(!BFS.nodes.Contains(node1)) if (check(BFS, node1)) { BFS.nodes.Add(node1); } } newNodes.Add(node1); myNode node2 = new myNode(BFS.CurrentNode.X, BFS.CurrentNode.Y + 10); pictureBox3.Location = new Point(node2.X, node2.Y); // System.Threading.Thread.Sleep(600); if (collision1()) { node2 = null; } else { node2.Parent = BFS.CurrentNode; node2.level = BFS.CurrentNode.level; //if (!BFS.nodes.Contains(node2)) if (check(BFS, node2)) { BFS.nodes.Add(node2); } } newNodes.Add(node2); myNode node3 = new myNode(BFS.CurrentNode.X - 10, BFS.CurrentNode.Y); pictureBox3.Location = new Point(node3.X, node3.Y); // System.Threading.Thread.Sleep(600); if (collision1()) { node3 = null; } else { node3.Parent = BFS.CurrentNode; node3.level = BFS.CurrentNode.level + 1; //if (!BFS.nodes.Contains(node3)) if (check(BFS, node3)) { BFS.nodes.Add(node3); } } newNodes.Add(node3); myNode node4 = new myNode(BFS.CurrentNode.X, BFS.CurrentNode.Y - 10); pictureBox3.Location = new Point(node4.X, node4.Y); // System.Threading.Thread.Sleep(600); if (collision1()) { node4 = null; } else { node4.Parent = BFS.CurrentNode; node4.level = BFS.CurrentNode.level + 1; //if (!BFS.nodes.Contains(node4)) if (check(BFS, node4)) { BFS.nodes.Add(node4); } } newNodes.Add(node4); BFS.CurrentNode.expand(newNodes); // MessageBox.Show(BFS.CurrentNode.X.ToString()); BFS.CurrentNode = BFS.nodes[i + 1]; } Stack path = new Stack(); bool b = true; while (b) { path.Push(gool); gool = gool.Parent; if (gool == root) { b = false; } } int time = 0; for (int i = 0; i < BFS.nodes.Count; i++) { if (BFS.nodes[i].Visited == true) { time++; } } int PathCost = path.Count; while (path.Count != 0) { myNode temp = (myNode)path.Pop(); pictureBox1.Location = new Point(temp.X, temp.Y); pictureBox1.Refresh(); System.Threading.Thread.Sleep(50); } MessageBox.Show("Congratolation \n your path cost = " + PathCost + " \n your space = " + BFS.nodes.Count + "\n your time = " + time); }
public void PathFinderFunction(float _x, float _z, Vector3 unitPosition, ref List <Vector3> directionList, ref bool isAbleToReach) //_x와 _z는 목표점의 transform.position의 값들입니다. { // be returned value //List<Vector3> directionList = new List <Vector3>(); float myTx = Mathf.Round(unitPosition.x); float myTz = Mathf.Round(unitPosition.z); Vector3 myUnitPosition = new Vector3(myTx, 1, myTz); openNodeDic = new Dictionary <Vector3, myNode>(); closedNodeDic = new Dictionary <Vector3, myNode>(); //0.1 보이는 패쓰만 만듭니다. //0.11 보이는 패쓰만으로도 만들 수 없는지 여부를 판단합니다. //0.12 알 수없는 타일만으로 갈 수 있는지 여부도 판단합니다. //0.2 꺾는 곳마다 패쓰포인트에 기록합니다. // 열린 목록 //0.1. // A* 알고리즘을 사용합니다. // 4개의 방향으로 리스트 만들기 // 일단 좌표만 찍고, 각 부분에 벽이 있는지 바닥이 있는지 검사합니다. // 만약 바닥인 경우, 그 좌표는 이용 가능한 것으로 판정됩니다. // 이용 가능한 좌표들중에 이동한 타일 갯수, 목표지점과 현재 타일의 Dy+Dx의 값을 각각 기록합니다. // 가는 길이 없는 경우 100번 블럭도 허용합니다. //for(int i = 0, i > 1, i++) bool isUnitKnowRoute = true; // 이 변수는 초반에 아는 길로 PathFind하도록 합니다. // Pop if (checkBlockForPath(new Vector3(myTx + 1, 1, myTz), false)) { openNodeDic.Add(new Vector3(myTx + 1, 1, myTz), new myNode(myTx + 1, myTz, _x, _z, 1, myUnitPosition)); } if (checkBlockForPath(new Vector3(myTx - 1, 1, myTz), false)) { openNodeDic.Add(new Vector3(myTx - 1, 1, myTz), new myNode(myTx - 1, myTz, _x, _z, 1, myUnitPosition)); } if (checkBlockForPath(new Vector3(myTx, 1, myTz + 1), false)) { openNodeDic.Add(new Vector3(myTx, 1, myTz + 1), new myNode(myTx, myTz + 1, _x, _z, 1, myUnitPosition)); } if (checkBlockForPath(new Vector3(myTx, 1, myTz - 1), false)) { openNodeDic.Add(new Vector3(myTx, 1, myTz - 1), new myNode(myTx, myTz - 1, _x, _z, 1, myUnitPosition)); } while (true) { // 선택된 것은 가장 낮은 값이여야 합니다! // F값이 가장 낮은 값을 선정 <입력 완료> var tempMyNodeList = new List <myNode>(openNodeDic.Values); //myNode tempMyNode = tempMyNodeList.Find(tempval => tempval != null); // <<<< 문제 myNode tempMyNode = tempMyNodeList[tempMyNodeList.FindIndex(LambdaMyNode => LambdaMyNode.deltaXZ >= 0)]; // 와일 문에서 사용되는 노드. foreach (myNode NodeInList in new List <myNode>(openNodeDic.Values)) { if (tempMyNode.F > NodeInList.F) { tempMyNode = NodeInList; } } // 열린 구간에서 빼내서 닫힌 구간에 넣기 openNodeDic.Remove(tempMyNode.locate); closedNodeDic.Add(tempMyNode.locate, tempMyNode);//////////////////// //if (tempMyNodeList.FindIndex(node => node.deltaXZ == 0) != -1) // 길을 찾았습니다. 목록 중에 DeltaXZ값이 0인 노드가 있습니다. if (tempMyNode.deltaXZ == 0) { //Debug.Log("길을 찾았습니다!"); // 패스파인더를 통해 만들어진 이동 목록 만들기 // a-1 deltaXZ가 0인 노드를 찾기 // a-2 그 노드를 이동목록의 맨 첫번째에 넣기 // a-3 perv가 (myTx, 1, myTy)인지 확인하기 // a-4 그 노드의 멤버 perv를 키값으로 하여 closedNodeDic에서 찾아보기 // 이 데이터를 단순한 방향을 배열한 정보로 변환한다 디렉션어레이라고 부르자 List <myNode> moveList = new List <myNode>(); for (myNode pickedMyNode = tempMyNodeList[tempMyNodeList.FindIndex(node => node.deltaXZ == 0)]; true;) { directionList.Insert(0, pickedMyNode.locate - pickedMyNode.perv); if (pickedMyNode.perv == myUnitPosition) { break; // 이것은 맨 마지막 노드입니다. } try { pickedMyNode = closedNodeDic[pickedMyNode.perv]; // 노드의 과거를 따라 짚어갑니다. //Debug.Log("헤헤 길 찾았아요!"); } catch (KeyNotFoundException) { Debug.Log("ERROR_PathFinderFunction_값을 찾을 수 없습니다!"); break; } } isAbleToReach = true; break; // 야호 드디어 길을 찾았어요! // 경로를 생성합니다. // 이동 명령은 클릭한 지 1초 뒤에 움직이도록 합니다. // 아마 스레드로 움직일테니 이벤트를 쓸 수 있으면 쓸 수 있도록 합니다. // 이벤트 활성화가 되지 않았으면 업데이트 함수에 이동 코드가 작동하지 않음 } if ((openNodeDic.Count == 0) && isUnitKnowRoute) // 초기에는 모르는 길을 선택하지 않으니 pop위쪽에 놔둠. { Debug.Log("알고 있는 길을 찾을 수 없습니다!"); isUnitKnowRoute = false; //break; } // Pop(가장 낮은) if (checkBlockForPath(new Vector3(tempMyNode.locate.x + 1, 1, tempMyNode.locate.z), isUnitKnowRoute)) { openNodeDic.Add(new Vector3(tempMyNode.locate.x + 1, 1, tempMyNode.locate.z), new myNode(tempMyNode.locate.x + 1, tempMyNode.locate.z, _x, _z, tempMyNode.moveCount + 1, tempMyNode.locate)); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x + 1, tempMyNode.moveCount, tempMyNode.locate.z), Quaternion.identity); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x + 1, 1.5f, tempMyNode.locate.z), Quaternion.identity); } if (checkBlockForPath(new Vector3(tempMyNode.locate.x - 1, 1, tempMyNode.locate.z), isUnitKnowRoute)) { openNodeDic.Add(new Vector3(tempMyNode.locate.x - 1, 1, tempMyNode.locate.z), new myNode(tempMyNode.locate.x - 1, tempMyNode.locate.z, _x, _z, tempMyNode.moveCount + 1, tempMyNode.locate)); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x - 1, tempMyNode.moveCount, tempMyNode.locate.z), Quaternion.identity); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x + 1, 1.5f, tempMyNode.locate.z), Quaternion.identity); } if (checkBlockForPath(new Vector3(tempMyNode.locate.x, 1, tempMyNode.locate.z + 1), isUnitKnowRoute)) { openNodeDic.Add(new Vector3(tempMyNode.locate.x, 1, tempMyNode.locate.z + 1), new myNode(tempMyNode.locate.x, tempMyNode.locate.z + 1, _x, _z, tempMyNode.moveCount + 1, tempMyNode.locate)); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x, tempMyNode.moveCount, tempMyNode.locate.z + 1), Quaternion.identity); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x + 1, 1.5f, tempMyNode.locate.z), Quaternion.identity); } if (checkBlockForPath(new Vector3(tempMyNode.locate.x, 1, tempMyNode.locate.z - 1), isUnitKnowRoute)) { openNodeDic.Add(new Vector3(tempMyNode.locate.x, 1, tempMyNode.locate.z - 1), new myNode(tempMyNode.locate.x, tempMyNode.locate.z - 1, _x, _z, tempMyNode.moveCount + 1, tempMyNode.locate)); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x, tempMyNode.moveCount, tempMyNode.locate.z - 1), Quaternion.identity); //Instantiate(PathFinderGuide, new Vector3(tempMyNode.locate.x + 1, 1.5f, tempMyNode.locate.z), Quaternion.identity); } // 길이 없는 경우 if ((openNodeDic.Count == 0) && !isUnitKnowRoute) { Debug.LogWarning("길을 찾을 수 없습니다!"); isAbleToReach = false; break; } } }