六爻观测基础(卅六)——案例粗解(24)

这是王虎应书中一个案例,本图截取自哔哩哔哩up主[牛正六爻]的一个免费教学视频。

主卦卦身为申,没有上卦,为卦主问卦之时处于无婚姻状态之象【卦主自离婚后至求测没有再娶】。

虢婶代码辅助理解记忆。

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <cctype>

// 游戏常量定义
const int MAP_WIDTH = 18;    // 地图宽度
const int MAP_HEIGHT = 12;   // 地图高度
const int INIT_PLAYER_HP = 120;  // 玩家初始生命值
const int INIT_PLAYER_ATK = 25;  // 玩家初始攻击力
const int INIT_MONSTER_HP = 60;  // 怪物初始生命值
const int INIT_MONSTER_ATK = 12; // 怪物初始攻击力
const int ATTACK_RANGE = 2;      // 攻击范围(曼哈顿距离)
const int MONSTER_COUNT = 4;     // 初始怪物数量

// 角色类(玩家)
class Role {
private:
    std::string name;   // 角色名称
    int level;          // 等级
    int hp;             // 当前生命值
    int maxHp;          // 最大生命值
    int atk;            // 攻击力
    int x, y;           // 坐标(x:横向,y:纵向)

public:
    // 构造函数:初始化角色
    Role(const std::string& name, int x, int y)
        : name(name), level(1), hp(INIT_PLAYER_HP), maxHp(INIT_PLAYER_HP),
          atk(INIT_PLAYER_ATK), x(x), y(y) {}

    // 移动:dx=横向偏移(-1左/1右),dy=纵向偏移(-1上/1下)
    bool move(int dx, int dy, const class Map& map);
    // 攻击怪物
    void attack(class Monster& monster);
    // 受伤害
    void takeDamage(int damage);
    // 显示角色状态
    void showStatus() const;
    // 获取坐标
    int getX() const { return x; }
    int getY() const { return y; }
    // 检查是否存活
    bool isAlive() const { return hp > 0; }
    // 获取攻击力
    int getAtk() const { return atk; }
    std::string getName() const { return name; }
};

// 怪物类
class Monster {
private:
    std::string name;   // 怪物名称
    int hp;             // 当前生命值
    int maxHp;          // 最大生命值
    int atk;            // 攻击力
    int x, y;           // 坐标
    bool alive;         // 是否存活

public:
    // 构造函数:初始化怪物
    Monster(const std::string& name, int x, int y)
        : name(name), hp(INIT_MONSTER_HP), maxHp(INIT_MONSTER_HP),
          atk(INIT_MONSTER_ATK), x(x), y(y), alive(true) {}

    // 攻击玩家
    void attack(Role& role);
    // 受伤害
    void takeDamage(int damage);
    // 随机移动(避开障碍物和玩家)
    void randomMove(const class Map& map);
    // 显示怪物状态
    void showStatus() const;
    // 获取坐标
    int getX() const { return x; }
    int getY() const { return y; }
    // 检查是否存活
    bool isAlive() const { return alive; }
    std::string getName() const { return name; }
    int getAtk() const { return atk; }
};

// 地图类
class Map {
private:
    std::vector<std::vector<char>> grid;  // 地图网格
    std::vector<Monster> monsters;        // 地图上的怪物
    int playerX, playerY;                 // 玩家当前位置

public:
    // 构造函数:初始化地图地形
    Map() {
        // 初始化网格为平地(.)
        grid.resize(MAP_HEIGHT, std::vector<char>(MAP_WIDTH, '.'));
        // 设置边界障碍物(#)
        for (int i = 0; i < MAP_HEIGHT; ++i) {
            grid[i][0] = '#';
            grid[i][MAP_WIDTH - 1] = '#';
        }
        for (int j = 0; j < MAP_WIDTH; ++j) {
            grid[0][j] = '#';
            grid[MAP_HEIGHT - 1][j] = '#';
        }
        // 设置中间障碍物(迷宫效果)
        grid[3][4] = grid[3][5] = grid[3][6] = '#';
        grid[6][10] = grid[7][10] = grid[8][10] = '#';
        grid[5][2] = grid[6][2] = grid[7][2] = '#';
    }

    // 初始化玩家位置(避开障碍物)
    void initPlayerPos(Role& player) {
        // 地图中心附近生成玩家
        playerX = MAP_WIDTH / 2;
        playerY = MAP_HEIGHT / 2;
        // 确保初始位置是平地且无障碍物
        while (grid[playerY][playerX] != '.') {
            playerX = rand() % (MAP_WIDTH - 2) + 1;
            playerY = rand() % (MAP_HEIGHT - 2) + 1;
        }
        player = Role("传奇勇士", playerX, playerY);
    }

    // 生成怪物(随机位置,避开障碍物、玩家)
    void spawnMonsters(int count) {
        for (int i = 0; i < count; ++i) {
            int x, y;
            // 循环生成合法位置(平地+无占用)
            do {
                x = rand() % (MAP_WIDTH - 2) + 1;
                y = rand() % (MAP_HEIGHT - 2) + 1;
            } while (grid[y][x] != '.' || isPosOccupied(x, y));

            monsters.emplace_back("黑野猪" + std::to_string(i + 1), x, y);
        }
    }

    // 检查坐标是否被占用(玩家或存活怪物)
    bool isPosOccupied(int x, int y) const {
        if (x == playerX && y == playerY) return true;
        for (const auto& monster : monsters) {
            if (monster.isAlive() && monster.getX() == x && monster.getY() == y) {
                return true;
            }
        }
        return false;
    }

    // 检查坐标是否合法(在地图内+非障碍物)
    bool isPosValid(int x, int y) const {
        return x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT && grid[y][x] == '.';
    }

    // 更新玩家位置到地图
    void updatePlayerPos(const Role& player) {
        playerX = player.getX();
        playerY = player.getY();
    }

    // 怪物随机移动更新
    void updateMonsters() {
        for (auto& monster : monsters) {
            if (monster.isAlive()) {
                monster.randomMove(*this);
            }
        }
    }

    // 查找玩家附近可攻击的怪物(最近优先)
    Monster* findAttackableMonster(const Role& player) {
        int px = player.getX();
        int py = player.getY();
        Monster* target = nullptr;
        int minDist = ATTACK_RANGE + 1;  // 初始距离超过攻击范围

        for (auto& monster : monsters) {
            if (!monster.isAlive()) continue;

            // 计算曼哈顿距离:|x1-x2| + |y1-y2|
            int dist = abs(monster.getX() - px) + abs(monster.getY() - py);
            if (dist <= ATTACK_RANGE && dist < minDist) {
                minDist = dist;
                target = &monster;
            }
        }
        return target;
    }

    // 渲染地图(显示玩家、怪物、地形)
    void display(const Role& player) const {
        system("cls");  // Windows清屏(Linux/macOS替换为 "clear")
        std::cout << "===== 传奇游戏地图 =====" << std::endl;
        for (int y = 0; y < MAP_HEIGHT; ++y) {
            for (int x = 0; x < MAP_WIDTH; ++x) {
                // 显示玩家(P)
                if (x == player.getX() && y == player.getY()) {
                    std::cout << "P ";
                }
                // 显示存活怪物(M)
                else {
                    bool isMonster = false;
                    for (const auto& monster : monsters) {
                        if (monster.isAlive() && monster.getX() == x && monster.getY() == y) {
                            std::cout << "M ";
                            isMonster = true;
                            break;
                        }
                    }
                    // 显示地形(障碍物# / 平地.)
                    if (!isMonster) {
                        std::cout << grid[y][x] << " ";
                    }
                }
            }
            std::cout << std::endl;
        }
        std::cout << "========================" << std::endl;
    }

    // 获取所有怪物(供主循环判断是否通关)
    const std::vector<Monster>& getMonsters() const { return monsters; }
};

// ------------------------------ 角色类方法实现 ------------------------------
bool Role::move(int dx, int dy, const Map& map) {
    int newX = x + dx;
    int newY = y + dy;
    // 检查位置是否合法(非障碍物+无占用)
    if (map.isPosValid(newX, newY) && !map.isPosOccupied(newX, newY)) {
        x = newX;
        y = newY;
        return true;
    }
    std::cout << "❌ 无法移动!前方有障碍物或其他单位" << std::endl;
    return false;
}

void Role::attack(Monster& monster) {
    if (!monster.isAlive()) {
        std::cout << "❌ 攻击无效!目标已死亡" << std::endl;
        return;
    }
    // 玩家攻击怪物
    std::cout << "\n⚔️ " << name << " 攻击了 " << monster.getName() << ",造成 " << atk << " 点伤害!" << std::endl;
    monster.takeDamage(atk);
    // 怪物存活则反击
    if (monster.isAlive()) {
        monster.attack(*this);
    } else {
        std::cout << "✅ " << monster.getName() << " 被击败!" << std::endl;
    }
}

void Role::takeDamage(int damage) {
    hp -= damage;
    if (hp < 0) hp = 0;
    std::cout << "💥 " << name << " 受到 " << damage << " 点伤害,剩余生命值:" << hp << std::endl;
    if (!isAlive()) {
        std::cout << "💀 " << name << " 生命值耗尽,游戏结束!" << std::endl;
    }
}

void Role::showStatus() const {
    std::cout << "\n【角色状态】" << std::endl;
    std::cout << "姓名:" << name << " | 等级:" << level << std::endl;
    std::cout << "生命值:" << hp << "/" << maxHp << " | 攻击力:" << atk << std::endl;
    std::cout << "当前位置:(" << x << "," << y << ")" << std::endl;
}

// ------------------------------ 怪物类方法实现 ------------------------------
void Monster::attack(Role& role) {
    std::cout << "🐗 " << name << " 发起反击,对 " << role.getName() << " 造成 " << atk << " 点伤害!" << std::endl;
    role.takeDamage(atk);
}

void Monster::takeDamage(int damage) {
    hp -= damage;
    if (hp <= 0) {
        hp = 0;
        alive = false;
    }
}

void Monster::randomMove(const Map& map) {
    // 四个移动方向(上、下、左、右)
    int dirs[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
    int randDir = rand() % 4;  // 随机选择方向
    int newX = x + dirs[randDir][0];
    int newY = y + dirs[randDir][1];

    // 位置合法则移动
    if (map.isPosValid(newX, newY) && !map.isPosOccupied(newX, newY)) {
        x = newX;
        y = newY;
    }
}

void Monster::showStatus() const {
    std::cout << "\n【怪物状态】" << std::endl;
    std::cout << "名称:" << name << " | 状态:" << (alive ? "存活" : "死亡") << std::endl;
    std::cout << "生命值:" << hp << "/" << maxHp << " | 攻击力:" << atk << std::endl;
    std::cout << "当前位置:(" << x << "," << y << ")" << std::endl;
}

// ------------------------------ 主函数(游戏流程) ------------------------------
int main() {
    // 初始化随机数种子(确保怪物位置/移动随机)
    srand(static_cast<unsigned int>(time(NULL)));

    // 游戏欢迎界面
    std::cout << "===== 🔥 传奇游戏 C++ 简化版 🔥 =====" << std::endl;
    std::cout << "📜 操作说明:" << std::endl;
    std::cout << "W - 向上 | S - 向下 | A - 向左 | D - 向右(移动)" << std::endl;
    std::cout << "空格 - 攻击(附近怪物) | T - 显示详细状态 | Q - 退出游戏" << std::endl;
    std::cout << "=====================================" << std::endl;
    system("pause");  // 暂停等待用户开始

    // 初始化游戏资源
    Map gameMap;          // 创建地图
    Role player("", 0, 0); // 创建玩家(后续初始化位置)
    gameMap.initPlayerPos(player);  // 初始化玩家位置
    gameMap.spawnMonsters(MONSTER_COUNT);  // 生成怪物

    // 游戏主循环
    char input;
    bool gameOver = false;
    while (!gameOver) {
        // 1. 渲染地图和角色状态
        gameMap.display(player);
        player.showStatus();

        // 2. 检查是否通关(所有怪物死亡)
        bool allMonstersDead = true;
        for (const auto& monster : gameMap.getMonsters()) {
            if (monster.isAlive()) {
                allMonstersDead = false;
                break;
            }
        }
        if (allMonstersDead) {
            std::cout << "\n🎉 恭喜!所有怪物已被击败,你通关了!" << std::endl;
            gameOver = true;
            break;
        }

        // 3. 接收用户输入
        std::cout << "\n请输入操作:";
        std::cin >> input;
        input = toupper(input);  // 转为大写,兼容小写输入

        // 4. 处理用户输入
        switch (input) {
            case 'W':  // 上移(y-1)
                player.move(0, -1, gameMap);
                gameMap.updatePlayerPos(player);
                break;
            case 'S':  // 下移(y+1)
                player.move(0, 1, gameMap);
                gameMap.updatePlayerPos(player);
                break;
            case 'A':  // 左移(x-1)
                player.move(-1, 0, gameMap);
                gameMap.updatePlayerPos(player);
                break;
            case 'D':  // 右移(x+1)
                player.move(1, 0, gameMap);
                gameMap.updatePlayerPos(player);
                break;
            case ' ':  // 攻击(空格)
            {
                Monster* target = gameMap.findAttackableMonster(player);
                if (target) {
                    player.attack(*target);
                } else {
                    std::cout << "❌ 附近没有可攻击的怪物!" << std::endl;
                }
                system("pause");  // 暂停查看战斗结果
                break;
            }
            case 'T':  // 显示详细状态(角色+所有怪物)
                player.showStatus();
                for (const auto& monster : gameMap.getMonsters()) {
                    monster.showStatus();
                }
                system("pause");
                break;
            case 'Q':  // 退出游戏
                std::cout << "👋 感谢游玩,再见!" << std::endl;
                gameOver = true;
                break;
            default:  // 无效输入
                std::cout << "❌ 无效操作,请重新输入!" << std::endl;
                system("pause");
                break;
        }

        // 5. 检查玩家是否死亡
        if (!player.isAlive()) {
            gameOver = true;
            break;
        }

        // 6. 怪物随机移动(每回合更新)
        gameMap.updateMonsters();
    }

    system("pause");
    return 0;
}
相关推荐
氷凌公子4 天前
六爻观测基础(十七)——卦例粗解(5)
国学·六爻
积跬步DEV1 年前
小白看八字排盘需要的基础知识
国学