c语言RPG小游戏二次开发
原代码如下(代码来源于网络)
点击查看代码
include
include
include
// Character base class
class Character {
protected:
std::string name;
int hp;
int maxHp;
int atk;
int def;
std::string className;
public:
Character(std::string name, int hp, int atk, int def, std::string className)
: name(name), hp(hp), maxHp(hp), atk(atk), def(def), className(className) {}
virtual void attack(Character& target) = 0; // Pure virtual function
virtual void specialAbility(Character& target) = 0; // Special skill
void takeDamage(int damage) {
int actualDamage = damage - def;
if (actualDamage < 0) actualDamage = 0;
hp -= actualDamage;
if (hp < 0) hp = 0;
std::cout << name << " takes " << actualDamage << " damage!\n";
}
bool isAlive() const {
return hp > 0;
}
void displayStatus() const {
std::cout << name << " (" << className << ") | HP: " << hp << "/" << maxHp << "\n";
}
std::string getName() const {
return name;
}
int getAtk() const {
return atk;
}
std::string getClassName() const {
return className;
}
};
// Player class
class Player : public Character {
public:
Player(std::string name, int hp, int atk, int def, std::string className)
: Character(name, hp, atk, def, className) {}
void attack(Character& target) override {
std::cout << name << " attacks " << target.getName() << "!\n";
target.takeDamage(atk);
}
void specialAbility(Character& target) override {
if (className == "Warrior") {
std::cout << name << " uses skill: Power Strike!\n";
target.takeDamage(atk * 2);
} else if (className == "Mage") {
std::cout << name << " casts Fireball!\n";
target.takeDamage(atk + 10);
} else if (className == "Rogue") {
std::cout << name << " uses skill: Dodge!\n";
std::cout << name << " evades the next attack!\n";
}
}
};
// Monster class
class Monster : public Character {
public:
Monster(std::string name, int hp, int atk, int def)
: Character(name, hp, atk, def, "Monster") {}
void attack(Character& target) override {
std::cout << name << " attacks " << target.getName() << "!\n";
target.takeDamage(atk);
}
void specialAbility(Character& target) override {
std::cout << name << " uses skill: Frenzy!\n";
target.takeDamage(atk + 5);
}
};
// Game logic
void startGame() {
std::string playerName;
std::string className;
int choice;
std::cout << "Welcome to the RPG Battle Game!\n";
std::cout << "Enter your character name: ";
std::cin >> playerName;
std::cout << "Choose your class:\n";
std::cout << "1. Warrior | 2. Mage | 3. Rogue\n";
std::cin >> choice;
Player* player = nullptr;
switch (choice) {
case 1:
player = new Player(playerName, 100, 15, 10, "Warrior");
break;
case 2:
player = new Player(playerName, 80, 20, 5, "Mage");
break;
case 3:
player = new Player(playerName, 90, 12, 8, "Rogue");
break;
default:
std::cout << "Invalid choice. Defaulting to Warrior.\n";
player = new Player(playerName, 100, 15, 10, "Warrior");
break;
}
std::cout << "You've chosen: " << player->getName() << " (" << player->getClassName() << ")\n";
// Create monster
Monster monster("Evil Troll", 120, 12, 8);
std::cout << "A wild " << monster.getName() << " appears!\n";
// Battle loop
while (player->isAlive() && monster.isAlive()) {
std::cout << "\n===== BATTLE START =====\n";
player->displayStatus();
monster.displayStatus();
std::cout << "Choose action:\n";
std::cout << "1. Normal Attack | 2. Use Skill\n";
std::cin >> choice;
if (choice == 1) {
player->attack(monster);
} else if (choice == 2) {
player->specialAbility(monster);
} else {
std::cout << "Invalid choice. Skipping turn.\n";
}
if (monster.isAlive()) {
monster.attack(*player);
}
}
// Battle result
if (player->isAlive()) {
std::cout << "\nCongratulations! You have defeated " << monster.getName() << "!\n";
} else {
std::cout << "\nYou were defeated by " << monster.getName() << "...\n";
}
delete player;
}
int main() {
std::srand(std::time(0));
startGame();
return 0;
}
原代码缺陷分析
内存管理问题
使用原始指针new Player但未使用智能指针,存在内存泄漏风险
盗贼技能未实现实际效果
盗贼的Dodge技能仅输出文本,未实际影响战斗逻辑
输入验证缺失
未处理非数字输入或无效选项(如输入字母导致程序崩溃)
怪物行动单一
怪物只会普通攻击,未使用specialAbilit
防御计算不合理
当damage <= def时实际伤害为0,可能导致战斗无限循环
职业逻辑耦合
通过字符串比较className判断职业类型,违反开闭原则
数值平衡问题
战士的Power Strike(30伤害)可两回合击杀怪物(120HP),战斗节奏过快
笔者的改进
内存管理
使用std::unique_ptr自动管理内存
移除手动delete
盗贼技能实现
添加dodging状态标记
在takeDamage()中检查闪避状态
输入验证
添加clearInputBuffer()处理无效输入
使用循环强制有效输入
怪物AI改进
30%概率使用Frenzy技能
调整怪物数值(150HP, 18ATK)
防御计算优化
std::max(1, damage - def)保证最小伤害
多态实现职业
分离Warrior/Mage/Rogue为独立子类
移除字符串比较逻辑
数值平衡调整
战士:100HP/15ATK/10DEF
法师:80HP/20ATK/5DEF
盗贼:90HP/12ATK/8DEF
怪物:150HP/18ATK/8DEF
修改后的代码
点击查看代码
include
include
include
include
include
// Character base class
class Character {
protected:
std::string name;
int hp;
int maxHp;
int atk;
int def;
bool dodging = false; // 新增闪避状态
public:
Character(std::string name, int hp, int atk, int def)
: name(name), hp(hp), maxHp(hp), atk(atk), def(def) {}
virtual void attack(Character& target) = 0;
virtual void specialAbility(Character& target) = 0;
void takeDamage(int damage) {
if (dodging) {
std::cout << name << " dodged the attack!\n";
dodging = false;
return;
}
int actualDamage = std::max(1, damage - def); // 至少1点伤害
hp -= actualDamage;
if (hp < 0) hp = 0;
std::cout << name << " takes " << actualDamage << " damage!\n";
}
void setDodge(bool status) { dodging = status; }
bool isAlive() const { return hp > 0; }
virtual void displayStatus() const {
std::cout << name << " | HP: " << hp << "/" << maxHp
<< " | ATK: " << atk << " | DEF: " << def << "\n";
}
std::string getName() const { return name; }
};
//-------------------
// 职业类分层实现多态
//-------------------
class Warrior : public Character {
public:
Warrior(std::string name)
: Character(name, 100, 15, 10) {}
void attack(Character& target) override {
std::cout << name << " slashes " << target.getName() << "!\n";
target.takeDamage(atk);
}
void specialAbility(Character& target) override {
std::cout << name << " uses Power Strike!\n";
target.takeDamage(atk * 2);
}
void displayStatus() const override {
std::cout << "[Warrior] ";
Character::displayStatus();
}
};
class Mage : public Character {
public:
Mage(std::string name)
: Character(name, 80, 20, 5) {}
void attack(Character& target) override {
std::cout << name << " casts magic missile at " << target.getName() << "!\n";
target.takeDamage(atk);
}
void specialAbility(Character& target) override {
std::cout << name << " casts Fireball!\n";
target.takeDamage(atk + 15);
}
void displayStatus() const override {
std::cout << "[Mage] ";
Character::displayStatus();
}
};
class Rogue : public Character {
public:
Rogue(std::string name)
: Character(name, 90, 12, 8) {}
void attack(Character& target) override {
std::cout << name << " stabs " << target.getName() << "!\n";
target.takeDamage(atk);
}
void specialAbility(Character& target) override {
std::cout << name << " uses Dodge!\n";
setDodge(true);
}
void displayStatus() const override {
std::cout << "[Rogue] ";
Character::displayStatus();
}
};
//-------------------
// 怪物类
//-------------------
class Monster : public Character {
public:
Monster(std::string name)
: Character(name, 150, 18, 8) {} // 调整数值
void attack(Character& target) override {
if (rand() % 100 < 30) { // 30%概率使用技能
specialAbility(target);
} else {
std::cout << name << " claws " << target.getName() << "!\n";
target.takeDamage(atk);
}
}
void specialAbility(Character& target) override {
std::cout << name << " uses Frenzy!\n";
target.takeDamage(atk + 8);
}
void displayStatus() const override {
std::cout << "[Monster] ";
Character::displayStatus();
}
};
//-------------------
// 游戏逻辑
//-------------------
void clearInputBuffer() {
std::cin.clear();
std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n');
}
std::unique_ptr
std::string name;
std::cout << "Enter your name: ";
std::getline(std::cin, name);
while (true) {
std::cout << "Choose class:\n"
<< "1. Warrior\n2. Mage\n3. Rogue\n";
int choice;
std::cin >> choice;
clearInputBuffer();
switch (choice) {
case 1: return std::make_unique<Warrior>(name);
case 2: return std::make_unique<Mage>(name);
case 3: return std::make_unique<Rogue>(name);
default:
std::cout << "Invalid input. Please enter 1-3.\n";
break;
}
}
}
void battleLoop(Character& player, Character& monster) {
while (player.isAlive() && monster.isAlive()) {
std::cout << "\n===== BATTLE =====" << std::endl;
player.displayStatus();
monster.displayStatus();
int choice;
while (true) {
std::cout << "Choose action:\n1. Attack\n2. Skill\n";
if (std::cin >> choice && (choice == 1 || choice == 2)) break;
clearInputBuffer();
std::cout << "Invalid choice! Enter 1 or 2.\n";
}
if (choice == 1) player.attack(monster);
else player.specialAbility(monster);
if (monster.isAlive()) monster.attack(player);
}
}
int main() {
srand(time(0));
auto player = createPlayer();
Monster monster("Giant Troll");
std::cout << "\nA wild " << monster.getName() << " appears!\n";
battleLoop(*player, monster);
if (player->isAlive()) {
std::cout << "\nVictory! " << monster.getName() << " was defeated!\n";
} else {
std::cout << "\nDefeat! " << player->getName() << " was slain...\n";
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】