因为下载了一个数独游戏,想着写个计算器。
原理很简单,就是暴力破解
但感觉代码还是非常复杂,在网上看了新加坡总理李显龙的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; }