一,题目
在这个弱肉强食的世界里总有一批黑恶恐怖势力匪徒企图破坏他人辛勤的劳动成果。正义的警察需要保护区域的安全,防止匪徒使用C4炸弹对区域造成破坏,一场激烈的反恐对抗即将拉开帷幕!
本游戏为回合制游戏,后续所讲的时间,都统一以回合为单位。
由玩家控制的警察或匪徒角色称为玩家角色,本游戏中玩家的客户端只控制己方的5个角色(5个警察或5个匪徒)进行移动、攻击、换枪等动作。角色死亡后不可复活。
每个队伍初始发放20000金钱,所有人物共用。
金钱只会在购买武器道具时消耗,不会增长。
动作 | 指令 | 描述 |
攻击 | AD | 使用当前武器攻击一个目标,对武器攻击范围内的敌方单位造成武器伤害。枪的攻击范围是一条直线。 枪支的攻击可以在其攻击直线范围上对第一个敌方单位造成伤害,后面的不造成伤害;如果第一个敌方单位位置上有多个敌方单位,则都受到伤害。 友军不受攻击伤害且不会阻挡子弹。 |
移动 | MOVE | 角色向目标移动,当目标为障碍物时移动失败,目标不为障碍物时移动成功。 移动可以和其它任何动作在一回合之内发送,不受互斥影响。 |
捡枪 | PICK | 在当前位置上有掉落的长枪时,使用捡枪指令可以更换手中的长枪与地上掉落的枪支。 |
购买装备 | BUY | 角色在己方基地范围内时,可以通过购买装备指令来购买长枪,手雷,护甲等装备。 |
安装C4 | PLANT | 匪徒角色在A区或B区布雷点范围内,可以通过这个指令安装C4,并等待爆炸。 |
解除C4 | DEFUSE | 警察角色站在已经布下的C4位置上执行此指令可以开始解除C4,解除C4需要30回合,在30回合之内执行其它的指令会打断解雷过程,打断后只能重新开始。 |
扔手雷 | THROW | 在手持手雷时执行此动作可以将手雷扔向目标点,手雷将在3回合后在目标点爆炸。手雷不受障碍物的限制,可以穿越障碍物在目标点爆炸。 |
买子弹 | BUY_BULLETS | 角色可以在己方基地范围内执行此命令购买子弹,购买子弹的动作可以补满当前手持枪支的子弹。 |
切换武器 | SWITCH | 角色可以通过此指令切换手持的武器。如扔手雷需要先切换到手雷,安装C4需要先切换到C4。 |
二,思路笔记
1,概念
阵营 一方警察 5个 一方匪徒 5个
角色 0警察 1匪徒
生命值:初始化为100,期间不会恢复,生命小于等于0时,将判定角色单位死亡。死亡后不可复活。
护甲值:初始化为0,购买护甲之后得到100护甲值,护甲值可以提供75%的伤害减免,生命值和护甲值比例是1:1
动作:8种动作(警察匪徒共9种)
金钱 初始发放20000金钱,所有人物共用,只会在购买武器道具时消耗,不会增长。
武器
初始武器:1种刀、2种手枪,开局自带,不用购买也不可购买。不会掉落。
可购买武器:1个手雷、5种长枪,会掉落。捡枪指令交换身上持有的长枪和地上的长枪。
C4炸弹:匪徒1号专属,其它匪徒角色可以捡起来
枪不能穿墙,手雷无视墙
AWP在攻击之后5回合内,将处于冷却状态不能攻击。
地图 67行75列
空地,障碍物,警/匪出生点,布雷区A/B 基地是购买装备的
距离计算公式:max(Δx, Δy)
视野:角色视野距离为20,且己方所有单位共享视野
获胜条件
C4爆炸之后匪徒直接取得胜利。
C4拆除之后警察直接获胜。
未布下C4时,一方杀死对方全员,且己方还有人的情况下获胜
达到回合上限之后,代表警察成功防守区域,警获胜
2,注意点
所有比赛过程中只使用此张地图,不会再变更!
拆炸弹需要30回合,不是20
寻路已经有了:JPS
3) 客户端Socket通信一次收包可能收不全(需处理粘包、分包问题)
自己控制回合缓存
3,疑问
枪的攻击路线上有障碍物是咋判断啊,比如站位是斜的,这个直线是怎么算的?如果2个墙格子是斜对角,子弹可以从缝里面插过去吗?
买枪之后是否自动切换?
如果某个格子上有多个敌人,会全部中枪,但是格子后面的敌人不会受到伤害?
手雷可以扔到20距离,范围和威力都是10?
冷却时间是否告知?
C4被其他匪徒捡起来之后,我方知道是谁捡起的吗?
4,策略
角色武器配置策略
角色站位配置策略
警察:AWP在基地下面一点控制全场
匪徒:AWP攻击上路
单点高价值位置识别
多角色之间攻击配合
三,代码框架
1,先定义数据结构
定义2个数据结构,1个是输入,1个是输出
输入:
enum CampType {
POLICE = 0,
GANGSTER,
};
enum RoleIdType {
HUMAN = 2,
BOMB = 4,
EQUIPMENT = 8,
PLANT_C4 = 16,
};
struct Statuses {
int planting;
int defusing;
int exploding;
};
struct Position {
Position(){
x=y=0;
}
Position(int xx,int yy){
x=xx,y=yy;
}
int x;
int y;
};
struct Weapon {
int equipmentId;
int bullets;
bool coolingDown;
bool isGun(){
return equipmentId>10 && equipmentId < 50;
}
bool isHugeGun(){
return equipmentId>30 && equipmentId < 50;
}
bool isAWP(){
return equipmentId == 45;
}
};
class Object {
public:
virtual int Inquire(cJSON *obj);
virtual void Dump();
int id;
int roleId;
struct Position pos;
struct Statuses statuses;
};
class Player : public Object {
public:
int Inquire(cJSON *playerObj) override;
Player(int id, int roleId, int camp)
{
this->id = id;
this->roleId = roleId;
this->camp = camp;
}
virtual ~Player() {}
void Dump() override;
private:
int GetEquipment(cJSON *equipmentObj, struct Weapon &equipment);
public:
int camp;
int defence;
int life;
int maxLife;
struct Weapon usingWeapon;
std::vector<struct Weapon> equipments;
};
class Bomb : public Object {
public:
Bomb(int id, int roleId)
{
this->id = id;
this->roleId = roleId;
}
virtual ~Bomb() {}
int Inquire(cJSON *bombObj) override;
void Dump() override;
int equipmentId;
};
class Equipment : public Object {
public:
Equipment(int id, int roleId)
{
this->id = id;
this->roleId = roleId;
}
virtual ~Equipment() {}
int Inquire(cJSON *equipmentObj) override;
void Dump() override;
int equipmentId;
};
class PlantC4 : public Object {
public:
PlantC4(int id, int roleId)
{
this->id = id;
this->roleId = roleId;
}
virtual ~PlantC4() {}
int Inquire(cJSON *plantC4Obj) override;
void Dump() override;
int equipmentId;
};
struct EquipmentInfo {
int bulletsPerRound;//每回合攻击所消耗的子弹数。
int coolDown;
int damage;//武器伤害,每回合造成的武器伤害。
int defence;//护甲的最大防护
int id;
int maxBullets;//武器所能装的最大子弹数
std::string name;
int price;
int range;//攻击范围。
};
class EquipmentTemplates {
public:
EquipmentTemplates() {}
virtual ~EquipmentTemplates() {}
int Start(cJSON *obj);
private:
int GetEquipment(cJSON *equipmentObj, struct EquipmentInfo &equipment);
int GetObjIntValue(cJSON *obj, std::string name, int &value);
int GetObjStrValue(cJSON *obj, std::string name, std::string &value);
void Dump();
public:
std::map<int, struct EquipmentInfo> equipmentes;
};
/*
struct WeaponBase{
int type;//0自带武器,1购买武器,2手雷, 3护甲,4C4
int price;//售价
int range;//攻击范围。
int damage;//武器伤害,每回合造成的武器伤害。
int bulletsPerRound;//每回合攻击所消耗的子弹数。
int maxBullets;//武器所能装的最大子弹数,或护甲的最大防护
};
map<id,WeaponBase>allWeapons;
allWeapons[1]= WeaponBase {0,0,1,8,0,1},//Knife
allWeapons[11]= WeaponBase {0,0,10,2,1,120},//Glock 18
allWeapons[12]= WeaponBase {0,0,10,2,1,120},//Five seven
allWeapons[31]= WeaponBase {1,1500,15,3,3,150},//MP5
allWeapons[33]= WeaponBase {1,1200,15,3,5,200},//P90
allWeapons[42]= WeaponBase {1,2500,30,5,2,120},//AK47
allWeapons[43]= WeaponBase {1,2500,30,5,2,120},//M4A1
allWeapons[45]= WeaponBase {1,10000,50,50,1,40},//AWP, 冷却回合5
allWeapons[4]= WeaponBase {2,200,20,10,10,1},//B04,手雷爆炸延迟回合3
allWeapons[2]= WeaponBase {3,1000,0,0,0,100},//护甲
allWeapons[81]= WeaponBase {4,0,0,0,0,1};//C4
*/
class ObjectRepo {
public:
ObjectRepo() {}
virtual ~ObjectRepo() {
for (auto &enemy : this->enemies) {
delete enemy.second;
}
for (auto &teammate : this->teammates) {
delete teammate.second;
}
for (auto &bomb : this->bombs) {
delete bomb.second;
}
for (auto &dropEquipment : this->dropEquipments) {
delete dropEquipment.second;
}
}
int Inquire(cJSON *obj);
int Start(cJSON *obj);
private:
int UpdateObjects(cJSON *objects);
class Object* GetObj(int objectId, int roleId, int camp);
void Dump();
public:
std::map<int, class Object*> enemies;
std::map<int, class Object*> teammates;
std::map<int, class Object*> bombs;
std::map<int, class Object*> dropEquipments;
class Object plantC4;
int round;
bool c4Planted;
int gold;
int selfCamp;
};
输出:
struct G_ACTION{
map<int, Position> ad;//每个人攻击哪,不攻击的不填
map<int, Position> move;//每个人移动到哪,不移动的不填
map<int, Position> throws;
map<int, vector<int>> buy;
map<int,int>switchs;
int plantid;
int defuseid;
vector<int>buy_bullets;
vector<int>pick;
};
2,完成消息解析
1个是请求消息转成输入结构体,1个是输出结构体转成返回消息
3,核心代码
核心代码就是策略算法,主要分2部分,1个是移动策略,1个是其他命令策略。