• 数独源码


    因为下载了一个数独游戏,想着写个计算器。

    原理很简单,就是暴力破解

    但感觉代码还是非常复杂,在网上看了新加坡总理李显龙的c代码,仅有几十行,用位运算比较多,比较晦涩难懂。但写的真好

    想着用c++尽量面向对象的思想实现一下,代码如下:

    平台ubuntu + Qt,控制台程序,在windows下运行应该也没问题。

    main.cpp

    /* write by huoqs
     * 2016-12-25
     */
    #include <QCoreApplication>
    #include <iostream>
    #include "sudoku.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        SudokuCalcultor oCalc;
        //input unknown number please input 0 (no space)
        char nData;
        for (int i = 0; i < 9; i++)
        {
            cout << "Row " << i+1 << ":";
            for (int j = 0; j < 9; j++)
            {
                cin >> nData;
                oCalc.setData(i, j, nData - '0');
            }
        }
        oCalc.outPut();
        oCalc.calculateAndOutput();
        cout << "Hello World!" << endl;
    
        return a.exec();
    }
    

     sudoku.h

    #ifndef SUDOKU_H
    #define SUDOKU_H
    #include <QVector>
    
    class SudokuBoxes;
    class SudokuBox;
    
    class SudokuCalcultor
    {
    public:
        SudokuCalcultor();
        ~SudokuCalcultor();
        void setData(int nRow, int nColumn, int nData);
        void calculateAndOutput();
        void outPut();
    
    private:
        void initialData();
        SudokuBox* findNextUncertainBox();
        QVector<int> findPossibleNumbers(SudokuBox* pBox);
        bool isValid();
        void attemptSetBox(SudokuBox* pBox);
        QVector<SudokuBoxes* > m_oRows;
        QVector<SudokuBoxes* > m_oColumns;
        QVector<SudokuBoxes* > m_oBlocks;
        QVector<SudokuBox* > m_oBoxes;
    };
    
    //has nine box
    class SudokuBoxes
    {
    public:
        void addBox(SudokuBox* pBox);
        SudokuBox* box(int nIndex);
        bool isValid();
    private:
        QVector<SudokuBox*> m_oSudokuBoxes;
    };
    
    class SudokuBox
    {
    public:
        SudokuBox(int nRow, int nColumn);
        int column();
        int row();
        int block();
        int data();
        void setData(int nData);
    private:
        int m_nColumn;
        int m_nRow;
        int m_nData;
    };
    
    #endif // SUDOKU_H
    

     sudoku.cpp

    #include <sudoku.h>
    #include <iostream>
    
    SudokuCalcultor::SudokuCalcultor()
    {
        initialData();
    }
    
    SudokuCalcultor::~SudokuCalcultor()
    {
        qDeleteAll(m_oBoxes);
        m_oBoxes.clear();
        qDeleteAll(m_oRows);
        m_oRows.clear();
        qDeleteAll(m_oColumns);
        m_oColumns.clear();
        qDeleteAll(m_oBlocks);
        m_oBlocks.clear();
    }
    
    void SudokuCalcultor::initialData()
    {
        for (int i = 0; i < 9; i++)
        {
            SudokuBoxes* pBoxes = new SudokuBoxes();
            m_oRows.append(pBoxes);
            pBoxes = new SudokuBoxes();
            m_oColumns.append(pBoxes);
            pBoxes = new SudokuBoxes();
            m_oBlocks.append(pBoxes);
        }
        for (int i = 0; i < 9; i++)
        {
    
            for (int j = 0; j < 9; j++)
            {
                SudokuBox * pBox = new SudokuBox(i, j);
                m_oBoxes.append(pBox);
                m_oRows.at(i)->addBox(pBox);
                m_oColumns.at(j)->addBox(pBox);
                m_oBlocks.at(i / 3 * 3 + j / 3)->addBox(pBox);
            }
        }
    }
    
    void SudokuCalcultor::outPut()
    {
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                std::cout << m_oRows.at(i)->box(j)->data() << " ";
            }
            std::cout << std::endl;
        }
    
        std::cout << std::endl;
    
    }
    bool SudokuCalcultor::isValid()
    {
        for (int i = 0; i < 9; i++)
        {
            if (!m_oRows.at(i)->isValid())
            {
                return false;
            }
        }
        for (int i = 0; i < 9; i++)
        {
            if (!m_oColumns.at(i)->isValid())
            {
                return false;
            }
        }
        for (int i = 0; i < 9; i++)
        {
            if (!m_oBlocks.at(i)->isValid())
            {
                return false;
            }
        }
        return true;
    }
    
    void SudokuCalcultor::setData(int nRow, int nColumn, int nData)
    {
        m_oRows.at(nRow)->box(nColumn)->setData(nData);
    }
    
    void SudokuCalcultor::calculateAndOutput()
    {
        if (!isValid())
        {
            std::cout << "The Initial is not Valid." << std::endl;
            return;
        }
        SudokuBox* pFirst = findNextUncertainBox();
        if (pFirst)
        {
            attemptSetBox(pFirst);
        }
    }
    
    void SudokuCalcultor::attemptSetBox(SudokuBox* pBox)
    {
        if (!pBox)
        {
            outPut();
            return;
        }
        QVector<int> oVec = findPossibleNumbers(pBox);
        for (auto it = oVec.begin(); it != oVec.end(); it++)
        {
            pBox->setData(*it);
            SudokuBox * pNextBox = findNextUncertainBox();
            attemptSetBox(pNextBox);
            pBox->setData(0);
        }
    }
    
    QVector<int> SudokuCalcultor::findPossibleNumbers(SudokuBox* pBox)
    {
        QVector<int> oVec{1,2,3,4,5,6,7,8,9};
        SudokuBoxes* pBoxes = m_oRows.at(pBox->row());
        for (int i = 0; i < 9; i++)
        {
            oVec.removeOne(pBoxes->box(i)->data());
        }
        pBoxes = m_oColumns.at(pBox->column());
        for (int i = 0; i < 9; i++)
        {
            oVec.removeOne(pBoxes->box(i)->data());
        }
        pBoxes = m_oBlocks.at(pBox->block());
        for (int i = 0; i < 9; i++)
        {
            oVec.removeOne(pBoxes->box(i)->data());
        }
        return oVec;
    }
    
    SudokuBox* SudokuCalcultor::findNextInvalid()
    {
        for (auto it = m_oBoxes.begin(); it != m_oBoxes.end(); it++)
        {
            if ((*it)->data() < 1)
            {
                return *it;
            }
        }
        return nullptr;
    }
    
    void SudokuBoxes::addBox(SudokuBox* pBox)
    {
        m_oSudokuBoxes.append(pBox);
    }
    
    SudokuBox* SudokuBoxes::box(int nIndex)
    {
        return m_oSudokuBoxes.at(nIndex);
    }
    
    bool SudokuBoxes::isValid()
    {
        QVector<int> oVec{1,2,3,4,5,6,7,8,9};
        for (auto it = m_oSudokuBoxes.begin(); it != m_oSudokuBoxes.end(); it ++)
        {
            int nData = (*it)->data();
            if (nData != 0)
            {
                if (oVec.contains(nData))
                {
                    oVec.removeOne(nData);
                }
                else
                {
                    return false;
                }
            }
        }
        return true;
    }
    
    SudokuBox::SudokuBox(int nRow, int nColumn):
        m_nRow(nRow), m_nColumn(nColumn), m_nData(0)
    {
    
    }
    
    int SudokuBox::column()
    {
        return m_nColumn;
    }
    
    int SudokuBox::row()
    {
        return m_nRow;
    }
    
    int SudokuBox::data()
    {
        return m_nData;
    }
    
    void SudokuBox::setData(int nData)
    {
        m_nData = nData;
    }
    
    int SudokuBox::block()
    {
        return m_nRow / 3 * 3 + m_nColumn / 3;
    }
    
  • 相关阅读:
    Azure Application Gateway (6) 使用OpenSSL创建SAN证书
    MySQL常用函数整理,建议收藏!
    设计一个接口至少要考虑这14点!
    SpringBoot 常用读取配置文件的 3 种方法!
    MyBatisPlus常用功能总结!(附项目示例)
    接口测试神器Apifox,亲测好用!
    huey在windows下使用的坑
    sublimeCodeIntel在windows下安装的坑
    字符串生成二维码
    android中EditText有光标不弹出软键盘处理(转)
  • 原文地址:https://www.cnblogs.com/huoqs/p/6218979.html
Copyright © 2020-2023  润新知