Giao diện
🎮 RPG Character Project
Áp dụng mọi kiến thức OOP vào một project thực tế: Xây dựng class RPG Character với Health, Mana, và Attack methods.
Yêu cầu Project
Xây dựng class Character với:
| Attribute | Description |
|---|---|
name_ | Tên nhân vật |
health_ | HP (0-maxHealth) |
maxHealth_ | HP tối đa |
mana_ | MP (0-maxMana) |
maxMana_ | MP tối đa |
attackPower_ | Sức tấn công |
level_ | Cấp độ |
| Method | Description |
|---|---|
attack(Character&) | Tấn công enemy |
heal(int) | Hồi HP |
castSpell(Character&) | Dùng mana tấn công |
takeDamage(int) | Nhận damage |
isAlive() | Check còn sống? |
levelUp() | Tăng cấp |
displayStats() | In stats |
Bước 1: Class Definition
cpp
#ifndef CHARACTER_HPP
#define CHARACTER_HPP
#include <string>
#include <iostream>
#include <algorithm> // std::max, std::min
class Character {
private:
// === Member Variables ===
std::string name_;
int health_;
int maxHealth_;
int mana_;
int maxMana_;
int attackPower_;
int level_;
public:
// === Constructor ===
Character(const std::string& name,
int maxHealth = 100,
int maxMana = 50,
int attackPower = 10)
: name_(name),
health_(maxHealth), // Start at full health
maxHealth_(maxHealth),
mana_(maxMana), // Start at full mana
maxMana_(maxMana),
attackPower_(attackPower),
level_(1) {}
// === Getters (const methods) ===
std::string getName() const { return name_; }
int getHealth() const { return health_; }
int getMaxHealth() const { return maxHealth_; }
int getMana() const { return mana_; }
int getMaxMana() const { return maxMana_; }
int getAttackPower() const { return attackPower_; }
int getLevel() const { return level_; }
bool isAlive() const { return health_ > 0; }
// === Combat Methods ===
void takeDamage(int damage);
void heal(int amount);
void attack(Character& target);
bool castSpell(Character& target, int manaCost, int spellPower);
// === Progression ===
void levelUp();
// === Display ===
void displayStats() const;
};
#endifBước 2: Method Implementations
cpp
// character.cpp
#include "character.hpp"
void Character::takeDamage(int damage) {
if (damage < 0) return; // Ignore negative damage
health_ = std::max(0, health_ - damage);
std::cout << name_ << " takes " << damage << " damage! ";
std::cout << "HP: " << health_ << "/" << maxHealth_ << std::endl;
if (!isAlive()) {
std::cout << "💀 " << name_ << " has been defeated!" << std::endl;
}
}
void Character::heal(int amount) {
if (amount < 0 || !isAlive()) return;
int oldHealth = health_;
health_ = std::min(maxHealth_, health_ + amount);
int actualHeal = health_ - oldHealth;
std::cout << name_ << " heals for " << actualHeal << " HP! ";
std::cout << "HP: " << health_ << "/" << maxHealth_ << std::endl;
}
void Character::attack(Character& target) {
if (!isAlive()) {
std::cout << name_ << " cannot attack (defeated)" << std::endl;
return;
}
if (!target.isAlive()) {
std::cout << target.getName() << " is already defeated!" << std::endl;
return;
}
std::cout << "⚔️ " << name_ << " attacks " << target.getName() << "!" << std::endl;
target.takeDamage(attackPower_);
}
bool Character::castSpell(Character& target, int manaCost, int spellPower) {
if (!isAlive()) {
std::cout << name_ << " cannot cast spell (defeated)" << std::endl;
return false;
}
if (mana_ < manaCost) {
std::cout << name_ << " doesn't have enough mana! ";
std::cout << "(" << mana_ << "/" << manaCost << " required)" << std::endl;
return false;
}
mana_ -= manaCost;
std::cout << "✨ " << name_ << " casts a spell on " << target.getName() << "!" << std::endl;
std::cout << " Mana: " << mana_ << "/" << maxMana_ << std::endl;
target.takeDamage(spellPower);
return true;
}
void Character::levelUp() {
++level_;
// Tăng stats khi level up
int healthBonus = 20;
int manaBonus = 10;
int attackBonus = 5;
maxHealth_ += healthBonus;
health_ = maxHealth_; // Full heal on level up
maxMana_ += manaBonus;
mana_ = maxMana_; // Full mana restore
attackPower_ += attackBonus;
std::cout << "🎉 " << name_ << " leveled up to Level " << level_ << "!" << std::endl;
std::cout << " Max HP +" << healthBonus << " → " << maxHealth_ << std::endl;
std::cout << " Max MP +" << manaBonus << " → " << maxMana_ << std::endl;
std::cout << " Attack +" << attackBonus << " → " << attackPower_ << std::endl;
}
void Character::displayStats() const {
std::cout << "╔════════════════════════════════╗" << std::endl;
std::cout << "║ " << name_;
// Padding
for (size_t i = name_.length(); i < 24; ++i) std::cout << " ";
std::cout << "Lv." << level_ << " ║" << std::endl;
std::cout << "╠════════════════════════════════╣" << std::endl;
std::cout << "║ HP: " << health_ << "/" << maxHealth_;
std::cout << " MP: " << mana_ << "/" << maxMana_;
std::cout << " ║" << std::endl;
std::cout << "║ Attack Power: " << attackPower_;
std::cout << " ║" << std::endl;
std::cout << "║ Status: " << (isAlive() ? "✅ Alive" : "💀 Dead");
std::cout << " ║" << std::endl;
std::cout << "╚════════════════════════════════╝" << std::endl;
}Bước 3: Main Program — Game Simulation
cpp
// main.cpp
#include "character.hpp"
#include <iostream>
int main() {
std::cout << "=== RPG Character Demo ===" << std::endl << std::endl;
// Tạo characters
Character hero("Aragorn", 120, 60, 15);
Character enemy("Goblin", 80, 20, 8);
// Display initial stats
std::cout << ">>> Initial Stats <<<" << std::endl;
hero.displayStats();
enemy.displayStats();
std::cout << std::endl << ">>> Battle Begins! <<<" << std::endl << std::endl;
// Combat simulation
hero.attack(enemy); // Basic attack
enemy.attack(hero); // Enemy attacks back
hero.castSpell(enemy, 20, 25); // Spell attack (cost 20 mana, 25 damage)
hero.castSpell(enemy, 20, 25); // Another spell
enemy.attack(hero);
hero.heal(30); // Hero heals
hero.attack(enemy); // Finish enemy
hero.attack(enemy); // Already dead check
std::cout << std::endl << ">>> Battle Results <<<" << std::endl;
hero.displayStats();
enemy.displayStats();
// Level up
std::cout << std::endl << ">>> Victory Rewards <<<" << std::endl;
hero.levelUp();
hero.displayStats();
return 0;
}Sample Output
=== RPG Character Demo ===
>>> Initial Stats <<<
╔════════════════════════════════╗
║ Aragorn Lv.1 ║
╠════════════════════════════════╣
║ HP: 120/120 MP: 60/60 ║
║ Attack Power: 15 ║
║ Status: ✅ Alive ║
╚════════════════════════════════╝
╔════════════════════════════════╗
║ Goblin Lv.1 ║
╠════════════════════════════════╣
║ HP: 80/80 MP: 20/20 ║
║ Attack Power: 8 ║
║ Status: ✅ Alive ║
╚════════════════════════════════╝
>>> Battle Begins! <<<
⚔️ Aragorn attacks Goblin!
Goblin takes 15 damage! HP: 65/80
⚔️ Goblin attacks Aragorn!
Aragorn takes 8 damage! HP: 112/120
✨ Aragorn casts a spell on Goblin!
Mana: 40/60
Goblin takes 25 damage! HP: 40/80
✨ Aragorn casts a spell on Goblin!
Mana: 20/60
Goblin takes 25 damage! HP: 15/80
⚔️ Goblin attacks Aragorn!
Aragorn takes 8 damage! HP: 104/120
Aragorn heals for 16 HP! HP: 120/120
⚔️ Aragorn attacks Goblin!
Goblin takes 15 damage! HP: 0/80
💀 Goblin has been defeated!
Goblin is already defeated!
>>> Battle Results <<<
...
>>> Victory Rewards <<<
🎉 Aragorn leveled up to Level 2!
Max HP +20 → 140
Max MP +10 → 70
Attack +5 → 20
...Mở rộng (Bài tập về nhà)
💡 Thử thách 1: Thêm Equipment System
cpp
class Weapon {
private:
std::string name_;
int bonusDamage_;
public:
Weapon(const std::string& name, int damage)
: name_(name), bonusDamage_(damage) {}
int getDamage() const { return bonusDamage_; }
};
class Character {
private:
Weapon* equippedWeapon_ = nullptr; // Optional weapon
public:
void equip(Weapon* weapon) { equippedWeapon_ = weapon; }
int getTotalAttack() const {
return attackPower_ + (equippedWeapon_ ? equippedWeapon_->getDamage() : 0);
}
};💡 Thử thách 2: Thêm Character Types (Warrior, Mage)
cpp
enum class CharacterClass { Warrior, Mage, Rogue };
class Character {
private:
CharacterClass charClass_;
public:
Character(const std::string& name, CharacterClass cls)
: name_(name), charClass_(cls) {
switch (cls) {
case CharacterClass::Warrior:
maxHealth_ = 150; attackPower_ = 20; maxMana_ = 30;
break;
case CharacterClass::Mage:
maxHealth_ = 80; attackPower_ = 8; maxMana_ = 100;
break;
case CharacterClass::Rogue:
maxHealth_ = 100; attackPower_ = 15; maxMana_ = 50;
break;
}
health_ = maxHealth_;
mana_ = maxMana_;
}
};💡 Thử thách 3: Save/Load System
cpp
#include <fstream>
class Character {
public:
void saveToFile(const std::string& filename) const {
std::ofstream file(filename);
file << name_ << "\n"
<< level_ << "\n"
<< health_ << " " << maxHealth_ << "\n"
<< mana_ << " " << maxMana_ << "\n"
<< attackPower_;
}
static Character loadFromFile(const std::string& filename) {
std::ifstream file(filename);
std::string name;
int level, hp, maxHp, mp, maxMp, atk;
file >> name >> level >> hp >> maxHp >> mp >> maxMp >> atk;
// ... construct character from data
}
};📚 Tổng kết
Trong project này, chúng ta đã áp dụng:
| Concept | Application |
|---|---|
| Encapsulation | Private members, public interface |
| Data Hiding | Stats ẩn, chỉ access qua methods |
| Constructors | Init với default parameters |
| Member init list | Efficient initialization |
| const methods | getters, displayStats |
| this pointer | (implicit trong các methods) |
| Validation | Kiểm tra bounds cho HP/MP |
🎉 Hoàn thành Module 2: Part 1!
Bạn đã nắm vững:
- ✅ Tại sao OOP
- ✅ Class Anatomy
- ✅ Access Modifiers
- ✅ this Pointer
- ✅ Member Initialization
- ✅ Practical Project