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 好搜索啊. 现讲一 ...
随机推荐
- osg osgUtil::LineSegmentIntersector
#ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include <osgViewer/Viewer> #include ...
- MySQL复制线程状态转变
一.主库线程状态(State)值 以下列表显示了主从复制中主服务器的Binlog Dump线程的State列中可能看到的最常见状态(SHOW PROCESSLIST).如果Binlog Dump线程在 ...
- java@ 注解原理与使用
Java反射 java反射机制的定义: 在运行转态时(动态的)时. 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够知道调用它的任意属性和方法 Class对象 java中用对 ...
- Apache工作模式切换
一.apache运行模式切换 apache比较常用的工作模式有worker以及prefork两种方式 1.编译安装: 如果在编译时候不指定,系统默认的是prefork模式.如果需要换成worker模式 ...
- Microsoft Visual Studio(VS)启动报安装过程中无法运行
开机启动VS提示无法运行,很可能VS正在更新,可以等待几分钟更新完成,再次运行VS. 也可以把更新进程结束,进程名:VSIXAutoUpdate.exe
- Treeview控件如何获得子节点的所有父节点的名称
Delphi或c++ 的treeview控件,比如一个节点上面有个父节点,这个父节点上面还有一个父节点,如何获得这两个父节点的名字呢?请给出实现代码 先定义一个nodevarnode:TTreeNod ...
- 【Leetcode_easy】633. Sum of Square Numbers
problem 633. Sum of Square Numbers 题意: solution1: 可以从c的平方根,注意即使c不是平方数,也会返回一个整型数.然后我们判断如果 i*i 等于c,说明c ...
- [c++]struct timeval
struct timeval { time_t tv_sec; // seconds long tv_usec; // microseconds }; re 1. struct timespec 和 ...
- react 打印页面怎么实现?
2017-11-10 react 打印页面怎么实现?
- Tools - Tcpdump
Tcpdump homepage - tcpdump wiki - tcpdump 常用格式 tcpdump -i eth<网卡号> port <端口号> -s0 -w < ...