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;
}

**原代码运行情况** ![](https://img2024.cnblogs.com/blog/3606931/202502/3606931-20250225130721828-326712052.png)

原代码缺陷分析
内存管理问题

使用原始指针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 createPlayer() {
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;

}

代码运行测试 ![](https://img2024.cnblogs.com/blog/3606931/202502/3606931-20250225130049771-40029451.png) 改进后的代码能够加快游戏的进度,游戏体验更加流畅。
posted @   H哈ha  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示