数独源码

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

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

但感觉代码还是非常复杂,在网上看了新加坡总理李显龙的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;
}

 

转载于:https://www.cnblogs.com/huoqs/p/6218979.html

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值