#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <limits>
#include <stdexcept>
#include <cctype>
#include <cmath>
#include <Windows.h>
#include <fstream>
#include <conio.h>
// 文字颜色
void SetColor(int textColor, int bgColor) {
WORD color = (bgColor << 4) + textColor;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
void ShowCombatText(const stdstring& text, int color)
{
SetColor(color, 0);
stdcout << text;
SetColor(7, 0);
}
// 游戏状态枚举
enum class GameState {
MAIN_MENU, EXPLORING, COMBAT, GAME_OVER, VICTORY, EVACUATION, SHOP
};
//难度选择
enum class Difficulty
{
NORMAL, //常规:难度低,爆率低
SECRET, //机密:一般难度,中等爆率
TOP_SECRET //绝密:高难度,高爆率
};
//全局当前难度
Difficulty current_difficulty = Difficulty::NORMAL;
//地区枚举 8个区域
enum class AreaId
{
CORE, //核心区(唯一有撤离点)
NUCLEAR_PLANT, //核电站
ADMIN_BUILD, //行政楼
MEDICAL_CENTER, //医疗中心
MILITARY_CAMP, //军营
RESIDENTIAL, //居民区
INDUSTRIAL, //工业区
HARBOUR //港口
};
// 物品类型枚举
enum class ItemType {
CONSUMABLE, WEAPON, ARMOR_HEAD, ARMOR_BODY, BACKPACK, COLLECTIBLE, AMMO
};
// 武器/弹药类型枚举
enum class WeaponType {
KNIFE, PISTOL, RIFLE, SPECIAL
};
enum class AmmoType {
PISTOL, RIFLE, SPECIAL
};
// 容器类型枚举
enum class ContainerType {
SAFE, SMALL_SAFE, WEAPON_BOX, PARCEL, SUITCASE, STORAGE_BOX, CLOTHING, MANHOLE, SCATTERED, MEDICAL_BOX,
STORAGE_BOX_S
};
// 基础物品结构体
struct Item {
stdstring name;
stdstring description;
ItemType type;
int value;
int size;
Item(const stdstring& n, const stdstring& desc, ItemType t, int v = 0, int s = 1)
: name(n), description(desc), type(t), value(v), size(s) {}
virtual ~Item() {}
};
// 消耗品
struct Consumable : Item {
int health_restore;
int status_effect; // 扩展:状态效果(0=无,1=临时防御,2=临时暴击)
Consumable(const stdstring& n, const stdstring& desc, int hr, int se = 0, int v = 0, int s = 1)
: Item(n, desc, ItemTypeCONSUMABLE, v, s), health_restore(hr), status_effect(se) {}
};
// 弹药
struct Ammo : Item {
AmmoType ammo_type;
int quantity;
Ammo(const stdstring& n, const stdstring& desc, AmmoType at, int qty, int v = 0, int s = 1)
: Item(n, desc, ItemTypeAMMO, v, s), ammo_type(at), quantity(qty) {}
};
// 武器
struct Weapon : Item {
int damage;
int crit_rate;
int hit_rate; //新增:武器命中率 0~100
WeaponType weapon_type;
AmmoType ammo_type;
int current_ammo;
int max_ammo;
};
// 头部防具
struct HeadArmor : Item {
int defense;
int dodge_rate;
int damage_reduction;
HeadArmor(const stdstring& n, const stdstring& desc, int def, int dr, int dmg_red = 0,
int v = 0, int s = 2)
: Item(n, desc, ItemType::ARMOR_HEAD, v, s),
defense(def), dodge_rate(dr), damage_reduction(dmg_red) {}
};
// 身体防具
struct BodyArmor : Item {
int defense;
int dodge_rate;
int damage_reduction;
BodyArmor(const stdstring& n, const stdstring& desc, int def, int dr, int dmg_red = 0,
int v = 0, int s = 3)
: Item(n, desc, ItemType::ARMOR_BODY, v, s),
defense(def), dodge_rate(dr), damage_reduction(dmg_red) {}
};
// 背包
struct Backpack : Item {
int capacity;
Backpack(const stdstring& n, const stdstring& desc, int cap, int v = 0, int s = 5)
: Item(n, desc, ItemType::BACKPACK, v, s), capacity(cap) {}
};
// 容器
struct Container {
ContainerType type;
stdstring name;
stdvector<Item*> contents; // 初始物品
std::vector<Item*> uncollected_items; // 未拾取的物品
bool is_opened; // 是否已打开(但可能还有未拾取物品)
bool safe_unlocked; //新增:大保险箱是否已经解开摩斯密码
};
//区域配置:名字、描述、本区域最大本地步数、相邻地区、容器权重、精英敌人倍率
struct AreaConfig
{
AreaId id;
stdstring name;
stdstring desc;
int max_local_step; //在本区域最多走多少步,之后必须切换相邻地区
std::vector<AreaId> neighbor; //相邻可前往的地区
};
// 敌人
struct Enemy {
stdstring name;
int health;
int max_health;
int damage;
int defense;
int exp_reward;
int money_reward;
stdvector<Item*> equipment;
stdvector<Item*> drop_items;
stdvector<Item*> rare_drops;
bool is_strong;
}
};
// 友军
struct BotPlayer {
std::string name;
int health;
int max_health;
int damage;
int alive_chance;
bool is_alive;
};
void auto_equip_if_slot_empty(Item* item);
// 玩家
struct Player {
stdstring name;
int health;
int max_health;
Weapon* main_weapon;
Weapon* secondary_weapon;
Weapon* pistol_weapon;
Weapon* knife_weapon;
HeadArmor* equipped_head;
BodyArmor* equipped_body;
Backpack* equipped_backpack;
stdvector<Item*> inventory;
std::vector<Item*> temp_cache;
const int CACHE_MAX_SLOT = 10;
int current_load;
int level;
int exp;
int money;
int kill_count;
int collectibles_value;
bool reached_evac;
int temp_defense; // 临时防御加成
int temp_crit; // 临时暴击加成
};
struct RedVault
{
std::vector<Item*> stored_red_collectibles;
long long bank_money;
long long total_kills;
bool unlock_blood_blade;
bool unlock_bi_xiao;
};
RedVault red_vault;
const stdstring VAULT_FILE = "red_vault.bin";
// 全局变量
bool player_last_attack_melee = false;
GameState current_state;
AreaId current_area; // 当前所在地区
int global_step = 0; //全局总步数(商店触发使用)
int local_step = 0; //当前区域本地步数
Player player("默认士兵");
stdvector<BotPlayer> bots; // 人机玩家列表
Enemy* current_enemy = nullptr;
stdvector<Item*> loot_items; // 战利品列表
Container* current_container = nullptr;
int explore_steps = 0; // 探索步数,用于触发撤离点和商店
stdvector<Item*> shop_items; // 商店商品
stdvector<Item*> lobby_starting_gifts;
bool in_hidden_mission_combat = false; // 萨萨隐藏任务战斗:禁止逃跑
//全局区域表
stdvector<AreaConfig> area_table = {
{
AreaIdCORE, "核心区", "任务核心区域,高概率出现撤离点",
35,
{AreaIdNUCLEAR_PLANT, AreaIdADMIN_BUILD, AreaIdRESIDENTIAL},
80,60,100,80,120,110,100,90,80,100,80,
1.0f
},
{
AreaIdNUCLEAR_PLANT,"核电站","辐射笼罩,高价值物资多,精英敌人频繁",
28,
{AreaIdCORE,AreaIdINDUSTRIAL},
150,120,80,50,60,50,90,30,120,100,150,
1.8f
},
{
AreaIdADMIN_BUILD,"行政楼","大量保险柜,文件与贵重物品",
32,
{AreaIdCORE,AreaIdMEDICAL_CENTER},
180,160,70,60,100,120,110,40,40,80,40,
1.2f
},
{
AreaIdMEDICAL_CENTER,"医疗中心","大量医疗物资,精英敌人较少",
30,
{AreaIdADMIN_BUILD,AreaIdRESIDENTIAL},
40,30,50,300,100,90,80,70,60,120,60,
0.7f
},
{
AreaIdMILITARY_CAMP,"军营","武器补给箱极多,危险,大量精英",
26,
{AreaIdINDUSTRIAL,AreaIdHARBOUR},
50,40,280,40,60,40,70,30,50,80,100,
2.0f
},
{
AreaIdRESIDENTIAL,"居民区","居民私人物品,包裹旅行箱多,相对安全",
40,
{AreaIdCORE,AreaIdMEDICAL_CENTER,AreaIdHARBOUR},
40,50,40,100,180,170,120,140,80,100,80,
0.6f
},
{
AreaIdINDUSTRIAL,"工业区","废弃工厂,井盖散落物多",
33,
{AreaIdNUCLEAR_PLANT,AreaIdMILITARY_CAMP},
60,50,130,40,80,70,110,50,160,150,100,
1.4f
},
{
AreaIdHARBOUR,"港口","大量集装箱,高级储物箱、包裹",
36,
{AreaIdMILITARY_CAMP,AreaIdRESIDENTIAL},
90,70,110,60,160,130,120,60,70,90,170,
1.1f
}
};
// 函数声明
void lobby_select_melee(); //大厅选择开局近战武器
void cleanup_game_session();
bool meet_sasa_event = false;
void lobby_shop();
void event_explorer_sasa();
void game_loop();
void show_main_menu();
void handle_main_menu_input();
void start_game();
void explore();
void handle_explore_input();
void encounter_enemy();
void generate_enemy();
void combat();
void handle_combat_input();
bool attempt_escape();
void game_over(bool victory);
void clear_screen();
void press_any_key();
void manage_inventory();
void loot_corpse();
void show_stats();
void generate_container();
void open_container();
void create_collectibles(std::vector<Item*>& items, int count, ContainerType container_type);
void evacuation_point();
void reset_bots();
void show_shop();
void handle_shop_input();
void generate_shop_items();
void enemy_attack();
void enemy_defeated();
void string_input_to_digit(int& choice);
long long get_red_vault_total_value(); //新增
bool safe_morse_unlock();
void event_sasa_hidden_mission();
std::string morse_encode(int num)
{
switch(num)
{
case 0: return "-----";
case 1: return ".----";
case 2: return "..---";
case 3: return "...--";
case 4: return "....-";
case 5: return ".....";
case 6: return "-....";
case 7: return "--...";
case 8: return "---..";
case 9: return "----.";
default: return "";
}
}
// 大保险箱数字密码解锁交互;返回true=解锁成功,false=放弃打开保险箱
bool safe_morse_unlock(){
// 生成4位随机密码数字
int pass[5];
for(int i=0;i<4;i++){
pass[i] = rand()%10;
}
// 如果在此之前有使用 cin >> 操作,缓冲区会残留 '\n',这里一次性清除
stdcin.ignore(stdnumeric_limitsstd::streamsizemax(), '\n');
while(true) //无限重试,不会损坏箱子物品
{
clear_screen();
SetColor(14,0);
stdcout << "==================== 大保险箱密码锁 ====================\n";
SetColor(7,0);
stdcout << "保险箱的密码以摩斯密码形式展示,请解读摩斯码,输入4位数字密码\n";
stdcout << "--------------------------------------------------------\n";
stdcout << "【摩斯密码提示】\n";
stdcout << "0:----- 1:.---- 2:..--- 3:...-- 4:....-\n";
stdcout << "5:..... 6:-.... 7:--... 8:---.. 9:----.\n";
stdcout << "--------------------------------------------------------\n";
stdcout << "保险箱摩斯密码:";
for(int i=0;i<4;i++)
{
stdcout << morse_encode(pass[i]) << " ";
}
stdcout << "\n\n";
stdcout << "说明:输入4个数字,中间用空格隔开。\n";
stdcout << "示例输入:1 2 3 4\n";
stdcout << "输入 q 可以放弃解锁,关闭保险箱\n";
stdcout << "请输入密码:";
stdstring line;
// getline 会读取整行包括最后的换行符并丢弃它,缓冲区变空,下次循环直接等待新输入
stdgetline(stdcin, line);
//放弃解锁
if(line == "q" || line == "Q")
{
stdcout << "\n你放弃解锁保险箱。\n";
press_any_key();
return false;
}
//分割输入为4段
stdvectorstd::string parts;
stdstring cur="";
for(char ch : line)
{
if(ch == ' '){
if(!cur.empty()){
parts.push_back(cur);
cur.clear();
}
}else{
cur.push_back(ch);
}
}
if(!cur.empty()) parts.push_back(cur);
if(parts.size() !=4 )
{
SetColor(12,0);
stdcout << "\n格式错误!必须输入4位数字!\n";
SetColor(7,0);
press_any_key();
continue;
}
}
void lobby_select_melee()
{
clear_screen();
stdcout << "===== 选择下一局开局近战武器 =====\n";
stdcout << "当前选择:";
if(red_vault.starter_melee_choice == -1)
{
stdcout << "【自动】根据仓库价值与解锁自动分配\n";
}
else if(red_vault.starter_melee_choice == 0) stdcout << "黑刃";
else if(red_vault.starter_melee_choice == 1) stdcout << "金刚";
else if(red_vault.starter_melee_choice == 2) stdcout << "裂空者";
else if(red_vault.starter_melee_choice == 3) stdcout << "灰海";
else if(red_vault.starter_melee_choice == 4) stdcout << "血痕【已解锁】";
else if(red_vault.starter_melee_choice == 5) stdcout << "碧霄【已解锁】";
stdcout << "\n\n";
}
// 新增:当对应装备槽为空时自动装备;槽位已有装备则不处理
void auto_equip_if_slot_empty(Item* item)
{
if (!item) return;
}
// 主游戏循环
void game_loop() {
player.level = 1000;
player.exp = 9999999;
player.money = 2000000000;
red_vault.bank_money = 900000000000000000LL;
while (current_state != GameStateGAME_OVER && current_state != GameStateVICTORY) {
clear_screen();
switch (current_state) {
case GameStateMAIN_MENU:
show_main_menu();
handle_main_menu_input();
break;
case GameStateEXPLORING:
explore();
handle_explore_input();
break;
case GameStateCOMBAT:
combat();
handle_combat_input();
break;
case GameStateEVACUATION:
evacuation_point();
break;
case GameStateSHOP:
show_shop();
handle_shop_input();
break;
default:
current_state = GameStateGAME_OVER;
break;
}
}
clear_screen();
show_stats(); // 显示统计信息
if (current_state == GameStateVICTORY) {
game_over(true);
} else {
game_over(false);
}
}
AreaConfig* get_area_config(AreaId aid)
{
for(auto &ac : area_table)
{
if(ac.id == aid) return ∾
}
return nullptr;
}
//当local_step >=本区域max_local_step,调用这个函数,选择前往相邻地区
void area_jump_menu()
{
clear_screen();
AreaConfig* cfg = get_area_config(current_area);
stdcout << "=本区域已经探索充分=\n";
std::cout << "当前位置:" << cfg->name << "|本地步数已达上限" << cfg->max_local_step << "\n\n";
}
// 主菜单
void show_main_menu() {
}
void lobby_shop()
{
clear_screen();
// 合并对局黑市全部商品池到大厅商店
std::vector<Item*> shop_pool = {
// =消耗品=
new Consumable("高级急救包", "恢复50点生命值", 50, 0, 50000, 2),
new Consumable("止痛药", "恢复20点生命值并获得临时防御", 20, 1, 10000, 1),
new Consumable("肾上腺素", "恢复10点生命值并获得临时暴击", 10, 2, 12000, 1),
new Consumable("绷带", "恢复15点生命值", 15, 0, 8000, 1),
new Consumable("医疗喷雾", "恢复40点生命值", 40, 0, 45000, 1),
}
Weapon* create_starter_melee_weapon();
void cleanup_game_session()
{
//释放当前敌人
delete current_enemy;
current_enemy = nullptr;
}
void string_input_to_digit(int& choice) {
for(;;)
{
stdstring input;
stdcout << "请输入你的选择: ";
stdcin.clear();
if (!(stdcin >> input))
{
stdcin.ignore(stdnumeric_limitsstd::streamsizemax(), '\n');
stdcout << "输入异常,请重试。\n";
system("pause");
continue;
}
}
// 根据红色仓库计算总价值
long long get_red_vault_total_value()
{
long long sum = 0;
for(auto item : red_vault.stored_red_collectibles)
{
sum += item->value;
}
return sum;
}
// 根据仓库总价值,获取开局近战武器
Weapon* create_starter_melee_weapon()
{
//玩家手动选择优先
int choice = red_vault.starter_melee_choice;
if(choice != -1)
{
switch(choice)
{
case 0:
return new Weapon("黑刃", "基础攻击武器,暴击率中等", 150000, 400000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL, 0, 30000);
case 1:
return new Weapon("金刚","钢制指虎,增加拳头杀伤,均衡伤害暴击",180000,500000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL,0,30000);
case 2:
return new Weapon("裂空者","锋利的弹簧折叠刀,极高暴击",220000,6500000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL,0,30000);
case 3:
return new Weapon("灰海","战术手斧,高伤害重型近战武器,破坏力惊人", 280000, 550000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL, 0, 30000);
case 4:
return new Weapon("血痕","浸染无数敌人鲜血的利刃,杀戮铸就的凶器", 240000, 600000, 100,
WeaponTypeKNIFE, AmmoTypeSPECIAL, 0, 30000);
case 5:
return new Weapon("碧霄","让颠覆开始吧!",280000,700000,100,
WeaponTypeKNIFE,AmmoTypeSPECIAL,0,30000);
default:
//异常,fallback走自动
break;
}
}
}