数独游戏求解

 其中ResovleCells()函数的参数含义是: 输入数独游戏的原始状态.
如下就是data.txt一个范例:

0 0 0 8 0 2 1 0 0
0 0 0 0 0 0 6 0 5
0 0 4 6 1 5 0 0 0
6 9 0 0 0 0 0 3 0
4 0 0 1 6 8 0 0 9
0 7 0 0 0 0 0 4 6
0 0 0 7 8 1 5 0 0
7 0 2 0 0 0 0 0 0
0 0 8 2 0 9 0 0 0

可以运行本程序求解得到:

 5 3 6 8 7 2 1 9 4
 2 1 7 9 3 4 6 8 5
 9 8 4 6 1 5 3 2 7
 6 9 5 4 2 7 8 3 1
 4 2 3 1 6 8 7 5 9
 8 7 1 5 9 3 2 4 6
 3 4 9 7 8 1 5 6 2
 7 5 2 3 4 6 9 1 8
 1 6 8 2 5 9 4 7 3
Successful

//================================================
// main.cpp

#include "ShuDu.h"

int main()
{
 CShuDu shudu;
 shudu.ResolveCells("data.txt");
 return 0;
} 

//===============================================
// ShuDu.h
#ifndef __SHUDU_H__
#define __SHUDU_H__

#include <memory.h>

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

typedef int ELEMTYPE;
typedef int BOOL;

#define FALSE 0
#define TRUE 1

class CShuDu
{
public:
 CShuDu();
 BOOL ResolveCells(const string &filename);
 ~CShuDu();

private:
 BOOL InitCells(const string &filename);
 BOOL RecursionBody(int position);
 BOOL CheckValid(int row, int col);
 BOOL PrintCells();

protected:
  ELEMTYPE m_iCells[9][9];
  BOOL m_bReadOnly[9][9];
};


// ============================================================

CShuDu::CShuDu()
{
 // Initial primative cells to 0.
 memset(m_iCells, 9*9, sizeof(ELEMTYPE));
}

CShuDu::~CShuDu()
{
 // nothing to do
}

BOOL CShuDu::InitCells(const string &filename)
{
 ifstream infile;
 ELEMTYPE iCount;

 infile.open(filename.data());

 if(!infile)
 {
  // open file fail
  cout<<filename<<" open fail!"<<endl;
  return FALSE;
 }

 iCount = 0;
 while(!infile.eof() && iCount < 81)
 {
  // read data to m_iCells array
  ELEMTYPE *pCurrentInput = &m_iCells[iCount/9][iCount%9];
  BOOL *pCurrentBool = &m_bReadOnly[iCount/9][iCount%9];

  infile>>*pCurrentInput;
  if(*pCurrentInput < 0 || *pCurrentInput > 9)
  {
   cout<<"Init data "<<*pCurrentInput<<" out of range!"<<endl;
   return FALSE;
  }
  else
  {
   if(*pCurrentInput != 0)
    *pCurrentBool = TRUE;
   else
    *pCurrentBool = FALSE;
   ++iCount;  
  }
 }
 
 if(iCount != 81)
 {
  // total number error
  cout<<"Total input data number error!"<<endl;
  return FALSE;
 }
 return TRUE;
}

BOOL CShuDu::PrintCells()
{
 int i, j;
 for(i=0; i<9; ++i)
 {
  for(j=0; j<9; ++j)
   cout<<" "<<m_iCells[i][j];
  cout<<endl;  
 }
 return TRUE;
}

BOOL CShuDu::CheckValid(int row, int col)
{
 int i, j;

 ELEMTYPE *pCurrent = &m_iCells[row][col];

 // check row
 for(j=0; j<9; ++j)
 {
  if(m_iCells[row][j] == *pCurrent)
  {
   if(j != col)
    return FALSE;
  }
 }

 // check col
 for(i=0; i<9; ++i)
 {
  if(m_iCells[i][col] == *pCurrent)
  {
   if(i != row)
    return FALSE;
  }
 }

 // check sub 9-cells
 int m = row / 3;
 int n = col / 3;

 for(i=m*3; i<(m+1)*3; ++i)
 {
  for(j=n*3; j<(n+1)*3; ++j)
  {
   if(m_iCells[i][j] == *pCurrent)
   {
    if(pCurrent != &m_iCells[i][j])
     return FALSE;
   }
  }
 }
 
 // no the same element yet, it is valid at present status.
 return TRUE;
}

BOOL CShuDu::ResolveCells(const string &filename)
{
 if(!InitCells(filename))
  return FALSE;
 BOOL bResult = RecursionBody(0);
 if(bResult)
  cout<<"Successful"<<endl;
 else 
  cout<<"Failure"<<endl;
 return bResult;
}

BOOL CShuDu::RecursionBody(int position)
{
 if(position >= 81)
 {
  // get the right answer
  PrintCells();
  return TRUE;
 }
 
 int row, col;
 row = position / 9;
 col = position % 9;
 while(position < 81 && m_bReadOnly[row][col])
 {
  ++position;
  row = position / 9;
  col = position % 9;
 }

 if(position >= 81)
  return RecursionBody(position);

 // still exist cells that have not be filled.
 ELEMTYPE *pCurrent = &m_iCells[row][col];
 for(int i=1; i<=9; ++i)
 {
  
  *pCurrent = i;
  if(!CheckValid(row, col))
   continue;
  // get the correct answer
  if(RecursionBody(position+1))
    return TRUE;
 }
 *pCurrent = 0;

 return FALSE;
}

#endif


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值