전에 있었던 c++ Astar 를 C# 으로 바꿔본 것.. C#를 처음 접해서 포인터에 대한 이해와 코드 최적화가 마구마구 떨어짐


 C#에는 우선순위큐가 없다는 걸 알았음..


어차피 Unity로 바꿔줘서 유도탄형식으로 사용할 껀데 어차피 별로 차이가 안난다고 생각했다. 그냥 순차탐색 돌렸던것 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CsharpAstar
{
    
    static class Constains
    {
        public const int SIZE = 8;
        public const float STANDARD = 1.0f;
        public const float CROSS = 1.4f;
    }
 
    public class Node 
    {
        public float x, y;
        public float fcost;
        public float gcost;
        public float hcost;
        public Node Parent;
        public Node[] Child;
        public bool is_in_openlist;
        public bool is_possible;
 
        public Node()
        {
            x = 0;
            y = 0;
            fcost = 0;
            gcost = 0;
            hcost = 0;
            //Parent = new Node();
            is_in_openlist = false;
            is_possible = true;
 
        }
        public Node(float x, float y)
        {
            this.x = x;
            this.y = y;
            fcost = 0;
            gcost = 0;
            hcost = 0;
            Parent = null;
            is_in_openlist = false;
            is_possible = true;
 
        }
        public Node(Node source)
        {
            this.x = source.x;
            this.y = source.y;
            fcost = source.fcost;
            gcost = source.gcost;
            hcost = source.hcost;
            Parent = source.Parent;
            is_in_openlist = source.is_in_openlist;
            is_possible = source.is_possible;
        }
        public void Initialize()
        {
            Child = new Node[Constains.SIZE];
 
            for (int i = 0; i < Constains.SIZE; i++)
            {
                Child[i] = new Node();
                Child[i].x = x;
                Child[i].y = y;
            }
        }
    }
 
    public class Astar
    {
        private Node start;
        private Node end;
        private Stack<Node> route;
        private List<Node> closeList;
        private List<Node> openList;
        private int close_index;
        private int open_index;
        
        public Astar(float x, float y, float x2,float y2)
        {
            route = new Stack<Node>();
            closeList = new List<Node>();
            openList = new List<Node>();
            open_index = 0;
            close_index = 0;
            start = new Node(x, y);
            end = new Node(x2, y2);
        }
 
        float Cal_fcost(Node source, int i)
        {
            return (source.Child[i].hcost + source.Child[i].gcost);
        }
 
 
        float Cal_gcost(Node source, int i)
        {
            switch (i)
            {
                case 0:
                    source.Child[i].x -= 1;
                    source.Child[i].y += 1;
                    return source.gcost + Constains.CROSS;
 
                case 2:
                    source.Child[i].x += 1;
                    source.Child[i].y += 1;
                    return source.gcost + Constains.CROSS;
 
                case 5:
                    source.Child[i].x -= 1;
                    source.Child[i].y -= 1;
                    return source.gcost + Constains.CROSS;
 
                case 7:
                    source.Child[i].x += 1;
                    source.Child[i].y -= 1;
 
                    return source.gcost + Constains.CROSS;
                  
                case 1:
                    source.Child[i].y += 1;
                    return source.gcost + Constains.STANDARD;
 
                case 3:
                    source.Child[i].x -= 1;
                    return source.gcost + Constains.STANDARD;
 
                case 4:
                    source.Child[i].x += 1;
                    return source.gcost + Constains.STANDARD;
 
                case 6:
                    source.Child[i].y -= 1;
                    
                    return source.gcost + Constains.STANDARD;
                    
                default:
                    return -1;
            }
        }
 
        float Cal_hcost(Node source, int i)
        {
            return Calculate((source.Child[i]), end);
        }
 
        float Calculate(Node source, Node destination)
        {
            return (float)Math.Sqrt((Math.Pow(destination.x - source.x, 2+ Math.Pow(destination.y - source.y, 2)));
        }
 
        bool PushOpenlist(Node source)
        {
 
            //인접 사각형에서 장애물이 있거나 이미 한번 갔던 곳이라면 openlist에 넣지않는다.
            // 그렇기 때문에 이동함수에서 본 source flag 를 true 로 바꿔주는 부분,
            // 인접 사각형 탐색시 장애물이 있다면 child 의 source 를 true로 바꿔준다.
 
            /*
                지금 내가 c++ 문법에서 짜고 있기 때문에 map table로 검사를 해서 flag 를 변경해줌
                -> 떄문에 class 안에서 미리 맵탐색을 통해 flag를 바꿔주는 부분은 제외해주어도 됨.
                -> c# 으로 옮겨주면서 unity 를 쓸떄 raycast로 Oncollision 으로 flag 를 변경해줘야 함. 
            */
            source.Initialize(); // source의 Child 를 생성해주는 부분
            for (int i = 0; i < Constains.SIZE; i++)
            {
                if (source.Child[i].is_possible == falsecontinue;
 
                if (source.Child[i].is_in_openlist == false)
                {//오픈리스트에 들어있지 않다면
 
                    //fcost gcost hcost 를 계산한다.
                    //gcost와 동시에 좌표까지 계산
                    source.Child[i].gcost = Cal_gcost(source, i);//Child 의 gcost 계산
                    if (source.Child[i].x == 4 && source.Child[i].y == 5continue;//4,5 를 막아줘봤음
                                                                                     //hcost
 
                    source.Child[i].hcost = Cal_hcost(source, i);//Child 의 hcost 계산
 
                    //fcost
 
                    source.Child[i].fcost = Cal_fcost(source, i); // Child 의 fcost 계산
 
                    source.Child[i].Parent = source; // Child의 parent Node 설정
 
                    source.Child[i].is_in_openlist = true;
 
                    openList.Add(source.Child[i]);
                    open_index++;
 
                    if (source.Child[i].hcost < 0.4)//원하는값에 근접 
                    {
                        SavePath((source.Child[i]));
                        return true;
                    }
 
                }
                else
                { // 만약 오픈리스트에 들어있다면
                    float Node_gcost = Cal_gcost(source, i);
                    if(source.Child[i].gcost < Node_gcost)
                    {
                        source.Parent = source.Child[i];
                    }
             
                }
                /*
                    차일드의 부모를 바꿔주는 작업
                */
            }
            return false;
        }
 
        Node Move(Node source)
        {
 
            if (open_index == 0return source;
 
 
            int min_index = Find_min();
            source = openList[min_index]; // 우선순위큐에서 가장 낮은 f코스트 값을 빼서 변경
            closeList.Add(source);
            close_index++;
            source.is_possible = false;
            Pop(min_index);
            return source;
        }
 
        int Find_min()
        {
            Node min = openList[0];
            int min_index = 0;
            for(int i = 0; i < open_index; i++)
            {
                if(min.fcost > openList[i].fcost)
                {
                    min = openList[i];
                    min_index = i;
                }
            }
            return min_index;
        }
 
        void Pop(int index)
        {
            if (index == open_index - 1return;
 
            for(int i = index; i < open_index - 1; i++)
            {
                openList[i] = openList[i + 1];
            }
 
            open_index--;
        }
 
        void SavePath(Node source)
        {
            while (source != null)
            {
                route.Push(source);
                source = source.Parent;
            }
        }
 
        void FollowPath()
        { // 이 부분에서는 유니티가 x,y 를 따라 움직이는 형태로 변해야됨
            while (route.Count != 0)
            {
                Console.WriteLine(route.Peek().x);
 
                Console.WriteLine(route.Peek().y);
                route.Pop();
            }
        }
 
        public void Run()
        {
            //기존 노드 push CloseList
            Node source = new Node(start.x,start.y); 
            //souce = start; 하면 어떻게 복사가될까?
            while (true)
            {
                source = Move(source);
                if (PushOpenlist(source)) break;
            }
 
            FollowPath();
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Astar astar = new Astar(1,1 , 3,3);
            astar.Run();
 
            return;
        }
    }
}
 
cs


'잡동사니' 카테고리의 다른 글

마지막 팀프  (0) 2018.06.24
팀프3  (0) 2018.06.24
팀프1-2  (0) 2018.06.24
팀프1  (0) 2018.06.24
타입 캐스팅에 관해 실험해보았다.  (0) 2018.05.26

+ Recent posts