POJ2729 Robocode(离散化与模拟-----提醒曾经爱玩游戏的自己没做出这个
题目链接 :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(离散化与模拟-----提醒曾经爱玩游戏的自己没做出这个的更多相关文章
- JZOJ 5777. 【NOIP2008模拟】小x玩游戏
5777. [NOIP2008模拟]小x玩游戏 (File IO): input:game.in output:game.out Time Limits: 1000 ms Memory Limits ...
- 爱拼图游戏android源码完整版
这个是一款爱拼图游戏源码完整版,该游戏源码比较完整的,可以支持音乐的播放在游戏的玩的过程中,还可以控制系统的声音等,可以支持多种图片的选择来进行玩的,还可以根据自己的爱好选择不同的难度来的,级别分为: ...
- lines---hdu5124(离散化+数组模拟)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124 就是有n条在x轴的线段,给你线段的左右端点,每条线段都会覆盖点,求出最多被覆盖多少次: #inc ...
- hdu 4995(离散化下标+模拟)
Revenge of kNN Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- 腾讯爱玩某处csrf导致骚扰用户(QQ弹窗+QQ会话+微博)
点击提醒,然后抓包: POST /dyid_proc.php HTTP/1.1 Host: tx.qq.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW ...
- LYDSY模拟赛day3 涂色游戏
/* 非常好的题 */ #include <cstdio> #include <iostream> #include <cstdlib> #include < ...
- 神奇的NOIP模拟赛 T3 LGTB 玩THD
LGTB 玩THD LGTB 最近在玩一个类似DOTA 的游戏名叫THD有一天他在守一座塔,对面的N 个小兵排成一列从近到远站在塔前面每个小兵有一定的血量hi,杀死后有一定的金钱gi每一秒,他都可以攻 ...
- 神奇的NOIP模拟赛 T1 LGTB 玩扫雷
LGTB 玩扫雷 在一个n m 的棋盘上,有位置上有雷(用“*” 表示),其他位置是空地(用“.” 表示).LGTB 想在每个空地上写下它周围8 个方向相邻的格子中有几个雷.请帮助他输出写了之后的棋盘 ...
- 3173. 【GDOI2103模拟3.17】扫雷游戏(搜索 + 剪枝)
Problem 给出一个类似扫雷的游戏,有\(num\)个数字,求至少有多少个雷. Data constraint \(n,m\le 15,num\le 15\) Solution 好搜索啊. 现讲一 ...
随机推荐
- ISO/IEC 9899:2011 条款6.4.6——标点符号
6.4.6 标点符号 语法 1.以下之一 [ ] ( ) { } . -> ++ -- & * + - ...
- c# 遍历局域网计算机(电脑)获取IP和计算机名称
c#可以遍历局域网计算机,获取全部计算机的名称和IP地址,网上提供了相关的几种方法,并对效率进行了比较,但是没有对各种方法进行比较,以确定可以使用的情况.这篇文章将对这几种方法进行分析,以帮助了解各种 ...
- 005-tomcat日志体系
一.概述 首先了解java的日志体系 在JDK1.4后,sun公司增加了一个包为java.util.logging,简称为jul,用以对抗log4j. 后续还有很多日志门面方案,但是tomcat使用了 ...
- 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_20-认证接口开发-接口测试
测试接口 因为继承了spring security会拦截这个请求,我们需要写代码 让他对这个认证接口放行 查看代码发现之前已经写过放行的代码了 发现是路径前面少了auth 加断点,测试.申请令牌 r ...
- spark:neither spark.yarn.jars not spark.yarn.archive is set
1.Spark启动警告:neither spark.yarn.jars not spark.yarn.archive is set,falling back to uploading librarie ...
- JAVA数据结构和算法 1-综述:数据结构和数据类型
数据结构:指数据在计算机内存空间中或者磁盘中的组织形式. 对于数据结构的操作:插入.删除.查找.迭代遍历.排序等: Java.util包中含有诸如向量(一个可扩充的数组).栈.哈希表等类型的数据结构, ...
- NLog文章系列—系列文章目录以及简要介绍
参考文章:http://www.cnblogs.com/dflying/archive/2006/12/04/581750.aspx
- FCM实现手机推送,推送的方式,真机调试
FCM实现手机 1 下载Androidstudio 3.2 版本,之后新建一个项目 2 创建完项目之后查找文件AndroidMainifest.xml 3 访问网站注册一个自己的firebase的 ...
- 日常工作问题解决:Redhat6.5--解决yum无法正常安装配置问题
1.问题描述 解决RedHat6.5下yum功能不能用问题: 在redhat6.5下使用yum安装时,会提示:This system is not registered to Red Hat Subs ...
- [CF369E]Valera and Queries_离线_树状数组
Valera and Queries 题目链接:codeforces.com/problemset/problem/369/E 数据范围:略. 题解: 这种题,就单独考虑一次询问即可. 我们发现,包括 ...