POJ2729 Robocode(離散化與模擬-----提醒曾經愛玩遊戲的本身沒作出這個

題目連接 :http://poj.org/problem?id=2729ios

題目很長,有很多也是廢話。相似小時候玩的坦克大戰。每一個坦克速度爲10,炮彈速度爲20.子彈出界就消失,坦克出不了界限。相向的子彈碰撞不會消失(區別與小時候的遊戲,炮彈能夠抵消)。 ide

坦克能夠90轉向...很多條件題目中仔細讀能夠知道。this

在這裏須要注意的是,因爲炮彈速度和坦克移動的速度不一致,致使對與一個時間單位,坦克與子彈在座標上的處理挺困難。由於若是子彈在最左小角,向右邊發射,坦克恰好在子彈右邊一個單位,而坦克正好向左邊運動,spa

那麼它們的碰撞點將會在一個距離單位的中間偏右2/3處,碰撞時間爲1/3個單位時間;還有。若是坦克不動,則碰撞時間爲1/2;所以咱們取兩者最大公約數1/6爲時間單位。這樣處理適合碰撞時間和地點。code

所以,120的長度將擴大爲720,至關於原來的每一格變成了6小格。坦克每6個時間單位走6格,即原來的一個時間單位走一格。blog

  1 #include <iostream>
  2 #include <fstream>
  3 #include <string>
  4 #include <vector>
  5 using namespace std;
  6 
  7 struct Spirit // 坦克和子彈都從這個類派生
  8 {
  9     int x, y; // 位置
 10     int face; // 前進方向
 11 };
 12 struct Bullet : public Spirit // 子彈類
 13 {
 14 
 15 };
 16 struct Tank : public Spirit // 坦克類
 17 {
 18     string name; // 坦克名稱
 19     bool move; // 標記坦克是移動仍是靜止
 20     Bullet CreateBullet(); // 坦克發射一枚子彈
 21 };
 22 Bullet Tank::CreateBullet() // 坦克發射一枚子彈,剛發射的時候子彈的位置和前進方向和坦克是同樣的
 23 {
 24     Bullet b;
 25     b.x = x;
 26     b.y = y;
 27     b.face = face;
 28     return b;
 29 }
 30 
 31 struct Command // 命令類
 32 {
 33     int time; // 執行時刻
 34     string name; // 相應的坦克
 35     string type; // 命令類型
 36     int angle; // 若是是轉向,標記轉了多少度
 37 };
 38 
 39 class Robocode // 解題類
 40 {
 41 protected:
 42     const int h; // 地圖高度(離散化以後)
 43     const int w; // 地圖寬度(離散化以後)
 44     int n; // 坦克數量
 45     int m; // 指令數量
 46     vector<Tank> tanks; // 坦克集合向量
 47     vector<Bullet> bullets; // 子彈集合向量
 48     vector<Command> commands; // 命令集合向量
 49     int** tankmap; // tankmap[i][j]表示第i行第j列的坦克在對應的向量中的下標,若是是-1則表示第i行第j列沒有坦克
 50     int** bulletmap; // bulletmap[i][j]表示第i行第j列有沒有子彈,如是是1表示第i行第j列有子彈,若是是-1則表示第i行第j列沒有子彈
 51     // void InitBullet();
 52     void Explode(); // 檢查子彈會不會擊中坦克,以及擊中後的處理
 53     void ExcuteCmd(const Command& cmd); // 執行命令cmd
 54     void UpdateBullet(); // 更新子彈集合在某一時刻的位置信息
 55     void UpdateTank(); // 更新坦克集合在某一時刻的位置信息
 56 public:
 57     Robocode(int n, int m, const vector<Tank>& tanks, const vector<Command>& commands); // 構造方法
 58     ~Robocode(); // 析構方法
 59     void Run(); // 模擬過程
 60     void Output() const; //輸出結果
 61 };
 62 
 63 Robocode::Robocode(int n, int m, const vector<Tank>& tanks, const vector<Command>& commands) 
 64     :h(12 * 6 + 1), w(12 * 6 + 1) // 注意高度和寬度作離散化處理,要乘上6(想一想爲何)
 65 {
 66     this->n = n;
 67     this->m = m;
 68     this->tanks.reserve(n);
 69     this->commands.reserve(m);
 70     tankmap = new int*[h];
 71     for (int i = 0; i < h; i++)
 72     {
 73         tankmap[i] = new int[w];
 74     }
 75     bulletmap = new int*[h];
 76     for (int i = 0; i < h; i++)
 77     {
 78         bulletmap[i] = new int[w];
 79     }
 80     this->tanks.assign(tanks.begin(), tanks.end());
 81     this->commands.assign(commands.begin(), commands.end());
 82     for (int i = 0; i < h; i++)
 83     {
 84         for (int j = 0; j < w; j++)
 85         {
 86             tankmap[i][j] = -1;
 87         }
 88     }
 89     for (int i = 0; i < h; i++)
 90     {
 91         for (int j = 0; j < w; j++)
 92         {
 93             bulletmap[i][j] = -1;
 94         }
 95     }
 96     // 對坦克的位置信息進行離散化處理
 97     for (unsigned int i = 0; i < this->tanks.size(); i++)
 98     {
 99         this->tanks[i].x = (this->tanks[i].x / 10) * 6;
100         this->tanks[i].y = (this->tanks[i].y / 10) * 6;
101         this->tanks[i].move = false;
102         tankmap[this->tanks[i].x][this->tanks[i].y] = i;
103     }
104     // 對時間進行離散化處理
105     for (unsigned int i = 0; i < this->commands.size(); i++)
106     {
107         this->commands[i].time *= 6;
108     }
109 }
110 Robocode::~Robocode()
111 {
112     for (int i = 0; i < h; i++)
113     {
114         delete[] tankmap[i];
115     }
116     delete[] tankmap;
117     for (int i = 0; i < h; i++)
118     {
119         delete[] bulletmap[i];
120     }
121     delete[] bulletmap;
122 }
123 //void Robocode::InitBullet()
124 //{
125 //    for (int i = 0; i < h; i++)
126 //    {
127 //        for (int j = 0; j < w; j++)
128 //        {
129 //            bulletmap[i][j] = -1;
130 //        }
131 //    }
132 //    for (unsigned int i = 0; i < bullets.size(); i++)
133 //    {
134 //        bulletmap[bullets[i].x][bullets[i].y] = 1;
135 //    }
136 //}
137 
138 // 判斷有沒有出現子彈打中坦克的狀況,若是出現,進行處理
139 void Robocode::Explode()
140 {
141     for (int i = 0; i < h; i++)
142     {
143         for (int j = 0; j < w; j++)
144         {
145             if (bulletmap[i][j] > -1 && tankmap[i][j] > -1) //離散化後的第i行第j列發生了子彈和坦克碰撞
146             {
147                 for (unsigned int k = 0; k < bullets.size();) // 遍歷子彈,注意for語句的表達式3空缺,不可直接寫k++
148                 {
149                     if (bullets[k].x == i && bullets[k].y == j) // 注意這裏若是多個子彈和一輛坦克碰撞,都通通消失
150                     {
151                         bullets.erase(bullets.begin() + k); // 刪除對應的子彈
152                     }
153                     else
154                     {
155                         k++;
156                     }
157                 }
158                 bulletmap[i][j] = -1;  // 標記離散化後的第i行第j列已經沒有子彈
159                 for (unsigned int k = 0; k < tanks.size();) // 遍歷坦克,注意for語句的表達式3空缺,不可直接寫k++
160                 {
161                     if (tanks[k].x == i && tanks[k].y == j) // 注意這裏若是多輛坦克和一個子彈碰撞,都通通消失
162                     {
163                         tanks.erase(tanks.begin() + k); // 刪除對應的坦克
164                     }
165                     else
166                     {
167                         k++;
168                     }
169                 }
170                 tankmap[i][j] = -1; // 標記離散化後的第i行第j列已經沒有坦克
171             }
172         }
173     }
174 }
175 
176 // 執行命令cmd
177 void Robocode::ExcuteCmd(const Command& cmd)
178 {
179     for (unsigned int i = 0; i < tanks.size(); i++)
180     {
181         if (cmd.name == tanks[i].name)
182         {
183             if (cmd.type == "MOVE") // 坦克移動,設置相應標誌便可
184             {
185                 tanks[i].move = true;
186             }
187             else if (cmd.type == "STOP") // 坦克中止,設置相應標誌便可
188             {
189                 tanks[i].move = false;
190             }
191             else if (cmd.type == "TURN") // 坦克轉向處理,注意取模
192             {
193                 tanks[i].face = (tanks[i].face + cmd.angle + 360) % 360;
194             }
195             else if (cmd.type == "SHOOT") // 大炮開兮轟他娘(張宗昌)
196             {
197                 Bullet b = tanks[i].CreateBullet(); // 坦克產生子彈
198                 bullets.push_back(b); // 更新子彈向量
199                 bulletmap[b.x][b.y] = bullets.size() - 1; // 標記對應的行列位置有子彈,設置子彈的下標
200             }
201         }
202     }
203 }
204 
205 // 更新離散化後的某個時刻的子彈的位置信息
206 void Robocode::UpdateBullet()
207 {
208     for (unsigned int i = 0; i < bullets.size(); )
209     {
210         // 反正子彈在消失之前老是飛的,因此上一時刻子彈i出現的位置和這一時刻子彈i出現的位置一定不同,先把原先位置標記沒有子彈
211         bulletmap[bullets[i].x][bullets[i].y] = -1; 
212         switch (bullets[i].face) // 根據子彈的前進方向判斷子彈在這一時刻的位置
213         {
214         case 0:
215             bullets[i].x += 2; // 注意離散化後,子彈每次移動2個單位
216             if (bullets[i].x > w - 1) // 子彈向右飛出了區域,應從戰場消失
217             {
218                 bullets.erase(bullets.begin() + i);
219             }
220             else
221             {
222                 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向右到了下一個位置,更新相應的信息
223                 i++;
224             }
225             break;
226         case 90:
227             bullets[i].y += 2; // 注意離散化後,子彈每次移動2個單位
228             if (bullets[i].y > h  - 1) // 子彈向下飛出了區域,應從戰場消失
229             {
230                 bullets.erase(bullets.begin() + i);
231             }
232             else
233             {
234                 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向下到了下一個位置,更新相應的信息
235                 i++;
236             }
237             break;
238         case 180:
239             bullets[i].x -= 2; // 注意離散化後,子彈每次移動2個單位
240             if (bullets[i].x < 0) // 子彈向左飛出了區域,應從戰場消失
241             {
242                 bullets.erase(bullets.begin() + i);
243             }
244             else
245             {
246                 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向左到了下一個位置,更新相應的信息
247                 i++;
248             }
249             break;
250         case 270:
251             bullets[i].y -= 2; // 注意離散化後,子彈每次移動2個單位
252             if (bullets[i].y < 0) // 子彈向上飛出了區域,應從戰場消失
253             {
254                 bullets.erase(bullets.begin() + i);
255             }
256             else
257             {
258                 bulletmap[bullets[i].x][bullets[i].y] = i; // 子彈向上到了下一個位置,更新相應的信息
259                 i++;
260             }
261             break;
262         }
263     }
264     //InitBullet();
265 }
266 
267 // 更新某一時刻的坦克的位置信息
268 void Robocode::UpdateTank()
269 {
270     for (unsigned int i = 0; i < tanks.size(); i++)
271     {
272         if (tanks[i].move) // 只處理在移動的坦克,有的坦克是靜止的,不用處理
273         {
274             tankmap[tanks[i].x][tanks[i].y] = -1; // 移動的坦克確定不在原先的位置了
275             switch (tanks[i].face) // 根據坦克的前進方向判斷坦克在這一時刻的位置
276             {
277             case 0: // 向右前進
278                 tanks[i].x += 1; // 注意離散化後,坦克每次移動1個單位
279                 if (tanks[i].x > w - 1) // 若是到達最右邊的邊界
280                 {
281                     tanks[i].x = w - 1; // 不能穿越也不能消失,在右邊界原地不動
282                 }
283                 break;
284             case 90: // 向下前進
285                 tanks[i].y += 1; // 注意離散化後,坦克每次移動1個單位
286                 if (tanks[i].y > h - 1) // 若是到達最下邊的邊界
287                 {
288                     tanks[i].y = h - 1; // 不能穿越也不能消失,在下邊界原地不動
289                 }
290                 break;
291             case 180:
292                 tanks[i].x -= 1; // 注意離散化後,坦克每次移動1個單位
293                 if (tanks[i].x < 0) // 若是到達最左邊的邊界
294                 {
295                     tanks[i].x = 0; // 不能穿越也不能消失,在左邊界原地不動
296                 }
297                 break;
298             case 270:
299                 tanks[i].y -= 1; // 注意離散化後,坦克每次移動1個單位
300                 if (tanks[i].y < 0) // 若是到達最上邊的邊界
301                 {
302                     tanks[i].y = 0; // 不能穿越也不能消失,在上邊界原地不動
303                 }
304                 break;
305             }
306             tankmap[tanks[i].x][tanks[i].y] = i; // 在新位置標記坦克在坦克向量中的下標
307         }
308     }
309 }
310 void Robocode::Run()
311 {
312     unsigned int cmdidx = 0;
313     int time = 0;
314     bullets.clear();
315     for (int i = 0; i < h; i++)
316     {
317         for (int j = 0; j < w; j++)
318         {
319             bulletmap[i][j] = -1;
320         }
321     }
322     while (true)
323     {
324         //InitBullet();
325         Explode(); // 先處理這一時刻有沒有子彈擊中坦克的狀況,why?
326 
327         //遍歷命令向量,若是某個向量的執行時刻到了,就執行
328         while (cmdidx < commands.size() && commands[cmdidx].time == time) 
329         {
330             ExcuteCmd(commands[cmdidx]);
331             cmdidx++;
332         }
333         
334         UpdateBullet(); // 更新子彈位置信息
335         UpdateTank(); // 更新坦克位置信息
336         //Explode();
337         if (cmdidx >= commands.size()) //命令所有執行完了
338         {
339             if (bullets.size() > 0) // 讓子彈再飛一會(姜文《讓子彈飛》)
340             {
341 
342             }
343             else // 若是命令所有執行完了,子彈也飛完了,說明遊戲結束
344             {
345                 break;
346             }
347         }
348         time++; // 時間單位計數器加1
349     }
350 }
351 
352 void Robocode::Output() const
353 {
354     if (tanks.size() == 1)
355     {
356         cout << tanks[0].name << "\n";
357     }
358     else
359     {
360         cout << "NO WINNER!\n";
361     }
362 }
363 
364 int main()
365 {
366     //ifstream cin("Text.txt");
367     int n = 0;
368     int m = 0;
369     cin >> n >> m;
370     while (n > 0 && m > 0)
371     {
372         vector<Tank> tanks;
373         vector<Command> commands;
374         for (int i = 0; i < n; i++)
375         {
376             Tank t;
377             cin >> t.name >> t.x >> t.y >> t.face;
378             tanks.push_back(t);
379         }
380         for (int i = 0; i < m; i++)
381         {
382             Command c;
383             cin >> c.time >> c.name >> c.type;
384             if (c.type == "TURN")
385             {
386                 cin >> c.angle;
387             }
388             commands.push_back(c);
389         }
390         Robocode obj(n, m, tanks, commands);
391         obj.Run();
392         obj.Output();
393         cin >> n >> m;
394     }
395     return 0;
396 }
View Code
相關文章
相關標籤/搜索