SudokuSolver 2.6 新增功能程序实现

SudokuSolver 2.6 新增功能程序实现

本次版本实现了 用C++实现的数独解题程序 SudokuSolver 2.6 的新功能及相关分析 里介绍的猜测级别相关的新功能。具体代码实现如下。

CQuizDealer 类声明部分的修改

增加了showLevels 接口:

    void showQuiz();
    void showLevels();

增加了交互式猜测模式查询与修改接口 guessMode:

    void guessMode(std::string& ex) {
        size_t pos = ex.find_first_not_of(" \t");
        if (pos != std::string::npos) {
            ex.erase(0, pos);
            m_guessMode = (u8)strtoul(ex.c_str(), 0, 10);
        }
        printf("In interactive guessing mode:%d (0:no; other:yes)\n", (int)m_guessMode);
    }

构造函数成员初始化部分小修改:

    CQuizDealer() : m_state(STA_UNLOADED), m_guessLevel(0), m_guessPos(0), m_guessValPos(0), 
        m_soluSum(0), m_bigSum(0), m_bigbigSum(0), m_steps(0), m_bigSteps(0), m_bigbigSteps(0), 
        m_mode(0), m_guessMode(0), m_maxLevel(0) {};

增加交互式猜测实现接口:

    void doInteractGuess(u8& guessIdx);
    bool dealGuess(std::string& strGuess, u8& guessIdx);

增加两个成员变量:

    u8 m_guessMode; // 0:auto-guess; other:interactive guess
    u8 m_maxLevel;

showLevels 接口实现

 1 void CQuizDealer::showLevels()
 2 {
 3     if (m_stkSnap.empty()) {
 4         printf("No guess level info\n");
 5         return;
 6     }
 7     std::stack<Snapshot*> stkSnap = m_stkSnap;
 8     u8 levels = (u8)stkSnap.size();
 9     printf("At guess level %d:\n", (int)levels);
10     for (u8 level = levels; level > 0; --level) {
11         Snapshot* pSnap = stkSnap.top();
12         u8 pos = pSnap->guessPos;
13         u8 val = pSnap->seqCell[pos].candidates[pSnap->guessValPos];
14         u8 sum = pSnap->seqCell[pos].candidates[0];
15         printf("Level %d [%d,%d]=%d (%d out of %d)\n", (int)level, (int)pos / 9 + 1, (int)pos % 9 + 1, (int)val, (int)pSnap->guessValPos, (u8)sum);
16         stkSnap.pop();
17     }
18 }

dealGuess 接口实现

 1 bool CQuizDealer::dealGuess(std::string& strGuess, u8& guessIdx)
 2 {
 3     size_t pos = strGuess.find_first_not_of(" \t");
 4     if (pos == std::string::npos)
 5         return true;
 6     if (strGuess[pos] != '[')
 7         return false;
 8     strGuess.erase(0, pos + 1);
 9     pos = strGuess.find_first_of(",");
10     if (pos == std::string::npos)
11         return false;
12     std::string str = strGuess.substr(0, pos);
13     u8 row = (u8)strtoul(str.c_str(), 0, 10);
14     if (row == 0 || row > 9)
15         return false;
16     --row;
17     strGuess.erase(0, pos + 1);
18     pos = strGuess.find_first_of("]");
19     if (pos == std::string::npos)
20         return false;
21     str = strGuess.substr(0, pos);
22     u8 col = (u8)strtoul(str.c_str(), 0, 10);
23     if (col == 0 || col > 9)
24         return false;
25     --col;
26     u8 newIdx = row * 9 + col;
27     if (m_seqCell[newIdx].val != 0)
28         return false;
29     strGuess.erase(0, pos + 1);
30     pos = strGuess.find_first_of("=");
31     if (pos == std::string::npos)
32         return false;
33     str = strGuess.erase(0, pos + 1);
34     u8 val = (u8)strtoul(strGuess.c_str(), 0, 10);
35     if (val == 0 || val > 9)
36         return false;
37     for (u8 idx = 1; idx <= m_seqCell[newIdx].candidates[0]; ++idx) {
38         if (val == m_seqCell[newIdx].candidates[idx]) {
39             if (idx != 1) {
40                 u8 tmp =  m_seqCell[newIdx].candidates[1];
41                 m_seqCell[newIdx].candidates[1] = val;
42                 m_seqCell[newIdx].candidates[idx] = tmp;
43             }
44             guessIdx = newIdx;
45             return true;
46         }
47     }
48     return false;
49 }

doInteractGuess 接口实现

 1 void CQuizDealer::doInteractGuess(u8& guessIdx)
 2 {
 3     std::string strGuess;
 4     while (true) {
 5         u8 val = m_seqCell[guessIdx].candidates[1];
 6         printf("Take a guess please, by default it will be [%d,%d]=%d:\n", (int)guessIdx / 9 + 1, (int)guessIdx % 9 + 1, (int)val);
 7         getline(std::cin, strGuess);
 8         if (dealGuess(strGuess, guessIdx))
 9             return;
10         printf("Invalid guess; please try again more carefully.\n");
11     }
12 }

guess 接口实现小修改

void CQuizDealer::guess(u8 guessIdx)
{
    if (m_guessMode != 0)
        doInteractGuess(guessIdx);
    incSteps();
    ++m_guessLevel;
    if (m_guessLevel > m_maxLevel)
        m_maxLevel = m_guessLevel;
    m_guessPos = guessIdx;
    ...
}

run 接口实现小修改

void CQuizDealer::run(ulong tilsteps)
{
    ...
std::cout << "Run time: " << clock() - begin << " milliseconds; steps: " << m_steps << ", solution sum: " << m_soluSum << ".\n"; std::cout << " Biggest level on this run(til): " << (int)m_maxLevel << "\n"; m_maxLevel = 0; }

runrun 接口实现小修改

void CQuizDealer::runrun(ulong newsum)
{
    ...
    std::cout << "Run-run time: " << clock() - begin << " milliseconds; current solutions: " << s_soluSum << std::endl;
    std::cout << " biggest level ever on this quiz: " << (int)m_maxLevel << std::endl;
    std::cout << " steps: " << m_bigbigSteps << " # " << m_bigSteps << " # " << m_steps << std::endl;
    std::cout << " total solutions: " << m_bigbigSum << " # " << m_bigSum << " # " << m_soluSum << ".\n";
}

其他小修改

// 1.0 2021/9/20
// 2.0 2021/10/2
// 2.1 2021/10/4
// 2.2 2021/10/10
// 2.3 2021/10/17
// 2.4 2021/10/19
// 2.5 2021/10/23
#define STR_VER "Sudoku Solver 2.6 2021/10/30 by readalps\n\n"

void showOrderList()
{
    printf(STR_VER);
    printf("Order List:\n");
    printf("load-quiz <file>: load quiz from file\n");
    printf("show: show quiz info\n");
    printf("levels: show info about guess levels\n");
    printf("run-mode [1|2|0]: query or change working mode\n");
    printf("guess-mode [1|0]: query or change guessing mode\n");
    printf("step: step forward\n");
    printf("run: run till the end or a new solution met\n");
    printf("runtil <steps>: run till certain steps run\n");
    printf("runrun <sum>: run till the end or certain new solutions met\n");
    printf("bye: quit\n");
}

void dealOrder(std::string& strOrder)
{
    std::string strEx;
    if ("bye" == strOrder)
        setQuit();
    else if (matchPrefixEx(strOrder, "load-quiz ", strEx))
        CQuizDealer::instance()->loadQuiz(strEx);
    else if ("show" == strOrder)
        CQuizDealer::instance()->showQuiz();
    else if ("levels" == strOrder)
        CQuizDealer::instance()->showLevels();
    else if (matchPrefixEx(strOrder, "run-mode", strEx))
        CQuizDealer::instance()->mode(strEx);
    else if (matchPrefixEx(strOrder, "guess-mode", strEx))
        CQuizDealer::instance()->guessMode(strEx);
    ...
}

 

上一篇:javascript多投事件的处理 (转)


下一篇:SudokuSolver 1.0:用C++实现的数独解题程序 【二】