根据题目要求,由于我第二次作业写得代码没有类,不好调用函数,所以 基于第二次写数独的思想代码进行了重写改动。
Su1.cpp代码(数独代码)
#include "stdafx.h"#include "Su.h"#include "Su1.h"#include#include #ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endifCSu::CSu(){ int i,j; for(i=1;i<10;i++) for(j=1;j<10;j++) map[i][j] = 0;}CSu::CSu(int n) //随机生成n个数字{ int i,j; for(i=1;i<10;i++) for(j=1;j<10;j++) map[i][j] = 0; srand((unsigned)time(0)); //每行初始一个 do { for(i=1;i<10;i++) { j = rand()%10; map[i][j] = i; } }while (!Check()); Solve();//填好 //挖空 int k = 0; while(1) { i=rand()%81; j=i%9; i=i/9; int x = map[i+1][j+1]; if(x>0) { map[i+1][j+1] = 0; k++; } if(k == 81-n) break; } }CSu::CSu(int data[9][9]){ int i,j; for(i=1;i<10;i++) for(j=1;j<10;j++) map[i][j] = data[i-1][j-1];}CSu::~CSu(){ return;}bool CSu::Check(){ memset(sqr,false,sizeof(sqr)); memset(row,false,sizeof(sqr)); memset(col,false,sizeof(sqr)); int i,j; for(i=1;i<10;i++) for(j=1;j<10;j++) { int temp = map[i][j]; if( temp != 0) { if( !row[i][temp] ) row[i][temp] = true; else return false; if( !col[j][temp]) col[j][temp] = true; else return false; if( !sqr[(i-1)/3*3+(j-1)/3+1][temp] ) sqr[(i-1)/3*3+(j-1)/3+1][temp] = true; else return false; } } return true;}bool CSu::Solve(){ int i,j; memset(sqr,false,sizeof(sqr)); memset(row,false,sizeof(sqr)); memset(col,false,sizeof(sqr)); for(i=1;i<=9;i++) for(j=1;j<=9;j++) { if(map[i][j]!=0) { row[i][map[i][j]]=true; col[j][map[i][j]]=true; //小正方形被标志为1--9; sqr[(i-1)/3*3+(j-1)/3+1][map[i][j]]=true; } } bool ans = DFS(); return ans;}bool CSu::DFS(){ int i,j,k; for(i=1;i<10;i++) for(j=1;j<10;j++) { if(map[i][j]==0) { for(k=1;k<=9;k++) { if(!row[i][k]&&!col[j][k]&&!sqr[(i-1)/3*3+(j-1)/3+1][k]) { map[i][j]=k; row[i][k]=true; col[j][k]=true; sqr[(i-1)/3*3+(j-1)/3+1][k]=true; if(DFS()) return true; else { map[i][j]=0; row[i][k]=false; col[j][k]=false; sqr[(i-1)/3*3+(j-1)/3+1][k]=false; } } } if(k==10)return false; } } return true;}
Su1.h代码
#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000class CSu {public: CSu(); CSu(int n); //随机生成数独,n个空格含有数字 CSu(int data[9][9]); virtual ~CSu(); bool Check(); bool Solve(); bool DFS(); int map[10][10];private: bool row[10][10],col[10][10],sqr[10][10]; };#endif
添加数独题目按钮代码
void CSuDlg::OnButton1() //数独题目按钮{ // TODO: Add your control notification handler code here int i,j; for(i=0;i<81;i++) { c[i].SetWindowText("0"); c[i].EnableWindow(1); } CSu s(40); char str[5]; int count = 0; for(i=1;i<=9;i++) for(j=1;j<=9;j++) { str[0]=s.map[i][j]+'0'; str[1]='\0'; c[count].SetWindowText(str); if(s.map[i][j]!=0) c[count].EnableWindow(0); count++; }}
添加解数独按钮代码
void CSuDlg::OnButton2() //解数独按钮{ // TODO: Add your control notification handler code here int i,j; int result[9][9]; char buf[5]; for(i=0;i<81;i++) { c[i].GetLine(0,buf,5); int x = atoi(buf); int l,c,temp; temp = i; l = temp/9; c = temp%9; result[l][c] = x; } CSu s(result); s.Solve(); char str[5]; int count = 0; for(i=1;i<=9;i++) for(j=1;j<=9;j++) { str[0]=s.map[i][j]+'0'; str[1]='\0'; c[count].SetWindowText(str); count++; } }
确定按钮代码
void CSuDlg::OnOK() //确定按钮{ // TODO: Add extra validation here int i; int result[9][9]; char buf[5]; for(i=0;i<81;i++) { c[i].GetLine(0,buf,5); int x = atoi(buf); if(x==0) { AfxMessageBox("没有填完!!"); return; } if(x<0 || x>9) { AfxMessageBox("请填入0--9以内的数字!!"); return; } int l,c,temp; temp = i; l = temp/9; c = temp%9; result[l][c] = x; } CSu s(result); if(s.Check()) AfxMessageBox("祝贺,成功完成!"); else AfxMessageBox("很遗憾,解答错误!"); CDialog::OnOK();}
程序运行能够出正确结果,如下图:(分别是一开始运行出来的界面,然后是单击“题目“”出现的数独题目,最后是单击“”解数独“”后出现的唯一解数独)
完整的代码可在https://coding.net/u/dhlg201810812010/p/Su/git查看
遇到的问题:
1.不知道怎么建立GUI界面,想起在大学的时候之前用VC++6.0可以自动生成GUI界面,于是就用VC++6.0建立了一个基于“MFC AppWizard[exe]”"基本对话框“”项目工程,建立完成后可以在"Resources"下的"IDD_SU_DIALOG"加控件,对控件也可以进行重命名,形成一个GUI界面,如图:
再往控件加相应的代码。
2.Debug/Su.pch:No such file or dictory(即找不到预编译文件) (解决办法:对StaAfx.cpp文件重新编译下)
3.在SuDlg.cpp文件编译的时候CSu s(40)报错,提示CSu没有定义类型 (解决办法:在该文件下加入 #include “Su1.h”,因为在Su1.h该文件对CSu有定义)
4.不知道该怎么把第二次作业写的数独代码和这次关联起来,一开始是想这次建个MFC AppWizard[dill]动态调用第二次写的代码,但是我不会,所以就建立了MFC AppWizard[exe]项目工程,然后在头文件新建一个Su1.cpp文件,在源文件新建立Su1.h文件,在这两文件写入之前作业的代码。
心得体会:
这次的作业我觉得难度挺大的,整个作业做下来花费了40个小时,做这个作业曾n次想放弃,然后室友说不能放弃,要坚持到底,然后就开始又硬着头皮开始查资料,思考,和同学交流,虽然这次做作业的过程是挺痛苦的,但是最后整个作业下来收获也是挺大的,从一开始不会创建GUI界面,到会创建GUI界面,会接控件,会给加的控件重命名,给控件加代码实现想要达到的功能,同时这个作业做下来对C++的面向对象与可视化程序设计也有了个更深层次的了解,也重拾了c++里的类、派生和函数调用知识。对自己遇到困难坚持下去的毅力也得到了锻炼,知道了交流的重要性,不能自己蒙着头做,学会交流,在交流中进步。