AI生成的恶魔轮盘(亲测可靠)
2026-09-27 15:43:18
发布于:广东
不废话,上代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
#include <iomanip>
#include <ctime>
using namespace std;
// 枚举定义
enum class BulletType { LIVE, BLANK };
enum class ItemType { CIGARETTE, HANDCUFFS, MAGNIFIER, KNIFE, BEER, NONE };
// 玩家结构体
struct Player {
string name;
int health;
int maxHealth;
vector<ItemType> inventory;
bool isHandcuffed; // 是否被手铐束缚,跳过回合
bool damageDoubled; // 下一发实弹伤害是否翻倍
Player(string n, int h) : name(n), health(h), maxHealth(h), isHandcuffed(false), damageDoubled(false) {}
};
// 游戏引擎类
class GameEngine {
private:
vector<BulletType> chamber;
int currentBulletIndex;
Player player;
Player dealer;
mt19937 rng;
// 辅助函数:打印分隔线
void printSeparator() {
cout << "\n========================================\n";
}
// 辅助函数:显示状态
void showStatus() {
printSeparator();
cout << "【当前状态】\n";
cout << left << setw(10) << player.name << ": HP " << player.health << "/" << player.maxHealth
<< " | 道具: " << getInventoryStr(player.inventory) << "\n";
cout << left << setw(10) << dealer.name << ": HP " << dealer.health << "/" << dealer.maxHealth
<< " | 道具: " << getInventoryStr(dealer.inventory) << "\n";
if (player.isHandcuffed) cout << "> " << player.name << " 被手铐束缚!\n";
if (dealer.isHandcuffed) cout << "> " << dealer.name << " 被手铐束缚!\n";
cout << "弹仓剩余子弹数: " << (chamber.size() - currentBulletIndex) << "\n";
if (player.damageDoubled) cout << "> " << player.name << " 的下一发实弹伤害翻倍!\n";
if (dealer.damageDoubled) cout << "> " << dealer.name << " 的下一发实弹伤害翻倍!\n";
printSeparator();
}
string getInventoryStr(const vector<ItemType>& inv) {
string res = "";
int counts[5] = {0}; // CIGARETTE, HANDCUFFS, MAGNIFIER, KNIFE, BEER
for (auto item : inv) {
if (item != ItemType::NONE) counts[(int)item]++;
}
if (counts[0]) res += "烟(" + to_string(counts[0]) + ") ";
if (counts[1]) res += "铐(" + to_string(counts[1]) + ") ";
if (counts[2]) res += "镜(" + to_string(counts[2]) + ") ";
if (counts[3]) res += "刀(" + to_string(counts[3]) + ") ";
if (counts[4]) res += "酒(" + to_string(counts[4]) + ") ";
return res.empty() ? "无" : res;
}
// 装填子弹
void loadChamber(int liveCount, int blankCount) {
chamber.clear();
chamber.insert(chamber.end(), liveCount, BulletType::LIVE);
chamber.insert(chamber.end(), blankCount, BulletType::BLANK);
shuffle(chamber.begin(), chamber.end(), rng);
currentBulletIndex = 0;
cout << "\n[系统] 装填了 " << liveCount << " 发实弹和 " << blankCount << " 发空弹。\n";
}
// 分发道具
void distributeItems() {
player.inventory.clear();
dealer.inventory.clear();
// 随机给玩家和庄家发道具,每种道具最多2个,总共随机发3-5个
vector<ItemType> allItems = {ItemType::CIGARETTE, ItemType::HANDCUFFS, ItemType::MAGNIFIER, ItemType::KNIFE, ItemType::BEER};
random_device rd;
mt19937 itemRng(rd());
uniform_int_distribution<int> itemCountDist(3, 5);
int totalItems = itemCountDist(itemRng);
for (int i = 0; i < totalItems; ++i) {
uniform_int_distribution<int> itemDist(0, 4);
ItemType item = allItems[itemDist(itemRng)];
// 简单平衡:每人每类道具不超过2个
int pCount = count(player.inventory.begin(), player.inventory.end(), item);
int dCount = count(dealer.inventory.begin(), dealer.inventory.end(), item);
if (pCount < 2 && dCount < 2) {
if (itemRng() % 2 == 0) {
player.inventory.push_back(item);
} else {
dealer.inventory.push_back(item);
}
} else if (pCount < 2) {
player.inventory.push_back(item);
} else if (dCount < 2) {
dealer.inventory.push_back(item);
}
}
cout << "[系统] 道具已分发。\n";
}
// 使用道具逻辑
bool useItem(Player& user, Player& target, ItemType item) {
auto it = find(user.inventory.begin(), user.inventory.end(), item);
if (it == user.inventory.end()) return false;
user.inventory.erase(it);
cout << "> " << user.name << " 使用了 ";
switch (item) {
case ItemType::CIGARETTE:
cout << "香烟";
if (user.health < user.maxHealth) {
user.health++;
cout << ",恢复了1点生命。";
} else {
cout << ",但生命值已满。";
}
break;
case ItemType::HANDCUFFS:
cout << "手铐";
if (!target.isHandcuffed) {
target.isHandcuffed = true;
cout << ",锁住了 " << target.name << ",其下一回合将被跳过。";
} else {
cout << ",但 " << target.name << " 已经被锁住了。";
// 归还道具或视为浪费,这里简单处理为浪费
}
break;
case ItemType::MAGNIFIER:
cout << "放大镜";
if (currentBulletIndex < chamber.size()) {
BulletType b = chamber[currentBulletIndex];
cout << ",查看了当前子弹:是 [" << (b == BulletType::LIVE ? "实弹" : "空弹") << "]。";
}
break;
case ItemType::KNIFE:
cout << "小刀";
user.damageDoubled = true;
cout << ",锯短了枪管,下一发实弹伤害翻倍。";
break;
case ItemType::BEER:
cout << "啤酒";
if (currentBulletIndex < chamber.size()) {
BulletType b = chamber[currentBulletIndex];
cout << ",退出了当前子弹:是 [" << (b == BulletType::LIVE ? "实弹" : "空弹") << "]。";
currentBulletIndex++;
}
break;
default:
break;
}
cout << "\n";
return true;
}
// 射击逻辑
void shoot(Player& shooter, Player& target, bool shootSelf) {
if (currentBulletIndex >= chamber.size()) {
cout << "[错误] 弹仓已空!\n";
return;
}
BulletType bullet = chamber[currentBulletIndex];
currentBulletIndex++;
Player& victim = shootSelf ? shooter : target;
string direction = shootSelf ? "自己" : target.name;
cout << "> " << shooter.name << " 向 " << direction << " 开枪... ";
if (bullet == BulletType::BLANK) {
cout << "咔哒!是空弹。无事发生。\n";
} else {
cout << "砰!是实弹!\n";
int damage = 1;
if (shooter.damageDoubled) {
damage = 2;
shooter.damageDoubled = false; // 消耗翻倍效果
cout << "! 由于小刀效果,造成双倍伤害!\n";
}
victim.health -= damage;
cout << victim.name << " 受到了 " << damage << " 点伤害。\n";
}
}
// 玩家回合
void playerTurn() {
showStatus();
if (player.isHandcuffed) {
cout << player.name << " 被手铐束缚,跳过本回合。\n";
player.isHandcuffed = false;
return;
}
while (true) {
cout << "\n请选择行动:\n";
cout << "1. 向自己开枪\n";
cout << "2. 向 " << dealer.name << " 开枪\n";
cout << "3. 使用道具\n";
cout << "输入选项 (1-3): ";
int choice;
cin >> choice;
if (choice == 1 || choice == 2) {
shoot(player, dealer, choice == 1);
break; // 射击后回合结束
} else if (choice == 3) {
if (player.inventory.empty()) {
cout << "没有道具可用。\n";
continue;
}
cout << "选择要使用的道具:\n";
cout << "1. 香烟 (恢复1HP)\n";
cout << "2. 手铐 (跳过对方回合)\n";
cout << "3. 放大镜 (查看当前子弹)\n";
cout << "4. 小刀 (下次实弹双倍伤害)\n";
cout << "5. 啤酒 (退出当前子弹)\n";
cout << "0. 返回\n";
int itemChoice;
cin >> itemChoice;
ItemType selected = ItemType::NONE;
if (itemChoice == 1) selected = ItemType::CIGARETTE;
else if (itemChoice == 2) selected = ItemType::HANDCUFFS;
else if (itemChoice == 3) selected = ItemType::MAGNIFIER;
else if (itemChoice == 4) selected = ItemType::KNIFE;
else if (itemChoice == 5) selected = ItemType::BEER;
if (selected != ItemType::NONE) {
if (!useItem(player, dealer, selected)) {
cout << "你没有这个道具。\n";
}
}
// 使用道具不结束回合,继续循环
} else {
cout << "无效输入。\n";
}
}
}
// AI回合
void dealerTurn() {
showStatus();
if (dealer.isHandcuffed) {
cout << dealer.name << " 被手铐束缚,跳过本回合。\n";
dealer.isHandcuffed = false;
return;
}
// 简单的AI逻辑
// 1. 如果血量低且有烟,用烟
if (dealer.health < dealer.maxHealth && useItemIfExists(dealer, player, ItemType::CIGARETTE)) return; // 注意:useItemIfExists内部会执行并返回true,但这里我们需要它执行后继续决策还是结束?通常道具使用后回合继续,除非是啤酒退弹可能想再射。简化:道具使用后,如果没死,继续决策直到射击。
// 修正AI逻辑:AI可以连续使用道具,最后必须射击
bool actionTaken = false;
// 尝试使用增益/信息道具
if (dealer.health < dealer.maxHealth) {
if (useItemIfExists(dealer, player, ItemType::CIGARETTE)) actionTaken = true;
}
// 如果有刀且没生效,用刀
if (!dealer.damageDoubled) {
if (useItemIfExists(dealer, player, ItemType::KNIFE)) actionTaken = true;
}
// 如果有镜子,用镜子看子弹
bool knownLive = false;
bool knownBlank = false;
if (useItemIfExists(dealer, player, ItemType::MAGNIFIER)) {
// 镜子使用后,我们知道当前子弹是什么
// 由于useItem内部打印了,我们需要知道结果来决策。
// 为了简化,我们假设AI“记得”刚才看到的。
// 在实际代码中,useItem只打印。我们需要修改useItem或者在这里重新检查。
// 更好的方式:AI直接访问chamber[currentBulletIndex]
if (currentBulletIndex < chamber.size()) {
if (chamber[currentBulletIndex] == BulletType::LIVE) knownLive = true;
else knownBlank = true;
}
actionTaken = true;
}
// 如果有手铐,且对方没被铐,且子弹未知或不利,可以考虑铐(简化:随机或总是用)
if (!player.isHandcuffed) {
if (useItemIfExists(dealer, player, ItemType::HANDCUFFS)) actionTaken = true;
}
// 如果有啤酒,且已知是空弹(用了也没用,不如留着?不,啤酒是退弹),或者未知想碰运气?
// 策略:如果已知是实弹,绝对不用啤酒打自己。如果已知空弹,打自己安全。
// 如果未知,AI可以根据概率。这里简化:如果已知空弹,不打啤酒,直接打自己。如果已知实弹,打对方。
// 决策射击
if (currentBulletIndex < chamber.size()) {
BulletType current = chamber[currentBulletIndex];
// 如果之前没用镜子,AI也可以猜,或者直接用啤酒赌一把?
// 简单策略:
// 1. 如果知道是空弹 -> 打自己 (安全,且如果规则允许连击则赚,这里规则是单发交换回合,打自己无伤但结束回合? 不,原游戏打自己空弹可以继续。本简化版:无论死活都换回合?
// 原题描述:俄罗斯轮盘。通常打自己空弹没事,回合继续?还是回合结束?
// 参考常见实现:打自己空弹,回合继续。打自己实弹,扣血,回合结束。打对方,无论虚实,回合结束。
// 让我们采用更刺激的规则:
// - 打对方:回合结束。
// - 打自己:
// - 实弹:扣血,回合结束。
// - 空弹:无事,**回合继续** (这是Buckshot Roulette的核心机制之一,给自己空弹可以获得额外行动机会)。
if (knownBlank) {
cout << "> " << dealer.name << " 知道是空弹,选择向自己开枪以获取额外回合。\n";
shoot(dealer, player, true);
// 如果是空弹,回合不结束,AI再次行动
if (dealer.health > 0 && player.health > 0) {
dealerTurn(); // 递归调用,模拟连续回合
return;
}
} else if (knownLive) {
cout << "> " << dealer.name << " 知道是实弹,选择向你开枪。\n";
shoot(dealer, player, false);
} else {
// 未知情况,简单概率或随机
// 如果血量健康,可能敢赌自己?或者保守打对方?
// 简单随机:50%打自己,50%打对方
if (rng() % 2 == 0) {
cout << "> " << dealer.name << " 猜测并向自己开枪。\n";
shoot(dealer, player, true);
// 如果空弹,继续
if (chamber[currentBulletIndex-1] == BulletType::BLANK && dealer.health > 0 && player.health > 0) {
dealerTurn();
return;
}
} else {
cout << "> " << dealer.name << " 选择向你开枪。\n";
shoot(dealer, player, false);
}
}
}
}
bool useItemIfExists(Player& user, Player& target, ItemType type) {
auto it = find(user.inventory.begin(), user.inventory.end(), type);
if (it != user.inventory.end()) {
useItem(user, target, type);
return true;
}
return false;
}
public:
GameEngine() : player("玩家", 4), dealer("恶魔", 4), rng(random_device{}()) {
cout << "欢迎来到《恶魔轮盘赌》C++复刻版!\n";
cout << "规则简介:\n";
cout << "- 实弹扣1血(小刀翻倍),空弹无事。\n";
cout << "- 向自己开枪若是空弹,可继续行动;若是实弹或向对方开枪,回合结束。\n";
cout << "- 先杀死对方者胜。\n";
}
void start() {
while (player.health > 0 && dealer.health > 0) {
// 新回合开始,如果弹仓空了,重新装填
if (currentBulletIndex >= chamber.size()) {
// 随机生成实弹和空弹数量,至少各1发,总数4-8
uniform_int_distribution<int> totalDist(4, 8);
int total = totalDist(rng);
uniform_int_distribution<int> liveDist(1, total - 1);
int live = liveDist(rng);
int blank = total - live;
loadChamber(live, blank);
distributeItems();
// 重置状态
player.isHandcuffed = false;
dealer.isHandcuffed = false;
player.damageDoubled = false;
dealer.damageDoubled = false;
cout << "\n--- 新一轮开始 ---\n";
}
// 玩家回合
if (player.health > 0 && dealer.health > 0) {
playerTurn();
}
// 检查游戏结束
if (player.health <= 0 || dealer.health <= 0) break;
// 庄家回合
if (player.health > 0 && dealer.health > 0) {
dealerTurn();
}
}
printSeparator();
if (player.health > 0) {
cout << "恭喜!你击败了恶魔!\n";
} else {
cout << "你被恶魔击败了... 游戏结束。\n";
}
}
};
int main() {
GameEngine game;
game.start();
return 0;
}
全部评论 3
1
1周前 来自 广东
01
1周前 来自 广东
01
1
1
1
11周前 来自 广东
0





















有帮助,赞一个