zoukankan      html  css  js  c++  java
  • POJ2729 Robocode(离散化与模拟-----提醒曾经爱玩游戏的自己没做出这个

    题目链接 :http://poj.org/problem?id=2729

    题目很长,有不少也是废话。类似小时候玩的坦克大战。每个坦克速度为10,炮弹速度为20.子弹出界就消失,坦克出不了界限。相向的子弹碰撞不会消失(区别与小时候的游戏,炮弹可以抵消)。 

    坦克可以90转向...不少条件题目中仔细读可以知道。

    在这里需要注意的是,由于炮弹速度和坦克移动的速度不一致,导致对于一个时间单位,坦克与子弹在坐标上的处理挺困难。因为如果子弹在最左小角,向右边发射,坦克刚好在子弹右边一个单位,而坦克正好向左边运动,那么它们的碰撞点将会在一个距离单位的中间偏右2/3处,碰撞时间为1/3个单位时间;还有。如果坦克不动,则碰撞时间为1/2;因此我们取二者最大公约数1/6为时间单位。这样处理适合碰撞时间和地点。

    因此,120的长度将扩大为720,相当于原来的每一格变成了6小格。坦克每6个时间单位走6格,即原来的一个时间单位走一格。

      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 << "
    ";
    357     }
    358     else
    359     {
    360         cout << "NO WINNER!
    ";
    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
  • 相关阅读:
    [大数据相关] Hive中的全排序:order by,sort by, distribute by
    [mysql] Mysql数据分组GROUP BY 和HAVING,与WHERE组合使用
    【hadoop环境问题】namenode无法启动问题解决
    【java】Java.math.BigDecimal.subtract()方法实例
    利用 force index优化sql语句性能
    navicat连接远程数据库报错'client does not support authentication protocol requested by server consider ...'解决方案
    spark SQL学习(数据源之parquet)
    spark SQL学习(load和save操作)
    spark学习(RDD案例实战)
    spark学习12(Wordcount程序之spark-shell)
  • 原文地址:https://www.cnblogs.com/ygsworld/p/11116221.html
Copyright © 2011-2022 走看看