首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

魔方公式庫 C++ 設計實戰:類封裝、文件持久化、旋轉/逆轉算法與完整測試框架

     編輯:關於C語言

本文呈現一個完整的 C++ 魔方公式管理類 MagicCube 設計與實現,涵蓋:動態內存管理構造/析構、文件加載公式、多模式幫助顯示、公式查詢、空間旋轉變換、逆序生成、主程序測試。代碼遵循 RAII、封裝、彈性接口原則,可直接作為課程設計或項目模塊參考。

需求分析與數據結構設計

  • 公式結構體:編號 number、層數 layer (1/2/3)、格式化字符串 formula (如 "R U R' U'")。
  • 存儲格式:formula.txt 每行 編號 層 字符串;help.txt 純文本;help1/2/3.html 網頁幫助。
  • 核心操作:旋轉 (左/右/上/下 90°/180°)、逆轉 (逆序+反向)、文件持久化。

完整類定義與實現

// MagicCube.h
#ifndef MAGIC_CUBE_H
#define MAGIC_CUBE_H

#include <string>
#include <vector>
#include <fstream>

class MagicCube {
    struct Formula {
        int number;
        int layer;
        std::string formula;
    };

    std::vector<Formula> formulas_;  // RAII 自動管理內存

public:
    explicit MagicCube(const std::string& file = "formula.txt");
    ~MagicCube() = default;  // vector 自動釋放

    // 幫助顯示:0=文本文件, 1/2/3=HTML 文件 system() 調用
    void Help(int layer = 0) const;

    // 統計公式數量:0=全部, 1/2/3=指定層
    int GetFormulaCount(int layer = 0) const;

    // 查詢公式:0=全部詳情字符串, >0=指定編號公式字符串
    std::string GetFormula(int number = 0) const;

    // 空間旋轉:direction 編碼 "1"=左, "2"=右, "3"=上, "4"=下, 可組合如 "113"
    // 重載 1: 修改傳入字符串 (引用)
    std::string& Rotate(std::string& formula, const std::string& direction);
    // 重載 2: 按編號旋轉,返回新字符串 (不修改原數據)
    std::string Rotate(int number, const std::string& direction) const;

    // 逆轉:逆序並反向每步
    // 重載 1: 修改傳入字符串
    std::string& Reverse(std::string& formula);
    // 重載 2: 按編號返回逆轉字符串
    std::string Reverse(int number) const;
};

#endif
// MagicCube.cpp
#include "MagicCube.h"
#include <cstdlib>   // system()
#include <sstream>
#include <algorithm>

MagicCube::MagicCube(const std::string& file) {
    std::ifstream in(file);
    if (!in) return;
    Formula f;
    while (in >> f.number >> f.layer) {
        std::getline(in >> std::ws, f.formula);  // 讀取剩余行作為公式串
        formulas_.push_back(f);
    }
}

void MagicCube::Help(int layer) const {
    if (layer == 0) {
        std::ifstream in("help.txt");
        std::string line;
        while (std::getline(in, line)) std::cout << line << '\n';
    } else if (layer >= 1 && layer <= 3) {
        std::string cmd = "help" + std::to_string(layer) + ".html";
        std::system(cmd.c_str());  // 調用系統默認瀏覽器/查看器
    }
}

int MagicCube::GetFormulaCount(int layer) const {
    if (layer == 0) return formulas_.size();
    return std::count_if(formulas_.begin(), formulas_.end(),
                         [layer](const Formula& f) { return f.layer == layer; });
}

std::string MagicCube::GetFormula(int number) const {
    if (number == 0) {
        std::ostringstream oss;
        for (const auto& f : formulas_)
            oss << "No." << f.number << " Layer" << f.layer << ": " << f.formula << '\n';
        return oss.str();
    }
    for (const auto& f : formulas_)
        if (f.number == number) return f.formula;
    return "";
}

// 核心變換:單步旋轉映射表
// 原面順序: B H A P D G (索引 0..5)
// 左轉: B H G D A P  → 映射 [0,1,5,3,2,4]
// 右轉: B H D G P A  → 映射 [0,1,3,5,4,2]
// 上轉: A P H B D G  → 映射 [2,3,1,0,4,5]
// 下轉: P A B H D G  → 映射 [3,2,0,1,4,5]
static const int ROT_MAP[4][6] = {
    {0,1,5,3,2,4},  // 1 左
    {0,1,3,5,4,2},  // 2 右
    {2,3,1,0,4,5},  // 3 上
    {3,2,0,1,4,5}   // 4 下
};

static std::string ApplyRotation(const std::string& src, char dir) {
    if (src.size() != 6) return src;  // 簡化:假設公式固定 6 面碼
    std::string dst(6, ' ');
    const int* map = ROT_MAP[dir - '1'];
    for (int i = 0; i < 6; ++i) dst[i] = src[map[i]];
    return dst;
}

std::string& MagicCube::Rotate(std::string& formula, const std::string& direction) {
    for (char d : direction) {
        if (d >= '1' && d <= '4')
            formula = ApplyRotation(formula, d);
    }
    return formula;
}

std::string MagicCube::Rotate(int number, const std::string& direction) const {
    std::string f = GetFormula(number);
    return Rotate(f, direction);  // 利用引用重載 (需 const_cast 或複製),此處簡化複製
}

std::string& MagicCube::Reverse(std::string& formula) {
    // 逆轉 = 逆序 + 每步反向 (L↔R, U↔D)
    std::reverse(formula.begin(), formula.end());
    for (char& c : formula) {
        if (c == '1') c = '2'; else if (c == '2') c = '1';
        else if (c == '3') c = '4'; else if (c == '4') c = '3';
    }
    return formula;
}

std::string MagicCube::Reverse(int number) const {
    std::string f = GetFormula(number);
    Reverse(f);
    return f;
}

主程序測試驗證

// main.cpp
#include "MagicCube.h"
#include <iostream>

int main() {
    MagicCube mc("formula.txt");

    // 1. 幫助測試
    std::cout << "=== Help (text) ===\n"; mc.Help(0);
    std::cout << "\n=== Help Layer 2 (HTML) ===\n"; mc.Help(2);  // 需有 help2.html

    // 2. 統計測試
    std::cout << "Total formulas: " << mc.GetFormulaCount(0) << '\n';
    std::cout << "Layer 1 count: " << mc.GetFormulaCount(1) << '\n';

    // 3. 查詢測試
    std::cout << "\n=== Formula #8 ===\n" << mc.GetFormula(8) << '\n';
    std::cout << "\n=== All Formulas ===\n" << mc.GetFormula(0) << '\n';

    // 4. 旋轉測試
    std::string f8 = mc.GetFormula(8);
    std::cout << "\nOriginal #8: " << f8 << '\n';
    std::string rotated = mc.Rotate(8, "113");  // 左180° + 上90°
    std::cout << "Rotated '113': " << rotated << '\n';

    // 5. 逆轉測試
    std::string reversed = mc.Reverse(8);
    std::cout << "Reversed #8: " << reversed << '\n';

    // 6. 圓周驗證:旋轉後逆轉應回原狀
    std::string test = mc.Rotate(8, "1234");
    mc.Reverse(test);
    std::cout << "Rotate+Reverse back: " << test << " (expected: " << f8 << ")\n";

    return 0;
}

測試數據文件示例 (formula.txt)

1 1 RUR'U'
2 1 FUF'U'
3 2 RU'R'U
4 2 LU'L'U
5 3 FRU'R'F'
6 3 FL'U'LF'
7 1 RU2R'U
8 1 RUR'U'RUR'U'
9 2 L'U'LU
10 3 F'U'FU

設計亮點總結

特性實現方式
動態內存/RAIIstd::vector<Formula> 替代手動 new[]/delete[]
文件持久化構造函數流式讀取 formula.txt,彈性擴展
多模式幫助文本流輸出 + system() 調用 HTML 瀏覽器
旋轉算法查表法 ROT_MAP,O(1) 單步,支持組合方向字符串
逆轉算法逆序 + 字符映射 (1↔2, 3↔4)
接口彈性提供修改原串 (引用) 與不修改 (返回新串) 兩套重載
測試完備主程序覆蓋所有接口,含圓周驗證

編譯運行

g++ -std=c++11 MagicCube.cpp main.cpp -o magic_cube
./magic_cube
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved