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

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

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

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

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

 #include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std; struct Spirit // 坦克和子弹都从这个类派生
{
int x, y; // 位置
int face; // 前进方向
};
struct Bullet : public Spirit // 子弹类
{ };
struct Tank : public Spirit // 坦克类
{
string name; // 坦克名称
bool move; // 标记坦克是移动还是静止
Bullet CreateBullet(); // 坦克发射一枚子弹
};
Bullet Tank::CreateBullet() // 坦克发射一枚子弹,刚发射的时候子弹的位置和前进方向和坦克是一样的
{
Bullet b;
b.x = x;
b.y = y;
b.face = face;
return b;
} struct Command // 命令类
{
int time; // 执行时刻
string name; // 相应的坦克
string type; // 命令类型
int angle; // 如果是转向,标记转了多少度
}; class Robocode // 解题类
{
protected:
const int h; // 地图高度(离散化之后)
const int w; // 地图宽度(离散化之后)
int n; // 坦克数量
int m; // 指令数量
vector<Tank> tanks; // 坦克集合向量
vector<Bullet> bullets; // 子弹集合向量
vector<Command> commands; // 命令集合向量
int** tankmap; // tankmap[i][j]表示第i行第j列的坦克在对应的向量中的下标,如果是-1则表示第i行第j列没有坦克
int** bulletmap; // bulletmap[i][j]表示第i行第j列有没有子弹,如是是1表示第i行第j列有子弹,如果是-1则表示第i行第j列没有子弹
// void InitBullet();
void Explode(); // 检查子弹会不会击中坦克,以及击中后的处理
void ExcuteCmd(const Command& cmd); // 执行命令cmd
void UpdateBullet(); // 更新子弹集合在某一时刻的位置信息
void UpdateTank(); // 更新坦克集合在某一时刻的位置信息
public:
Robocode(int n, int m, const vector<Tank>& tanks, const vector<Command>& commands); // 构造方法
~Robocode(); // 析构方法
void Run(); // 模拟过程
void Output() const; //输出结果
}; Robocode::Robocode(int n, int m, const vector<Tank>& tanks, const vector<Command>& commands)
:h( * + ), w( * + ) // 注意高度和宽度做离散化处理,要乘上6(想想为什么)
{
this->n = n;
this->m = m;
this->tanks.reserve(n);
this->commands.reserve(m);
tankmap = new int*[h];
for (int i = ; i < h; i++)
{
tankmap[i] = new int[w];
}
bulletmap = new int*[h];
for (int i = ; i < h; i++)
{
bulletmap[i] = new int[w];
}
this->tanks.assign(tanks.begin(), tanks.end());
this->commands.assign(commands.begin(), commands.end());
for (int i = ; i < h; i++)
{
for (int j = ; j < w; j++)
{
tankmap[i][j] = -;
}
}
for (int i = ; i < h; i++)
{
for (int j = ; j < w; j++)
{
bulletmap[i][j] = -;
}
}
// 对坦克的位置信息进行离散化处理
for (unsigned int i = ; i < this->tanks.size(); i++)
{
this->tanks[i].x = (this->tanks[i].x / ) * ;
this->tanks[i].y = (this->tanks[i].y / ) * ;
this->tanks[i].move = false;
tankmap[this->tanks[i].x][this->tanks[i].y] = i;
}
// 对时间进行离散化处理
for (unsigned int i = ; i < this->commands.size(); i++)
{
this->commands[i].time *= ;
}
}
Robocode::~Robocode()
{
for (int i = ; i < h; i++)
{
delete[] tankmap[i];
}
delete[] tankmap;
for (int i = ; i < h; i++)
{
delete[] bulletmap[i];
}
delete[] bulletmap;
}
//void Robocode::InitBullet()
//{
// for (int i = 0; i < h; i++)
// {
// for (int j = 0; j < w; j++)
// {
// bulletmap[i][j] = -1;
// }
// }
// for (unsigned int i = 0; i < bullets.size(); i++)
// {
// bulletmap[bullets[i].x][bullets[i].y] = 1;
// }
//} // 判断有没有出现子弹打中坦克的情况,如果出现,进行处理
void Robocode::Explode()
{
for (int i = ; i < h; i++)
{
for (int j = ; j < w; j++)
{
if (bulletmap[i][j] > - && tankmap[i][j] > -) //离散化后的第i行第j列发生了子弹和坦克碰撞
{
for (unsigned int k = ; k < bullets.size();) // 遍历子弹,注意for语句的表达式3空缺,不可直接写k++
{
if (bullets[k].x == i && bullets[k].y == j) // 注意这里如果多个子弹和一辆坦克碰撞,都统统消失
{
bullets.erase(bullets.begin() + k); // 删除对应的子弹
}
else
{
k++;
}
}
bulletmap[i][j] = -; // 标记离散化后的第i行第j列已经没有子弹
for (unsigned int k = ; k < tanks.size();) // 遍历坦克,注意for语句的表达式3空缺,不可直接写k++
{
if (tanks[k].x == i && tanks[k].y == j) // 注意这里如果多辆坦克和一个子弹碰撞,都统统消失
{
tanks.erase(tanks.begin() + k); // 删除对应的坦克
}
else
{
k++;
}
}
tankmap[i][j] = -; // 标记离散化后的第i行第j列已经没有坦克
}
}
}
} // 执行命令cmd
void Robocode::ExcuteCmd(const Command& cmd)
{
for (unsigned int i = ; i < tanks.size(); i++)
{
if (cmd.name == tanks[i].name)
{
if (cmd.type == "MOVE") // 坦克移动,设置相应标志即可
{
tanks[i].move = true;
}
else if (cmd.type == "STOP") // 坦克停止,设置相应标志即可
{
tanks[i].move = false;
}
else if (cmd.type == "TURN") // 坦克转向处理,注意取模
{
tanks[i].face = (tanks[i].face + cmd.angle + ) % ;
}
else if (cmd.type == "SHOOT") // 大炮开兮轰他娘(张宗昌)
{
Bullet b = tanks[i].CreateBullet(); // 坦克产生子弹
bullets.push_back(b); // 更新子弹向量
bulletmap[b.x][b.y] = bullets.size() - ; // 标记对应的行列位置有子弹,设置子弹的下标
}
}
}
} // 更新离散化后的某个时刻的子弹的位置信息
void Robocode::UpdateBullet()
{
for (unsigned int i = ; i < bullets.size(); )
{
// 反正子弹在消失以前总是飞的,所以上一时刻子弹i出现的位置和这一时刻子弹i出现的位置必定不一样,先把原先位置标记没有子弹
bulletmap[bullets[i].x][bullets[i].y] = -;
switch (bullets[i].face) // 根据子弹的前进方向判断子弹在这一时刻的位置
{
case :
bullets[i].x += ; // 注意离散化后,子弹每次移动2个单位
if (bullets[i].x > w - ) // 子弹向右飞出了区域,应从战场消失
{
bullets.erase(bullets.begin() + i);
}
else
{
bulletmap[bullets[i].x][bullets[i].y] = i; // 子弹向右到了下一个位置,更新相应的信息
i++;
}
break;
case :
bullets[i].y += ; // 注意离散化后,子弹每次移动2个单位
if (bullets[i].y > h - ) // 子弹向下飞出了区域,应从战场消失
{
bullets.erase(bullets.begin() + i);
}
else
{
bulletmap[bullets[i].x][bullets[i].y] = i; // 子弹向下到了下一个位置,更新相应的信息
i++;
}
break;
case :
bullets[i].x -= ; // 注意离散化后,子弹每次移动2个单位
if (bullets[i].x < ) // 子弹向左飞出了区域,应从战场消失
{
bullets.erase(bullets.begin() + i);
}
else
{
bulletmap[bullets[i].x][bullets[i].y] = i; // 子弹向左到了下一个位置,更新相应的信息
i++;
}
break;
case :
bullets[i].y -= ; // 注意离散化后,子弹每次移动2个单位
if (bullets[i].y < ) // 子弹向上飞出了区域,应从战场消失
{
bullets.erase(bullets.begin() + i);
}
else
{
bulletmap[bullets[i].x][bullets[i].y] = i; // 子弹向上到了下一个位置,更新相应的信息
i++;
}
break;
}
}
//InitBullet();
} // 更新某一时刻的坦克的位置信息
void Robocode::UpdateTank()
{
for (unsigned int i = ; i < tanks.size(); i++)
{
if (tanks[i].move) // 只处理在移动的坦克,有的坦克是静止的,不用处理
{
tankmap[tanks[i].x][tanks[i].y] = -; // 移动的坦克肯定不在原先的位置了
switch (tanks[i].face) // 根据坦克的前进方向判断坦克在这一时刻的位置
{
case : // 向右前进
tanks[i].x += ; // 注意离散化后,坦克每次移动1个单位
if (tanks[i].x > w - ) // 如果到达最右边的边界
{
tanks[i].x = w - ; // 不能穿越也不能消失,在右边界原地不动
}
break;
case : // 向下前进
tanks[i].y += ; // 注意离散化后,坦克每次移动1个单位
if (tanks[i].y > h - ) // 如果到达最下边的边界
{
tanks[i].y = h - ; // 不能穿越也不能消失,在下边界原地不动
}
break;
case :
tanks[i].x -= ; // 注意离散化后,坦克每次移动1个单位
if (tanks[i].x < ) // 如果到达最左边的边界
{
tanks[i].x = ; // 不能穿越也不能消失,在左边界原地不动
}
break;
case :
tanks[i].y -= ; // 注意离散化后,坦克每次移动1个单位
if (tanks[i].y < ) // 如果到达最上边的边界
{
tanks[i].y = ; // 不能穿越也不能消失,在上边界原地不动
}
break;
}
tankmap[tanks[i].x][tanks[i].y] = i; // 在新位置标记坦克在坦克向量中的下标
}
}
}
void Robocode::Run()
{
unsigned int cmdidx = ;
int time = ;
bullets.clear();
for (int i = ; i < h; i++)
{
for (int j = ; j < w; j++)
{
bulletmap[i][j] = -;
}
}
while (true)
{
//InitBullet();
Explode(); // 先处理这一时刻有没有子弹击中坦克的情况,why? //遍历命令向量,如果某个向量的执行时刻到了,就执行
while (cmdidx < commands.size() && commands[cmdidx].time == time)
{
ExcuteCmd(commands[cmdidx]);
cmdidx++;
} UpdateBullet(); // 更新子弹位置信息
UpdateTank(); // 更新坦克位置信息
//Explode();
if (cmdidx >= commands.size()) //命令全部执行完了
{
if (bullets.size() > ) // 让子弹再飞一会(姜文《让子弹飞》)
{ }
else // 如果命令全部执行完了,子弹也飞完了,说明游戏结束
{
break;
}
}
time++; // 时间单位计数器加1
}
} void Robocode::Output() const
{
if (tanks.size() == )
{
cout << tanks[].name << "\n";
}
else
{
cout << "NO WINNER!\n";
}
} int main()
{
//ifstream cin("Text.txt");
int n = ;
int m = ;
cin >> n >> m;
while (n > && m > )
{
vector<Tank> tanks;
vector<Command> commands;
for (int i = ; i < n; i++)
{
Tank t;
cin >> t.name >> t.x >> t.y >> t.face;
tanks.push_back(t);
}
for (int i = ; i < m; i++)
{
Command c;
cin >> c.time >> c.name >> c.type;
if (c.type == "TURN")
{
cin >> c.angle;
}
commands.push_back(c);
}
Robocode obj(n, m, tanks, commands);
obj.Run();
obj.Output();
cin >> n >> m;
}
return ;
}

POJ2729 Robocode(离散化与模拟-----提醒曾经爱玩游戏的自己没做出这个的更多相关文章

  1. JZOJ 5777. 【NOIP2008模拟】小x玩游戏

    5777. [NOIP2008模拟]小x玩游戏 (File IO): input:game.in output:game.out Time Limits: 1000 ms  Memory Limits ...

  2. 爱拼图游戏android源码完整版

    这个是一款爱拼图游戏源码完整版,该游戏源码比较完整的,可以支持音乐的播放在游戏的玩的过程中,还可以控制系统的声音等,可以支持多种图片的选择来进行玩的,还可以根据自己的爱好选择不同的难度来的,级别分为: ...

  3. lines---hdu5124(离散化+数组模拟)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124 就是有n条在x轴的线段,给你线段的左右端点,每条线段都会覆盖点,求出最多被覆盖多少次: #inc ...

  4. hdu 4995(离散化下标+模拟)

    Revenge of kNN Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  5. 腾讯爱玩某处csrf导致骚扰用户(QQ弹窗+QQ会话+微博)

    点击提醒,然后抓包: POST /dyid_proc.php HTTP/1.1 Host: tx.qq.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW ...

  6. LYDSY模拟赛day3 涂色游戏

    /* 非常好的题 */ #include <cstdio> #include <iostream> #include <cstdlib> #include < ...

  7. 神奇的NOIP模拟赛 T3 LGTB 玩THD

    LGTB 玩THD LGTB 最近在玩一个类似DOTA 的游戏名叫THD有一天他在守一座塔,对面的N 个小兵排成一列从近到远站在塔前面每个小兵有一定的血量hi,杀死后有一定的金钱gi每一秒,他都可以攻 ...

  8. 神奇的NOIP模拟赛 T1 LGTB 玩扫雷

    LGTB 玩扫雷 在一个n m 的棋盘上,有位置上有雷(用“*” 表示),其他位置是空地(用“.” 表示).LGTB 想在每个空地上写下它周围8 个方向相邻的格子中有几个雷.请帮助他输出写了之后的棋盘 ...

  9. 3173. 【GDOI2103模拟3.17】扫雷游戏(搜索 + 剪枝)

    Problem 给出一个类似扫雷的游戏,有\(num\)个数字,求至少有多少个雷. Data constraint \(n,m\le 15,num\le 15\) Solution 好搜索啊. 现讲一 ...

随机推荐

  1. springboot之多模块化项目打包

    1.目录结构 2.打成war包,只需在web子项目中的pom文件中添加 <packaging>war</packaging> <build> <!-- 为ja ...

  2. Qt编写自定义控件46-树状导航栏

    一.前言 树状导航栏控件是所有控件中最牛逼最经典最厉害的一个,在很多购买者中,使用频率也是最高,因为该导航控件集合了非常多的展示效果,比如左侧图标+右侧箭头+元素前面的图标设置+各种颜色设置等,全部涵 ...

  3. 123457123456---com.treeapp.quweiyingyushuzi01----趣味英语数字游戏(儿童宝宝学英语)

    com.treeapp.quweiyingyushuzi01----趣味英语数字游戏(儿童宝宝学英语)

  4. SpringCloud学习成长之路 五 路由器网关

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: ...

  5. npm的问题【解决】

    1.解决npm下载慢的问题,使用该命令 npm install --registry=https://registry.npm.taobao.org 好处:比起cnpm官网解释的,这个更好,使用cnp ...

  6. MVC模式实现注册登录

    很多人对MVC模式搞不懂,刚开始是我也犯迷糊,知道看到一个前辈写的代码,我顿时有的恍然大悟,拿来分享给各位 MVC: 就是M:模型.V:视图(前台界面)C:后台处理的servlet 话不多说.上代码 ...

  7. 权限管理ranger

    为超级管理员airflow赋权: 在ranger 中的hive中加入root policy, url policy 在hdfs中加入/ 的poclicy 你如果需要自动ldap同步,时间1小时,ran ...

  8. Redis 集群_主从复制_哨兵模型

    1 redis集群简介 1.1 集群的概念 所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定.高效的状态. 1.1.1 使用redis集群的必要性 问题:我们已经部署好了 ...

  9. PAT甲级 散列题_C++题解

    散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...

  10. Centos6.5镜像下载

    CentOS6.5系统安装 1.首先打开网易开源镜像站: http://mirrors.163.com/ 当然,大家也可以使用阿里开源镜像站:http://mirrors.aliyun.com/ 2. ...