mirror of https://github.com/dnomd343/Sudoku
dnomd343
5 years ago
committed by
GitHub
5 changed files with 677 additions and 0 deletions
@ -0,0 +1,167 @@ |
|||||
|
VERSION 5.00 |
||||
|
Begin VB.Form Form1 |
||||
|
AutoRedraw = -1 'True |
||||
|
BorderStyle = 1 'Fixed Single |
||||
|
Caption = "Sudoku Calculator" |
||||
|
ClientHeight = 9045 |
||||
|
ClientLeft = 45 |
||||
|
ClientTop = 390 |
||||
|
ClientWidth = 8730 |
||||
|
LinkTopic = "Form1" |
||||
|
MaxButton = 0 'False |
||||
|
MinButton = 0 'False |
||||
|
ScaleHeight = 9045 |
||||
|
ScaleWidth = 8730 |
||||
|
StartUpPosition = 2 'ÆÁÄ»ÖÐÐÄ |
||||
|
Begin VB.CommandButton Command4 |
||||
|
Caption = "Clear" |
||||
|
Height = 375 |
||||
|
Left = 4440 |
||||
|
TabIndex = 4 |
||||
|
Top = 8520 |
||||
|
Width = 1965 |
||||
|
End |
||||
|
Begin VB.CommandButton Command3 |
||||
|
Caption = "Save" |
||||
|
Height = 375 |
||||
|
Left = 2400 |
||||
|
TabIndex = 3 |
||||
|
Top = 8520 |
||||
|
Width = 1965 |
||||
|
End |
||||
|
Begin VB.CommandButton Command2 |
||||
|
Caption = "Open" |
||||
|
Height = 375 |
||||
|
Left = 360 |
||||
|
TabIndex = 2 |
||||
|
Top = 8520 |
||||
|
Width = 1965 |
||||
|
End |
||||
|
Begin VB.CommandButton Command1 |
||||
|
Caption = "Calculate" |
||||
|
Height = 375 |
||||
|
Left = 6480 |
||||
|
TabIndex = 1 |
||||
|
Top = 8520 |
||||
|
Width = 1965 |
||||
|
End |
||||
|
Begin VB.TextBox Text |
||||
|
Height = 300 |
||||
|
Index = 0 |
||||
|
Left = 0 |
||||
|
TabIndex = 0 |
||||
|
Top = 0 |
||||
|
Visible = 0 'False |
||||
|
Width = 300 |
||||
|
End |
||||
|
End |
||||
|
Attribute VB_Name = "Form1" |
||||
|
Attribute VB_GlobalNameSpace = False |
||||
|
Attribute VB_Creatable = False |
||||
|
Attribute VB_PredeclaredId = True |
||||
|
Attribute VB_Exposed = False |
||||
|
Option Explicit |
||||
|
Dim Start_X, Start_Y, Square_Length, Distance As Integer |
||||
|
Private Sub Init_Object() |
||||
|
Cls |
||||
|
Dim x, y, i |
||||
|
For x = 1 To 9 |
||||
|
For y = 1 To 9 |
||||
|
i = x + y * 9 - 9 |
||||
|
Text(i).Text = "" |
||||
|
Text(i).FontSize = 40 |
||||
|
Text(i).MaxLength = 1 |
||||
|
Text(i).Width = Square_Length |
||||
|
Text(i).Height = Square_Length |
||||
|
Text(i).Left = Start_X + Distance * (x - 0.5) + Square_Length * (x - 1) |
||||
|
Text(i).Top = Start_Y + Distance * (y - 0.5) + Square_Length * (y - 1) |
||||
|
Next y |
||||
|
Next x |
||||
|
For i = 0 To 9 |
||||
|
If Int(i / 3) = i / 3 Then DrawWidth = 3 Else DrawWidth = 1 |
||||
|
Line (Start_X, Start_Y + (Square_Length + Distance) * i)-(Start_X + (Square_Length + Distance) * 9, Start_Y + (Square_Length + Distance) * i) |
||||
|
Line (Start_X + (Square_Length + Distance) * i, Start_Y)-(Start_X + (Square_Length + Distance) * i, Start_Y + (Square_Length + Distance) * 9) |
||||
|
Next i |
||||
|
End Sub |
||||
|
Private Sub Form_Activate() |
||||
|
Text(1).SetFocus |
||||
|
End Sub |
||||
|
Private Sub Form_Load() |
||||
|
Dim i As Integer |
||||
|
For i = 1 To 81 |
||||
|
Load Text(i) |
||||
|
Text(i).Left = 0 |
||||
|
Text(i).Alignment = 2 |
||||
|
Text(i).Appearance = 0 |
||||
|
Text(i).BackColor = Form1.BackColor |
||||
|
Text(i).BorderStyle = 0 |
||||
|
Text(i).FontSize = 40 |
||||
|
Text(i).MaxLength = 1 |
||||
|
Text(i).Visible = True |
||||
|
Next i |
||||
|
Start_X = 300: Start_Y = 300 |
||||
|
Square_Length = 800 |
||||
|
Distance = 100 |
||||
|
Call Init_Object |
||||
|
End Sub |
||||
|
Private Sub Command2_Click() |
||||
|
On Error Resume Next |
||||
|
Dim i As Integer, dat As String |
||||
|
If Dir(App.Path & "\temp") = "" Then |
||||
|
MsgBox "No Saved File" |
||||
|
Exit Sub |
||||
|
End If |
||||
|
For i = 1 To 81 |
||||
|
Text(i).Text = "" |
||||
|
Next i |
||||
|
Open App.Path & "\temp" For Input As #1 |
||||
|
Line Input #1, dat |
||||
|
For i = 1 To 81 |
||||
|
If Mid(dat, i, 1) <> "0" Then Text(i).Text = Mid(dat, i, 1) |
||||
|
Next i |
||||
|
Close #1 |
||||
|
End Sub |
||||
|
Private Sub Command3_Click() |
||||
|
On Error Resume Next |
||||
|
Dim i As Integer |
||||
|
Open App.Path & "\temp" For Output As #1 |
||||
|
For i = 1 To 81 |
||||
|
Print #1, Trim(Val(Text(i).Text)); |
||||
|
Next i |
||||
|
Close #1 |
||||
|
If Dir(App.Path & "\temp") <> "" Then |
||||
|
MsgBox "Saved Successfully" |
||||
|
Else |
||||
|
MsgBox "Failed Save" |
||||
|
End If |
||||
|
End Sub |
||||
|
Private Sub Command4_Click() |
||||
|
Dim i As Integer |
||||
|
If MsgBox("Are you sure ?", vbQuestion + vbYesNo, "Tips") = vbYes Then |
||||
|
For i = 1 To 81 |
||||
|
Text(i).Text = "" |
||||
|
Next i |
||||
|
End If |
||||
|
End Sub |
||||
|
Private Sub Command1_Click() |
||||
|
On Error Resume Next |
||||
|
Dim i As Integer |
||||
|
Open App.Path & "\Data_Input.txt" For Output As #1 |
||||
|
For i = 1 To 81 |
||||
|
Print #1, Trim(Val(Text(i).Text)); |
||||
|
Next i |
||||
|
Close #1 |
||||
|
Kill App.Path & "\Compete" |
||||
|
If Dir(App.Path & "\Sudoku_Engine.exe") = "" Then |
||||
|
MsgBox "Sudoku Engine not Found", vbCritical |
||||
|
Exit Sub |
||||
|
Else |
||||
|
Shell App.Path & "\Sudoku_Engine.exe" |
||||
|
End If |
||||
|
Form2.Timer1.Enabled = True |
||||
|
Form2.Show 1 |
||||
|
End Sub |
||||
|
Private Sub Form_Unload(Cancel As Integer) |
||||
|
On Error Resume Next |
||||
|
Kill App.Path & "\Compete" |
||||
|
End Sub |
@ -0,0 +1,74 @@ |
|||||
|
VERSION 5.00 |
||||
|
Begin VB.Form Form2 |
||||
|
BorderStyle = 0 'None |
||||
|
Caption = "Please Wait..." |
||||
|
ClientHeight = 660 |
||||
|
ClientLeft = 0 |
||||
|
ClientTop = 0 |
||||
|
ClientWidth = 3240 |
||||
|
LinkTopic = "Form2" |
||||
|
MaxButton = 0 'False |
||||
|
MinButton = 0 'False |
||||
|
ScaleHeight = 660 |
||||
|
ScaleWidth = 3240 |
||||
|
ShowInTaskbar = 0 'False |
||||
|
StartUpPosition = 2 'ÆÁÄ»ÖÐÐÄ |
||||
|
Begin VB.Timer Timer1 |
||||
|
Interval = 300 |
||||
|
Left = 0 |
||||
|
Top = 0 |
||||
|
End |
||||
|
Begin VB.Label Label1 |
||||
|
AutoSize = -1 'True |
||||
|
Caption = "Please Wait..." |
||||
|
BeginProperty Font |
||||
|
Name = "ËÎÌå" |
||||
|
Size = 26.25 |
||||
|
Charset = 134 |
||||
|
Weight = 400 |
||||
|
Underline = 0 'False |
||||
|
Italic = 0 'False |
||||
|
Strikethrough = 0 'False |
||||
|
EndProperty |
||||
|
Height = 690 |
||||
|
Left = 0 |
||||
|
TabIndex = 0 |
||||
|
ToolTipText = "Double Click to Exit..." |
||||
|
Top = 0 |
||||
|
Width = 3240 |
||||
|
End |
||||
|
End |
||||
|
Attribute VB_Name = "Form2" |
||||
|
Attribute VB_GlobalNameSpace = False |
||||
|
Attribute VB_Creatable = False |
||||
|
Attribute VB_PredeclaredId = True |
||||
|
Attribute VB_Exposed = False |
||||
|
Private Sub Form_DblClick() |
||||
|
If MsgBox("Are you sure to exit?", vbQuestion + vbOKCancel, "Tips") = vbOK Then |
||||
|
Shell "taskkill /f /im Sudoku_Engine.exe" |
||||
|
Timer1.Enabled = False |
||||
|
Form2.Hide |
||||
|
End If |
||||
|
End Sub |
||||
|
Private Sub Label1_DblClick() |
||||
|
Call Form_DblClick |
||||
|
End Sub |
||||
|
Private Sub Timer1_Timer() |
||||
|
On Error Resume Next |
||||
|
If Dir(App.Path & "\Compete") <> "" Then |
||||
|
Open App.Path & "\Compete" For Input As #1 |
||||
|
Line Input #1, dat |
||||
|
If Trim(dat) = "Error!!!" Then |
||||
|
MsgBox "Error or No-Solution", vbCritical |
||||
|
Timer1.Enabled = False |
||||
|
Form2.Hide |
||||
|
Close #1 |
||||
|
Exit Sub |
||||
|
End If |
||||
|
Close #1 |
||||
|
Timer1.Enabled = False |
||||
|
Form1.Visible = False |
||||
|
Form2.Hide |
||||
|
Form3.Show |
||||
|
End If |
||||
|
End Sub |
@ -0,0 +1,165 @@ |
|||||
|
VERSION 5.00 |
||||
|
Begin VB.Form Form3 |
||||
|
AutoRedraw = -1 'True |
||||
|
BorderStyle = 1 'Fixed Single |
||||
|
Caption = "Sudoku Displayer" |
||||
|
ClientHeight = 8985 |
||||
|
ClientLeft = 45 |
||||
|
ClientTop = 375 |
||||
|
ClientWidth = 8730 |
||||
|
LinkTopic = "Form3" |
||||
|
MaxButton = 0 'False |
||||
|
MinButton = 0 'False |
||||
|
ScaleHeight = 8985 |
||||
|
ScaleWidth = 8730 |
||||
|
StartUpPosition = 2 'ÆÁÄ»ÖÐÐÄ |
||||
|
Begin VB.CommandButton Command3 |
||||
|
Caption = "-" |
||||
|
Height = 375 |
||||
|
Left = 3600 |
||||
|
TabIndex = 3 |
||||
|
Top = 8520 |
||||
|
Width = 1455 |
||||
|
End |
||||
|
Begin VB.CommandButton Command2 |
||||
|
Caption = ">" |
||||
|
Height = 375 |
||||
|
Left = 5160 |
||||
|
TabIndex = 0 |
||||
|
Top = 8520 |
||||
|
Width = 3015 |
||||
|
End |
||||
|
Begin VB.CommandButton Command1 |
||||
|
Caption = "<" |
||||
|
Height = 375 |
||||
|
Left = 480 |
||||
|
TabIndex = 2 |
||||
|
ToolTipText = "Try to Press A or D..." |
||||
|
Top = 8520 |
||||
|
Width = 3015 |
||||
|
End |
||||
|
Begin VB.Timer Timer1 |
||||
|
Interval = 5000 |
||||
|
Left = 0 |
||||
|
Top = 0 |
||||
|
End |
||||
|
Begin VB.TextBox Text |
||||
|
Height = 300 |
||||
|
Index = 0 |
||||
|
Left = 0 |
||||
|
TabIndex = 1 |
||||
|
Top = 0 |
||||
|
Visible = 0 'False |
||||
|
Width = 300 |
||||
|
End |
||||
|
End |
||||
|
Attribute VB_Name = "Form3" |
||||
|
Attribute VB_GlobalNameSpace = False |
||||
|
Attribute VB_Creatable = False |
||||
|
Attribute VB_PredeclaredId = True |
||||
|
Attribute VB_Exposed = False |
||||
|
Dim Input_Data() As String |
||||
|
Dim Start_X, Start_Y, Square_Length, Distance As Integer |
||||
|
Dim use As Long |
||||
|
Private Sub Init_Object() |
||||
|
On Error Resume Next |
||||
|
Cls |
||||
|
For x = 1 To 9 |
||||
|
For y = 1 To 9 |
||||
|
i = x + y * 9 - 9 |
||||
|
Text(i).Text = "" |
||||
|
Text(i).FontSize = 40 |
||||
|
Text(i).MaxLength = 1 |
||||
|
Text(i).Width = Square_Length |
||||
|
Text(i).Height = Square_Length |
||||
|
Text(i).Left = Start_X + Distance * (x - 0.5) + Square_Length * (x - 1) |
||||
|
Text(i).Top = Start_Y + Distance * (y - 0.5) + Square_Length * (y - 1) |
||||
|
Next y |
||||
|
Next x |
||||
|
For i = 0 To 9 |
||||
|
If Int(i / 3) = i / 3 Then DrawWidth = 3 Else DrawWidth = 1 |
||||
|
Line (Start_X, Start_Y + (Square_Length + Distance) * i)-(Start_X + (Square_Length + Distance) * 9, Start_Y + (Square_Length + Distance) * i) |
||||
|
Line (Start_X + (Square_Length + Distance) * i, Start_Y)-(Start_X + (Square_Length + Distance) * i, Start_Y + (Square_Length + Distance) * 9) |
||||
|
Next i |
||||
|
End Sub |
||||
|
Private Sub Form_Load() |
||||
|
On Error Resume Next |
||||
|
For i = 1 To 81 |
||||
|
Load Text(i) |
||||
|
Text(i).Left = 0 |
||||
|
Text(i).Alignment = 2 |
||||
|
Text(i).Appearance = 0 |
||||
|
Text(i).BackColor = Form3.BackColor |
||||
|
Text(i).BorderStyle = 0 |
||||
|
Text(i).FontSize = 40 |
||||
|
Text(i).MaxLength = 1 |
||||
|
Text(i).Locked = True |
||||
|
Text(i).Visible = True |
||||
|
Next i |
||||
|
Start_X = 300: Start_Y = 300 |
||||
|
Square_Length = 800 |
||||
|
Distance = 100 |
||||
|
Call Init_Object |
||||
|
Call Data_Input |
||||
|
Call Data_Output(0) |
||||
|
use = 0 |
||||
|
End Sub |
||||
|
Private Sub Data_Input() |
||||
|
Open App.Path & "\Data_Input.txt" For Input As #1 |
||||
|
Line Input #1, dat |
||||
|
For i = 1 To 81 |
||||
|
If Mid(dat, i, 1) <> "0" Then Text(i).ForeColor = vbRed |
||||
|
Next i |
||||
|
Close #1 |
||||
|
Open App.Path & "\Data_Output.txt" For Input As #1 |
||||
|
ReDim Input_Data(0) |
||||
|
Do While Not EOF(1) |
||||
|
Line Input #1, Input_Data(UBound(Input_Data)) |
||||
|
ReDim Preserve Input_Data(UBound(Input_Data) + 1) |
||||
|
Loop |
||||
|
Close #1 |
||||
|
End Sub |
||||
|
Private Sub Data_Output(Num As Long) |
||||
|
dat = Input_Data(Num) |
||||
|
Form3.Caption = "Sudoku Displayer(" & Trim(Num + 1) & "/" & Trim(UBound(Input_Data)) & ")" |
||||
|
Call Init_Object |
||||
|
For i = 1 To 81 |
||||
|
Text(i).FontSize = 40 |
||||
|
Text(i).MaxLength = 1 |
||||
|
a = Mid(dat, i, 1) |
||||
|
If a = "0" Then a = "" |
||||
|
Text(i).Text = a |
||||
|
Next i |
||||
|
End Sub |
||||
|
Private Sub Command1_Click() |
||||
|
If use > 0 Then use = use - 1 |
||||
|
Call Data_Output(use) |
||||
|
End Sub |
||||
|
Private Sub Command2_Click() |
||||
|
If use < UBound(Input_Data) - 1 Then use = use + 1 |
||||
|
Call Data_Output(use) |
||||
|
End Sub |
||||
|
Private Sub Command3_Click() |
||||
|
On Error Resume Next |
||||
|
dat = Int(InputBox("Please input a number", "Tips")) - 1 |
||||
|
If dat >= 0 And dat < UBound(Input_Data) Then use = dat: Data_Output (use) |
||||
|
End Sub |
||||
|
Private Sub Command1_KeyPress(KeyAscii As Integer) |
||||
|
If KeyAscii = 97 Then Call Command1_Click |
||||
|
If KeyAscii = 100 Then Call Command2_Click |
||||
|
End Sub |
||||
|
Private Sub Command2_KeyPress(KeyAscii As Integer) |
||||
|
If KeyAscii = 97 Then Call Command1_Click |
||||
|
If KeyAscii = 100 Then Call Command2_Click |
||||
|
End Sub |
||||
|
Private Sub Command3_KeyPress(KeyAscii As Integer) |
||||
|
If KeyAscii = 97 Then Call Command1_Click |
||||
|
If KeyAscii = 100 Then Call Command2_Click |
||||
|
End Sub |
||||
|
Private Sub Form_DblClick() |
||||
|
Call Data_Input |
||||
|
Call Data_Output(use) |
||||
|
End Sub |
||||
|
Private Sub Form_Unload(Cancel As Integer) |
||||
|
Form1.Visible = True |
||||
|
End Sub |
@ -0,0 +1,36 @@ |
|||||
|
Type=Exe |
||||
|
Form=Form1.frm |
||||
|
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation |
||||
|
Form=Form2.frm |
||||
|
Form=Form3.frm |
||||
|
IconForm="Form1" |
||||
|
Startup="Form1" |
||||
|
HelpFile="" |
||||
|
Title="Sudoku" |
||||
|
ExeName32="Sudoku.exe" |
||||
|
Command32="" |
||||
|
Name="Sudoku" |
||||
|
HelpContextID="0" |
||||
|
CompatibleMode="0" |
||||
|
MajorVer=1 |
||||
|
MinorVer=0 |
||||
|
RevisionVer=0 |
||||
|
AutoIncrementVer=0 |
||||
|
ServerSupportFiles=0 |
||||
|
VersionCompanyName="Dnomd343" |
||||
|
VersionProductName="Sudoku Calculator" |
||||
|
CompilationType=0 |
||||
|
OptimizationType=0 |
||||
|
FavorPentiumPro(tm)=0 |
||||
|
CodeViewDebugInfo=0 |
||||
|
NoAliasing=0 |
||||
|
BoundsCheck=0 |
||||
|
OverflowCheck=0 |
||||
|
FlPointCheck=0 |
||||
|
FDIVCheck=0 |
||||
|
UnroundedFP=0 |
||||
|
StartMode=0 |
||||
|
Unattended=0 |
||||
|
Retained=0 |
||||
|
ThreadPerObject=0 |
||||
|
MaxNumberOfThreads=1 |
@ -0,0 +1,235 @@ |
|||||
|
#include<iostream> |
||||
|
#include<vector> |
||||
|
#include<fstream> |
||||
|
using namespace std; |
||||
|
ifstream File_Input; |
||||
|
ofstream File_Output; |
||||
|
|
||||
|
struct Sudoku_Class{ //一个宫格的内容
|
||||
|
unsigned char Data; //数字1~9,0表示未完成
|
||||
|
bool May[9]; //假设数
|
||||
|
}; |
||||
|
struct Try_Point_Class{ //假设链上的节点
|
||||
|
unsigned char Block_Num; //被假设的宫格编号
|
||||
|
unsigned char Point_Num; //当前正在被假设的Item编号
|
||||
|
vector <unsigned char> Item; //节点中的所有假设数
|
||||
|
}; |
||||
|
|
||||
|
struct Sudoku_Class Base[81]; //全部81个宫格
|
||||
|
struct Sudoku_Class Backup[81]; //进行假设的时候暂存使用
|
||||
|
unsigned char Addr_Kind[3][9][9]; //行列宫对应的位置表
|
||||
|
unsigned char Addr_Block[81][3]; //宫格所在行列宫的编号
|
||||
|
vector <struct Try_Point_Class> Try; //假设链
|
||||
|
struct Try_Point_Class Empty_Point; //空的假设节点
|
||||
|
|
||||
|
void Init(); |
||||
|
void Analyse(); |
||||
|
void Engine(); |
||||
|
bool Check_Compete(); |
||||
|
bool Check_Error(); |
||||
|
void Create_New_Point(); |
||||
|
void Solve_Output(); |
||||
|
bool Try_Next(); |
||||
|
bool Data_Input(); |
||||
|
unsigned int Calculate(); |
||||
|
unsigned char Next_Empty_Block(unsigned char Start); |
||||
|
void Init_Point(unsigned char Block_Num,unsigned char Point_Num); |
||||
|
|
||||
|
int main(){ |
||||
|
cout<<"Welcome to Sudoku-Calculator by Dnomd343"<<endl; |
||||
|
cout<<"Please wait..."<<endl; |
||||
|
Init(); |
||||
|
if(Data_Input()==false){cout<<"Something Wrong!"<<endl;return 0;} |
||||
|
unsigned int i; |
||||
|
i=Calculate(); |
||||
|
cout<<"Calculate Compete"<<endl; |
||||
|
File_Output.open("Compete"); |
||||
|
if(i==0){File_Output<<"Error!!!"<<endl;} |
||||
|
File_Output.close(); |
||||
|
return 0; |
||||
|
} |
||||
|
bool Data_Input(){ |
||||
|
unsigned char i; |
||||
|
char dat[81]; |
||||
|
File_Input.open("Data_Input.txt"); |
||||
|
File_Input>>dat; |
||||
|
File_Input.close(); |
||||
|
for(i=0;i<=80;i++){ |
||||
|
Base[i].Data=dat[i]-48; |
||||
|
if(Base[i].Data>9){return false;} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
void Solve_Output(){ |
||||
|
unsigned char i; |
||||
|
char Data[82]; |
||||
|
for(i=0;i<=80;i++){ |
||||
|
Data[i]=Base[i].Data+48; |
||||
|
} |
||||
|
Data[81]=0; |
||||
|
File_Output<<Data<<endl; |
||||
|
} |
||||
|
unsigned int Calculate(){ //主计算函数
|
||||
|
unsigned char i; |
||||
|
int Solve_Num=0; |
||||
|
File_Output.open("Data_Output.txt"); |
||||
|
Engine(); //初步排除运算
|
||||
|
if(Check_Error()==true){File_Output.close();return 0;} //输入的数独有误
|
||||
|
if(Check_Compete()==true){Solve_Output();File_Output.close();return 1;} //输入的数独已完成
|
||||
|
for(i=0;i<=80;i++){Backup[i]=Base[i];} //备份数据 假设时暂存
|
||||
|
Create_New_Point(); //创建假设链根节点
|
||||
|
while(1){ |
||||
|
for(i=0;i<=(Try.size()-1);i++){ //装载假设链
|
||||
|
Base[Try[i].Block_Num].Data=Try[i].Item[Try[i].Point_Num]; |
||||
|
} |
||||
|
Engine(); //进行排除运算
|
||||
|
if(Check_Error()==true){ //当前假设错误
|
||||
|
if(Try_Next()==false){break;} //没有下一个假设,则该数独无解,退出
|
||||
|
} |
||||
|
else{ //当前假设可能正确
|
||||
|
if(Check_Compete()==false){ //若仍未完成,则创建新的假设节点
|
||||
|
Create_New_Point(); |
||||
|
} |
||||
|
else{ //已完成
|
||||
|
Solve_Output(); |
||||
|
Solve_Num++; //答案数目+1
|
||||
|
if(Try_Next()==false){break;} //没有下一个假设,求解完成,退出
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
File_Output.close(); |
||||
|
return Solve_Num; |
||||
|
} |
||||
|
bool Try_Next(){ //当前假设错误,装载下一个假设
|
||||
|
unsigned char i; |
||||
|
while((Try[Try.size()-1].Point_Num>=(Try[Try.size()-1].Item.size()-1))){ |
||||
|
if(Try.size()==1){return false;} |
||||
|
Try.resize(Try.size()-1); |
||||
|
} |
||||
|
Try[Try.size()-1].Point_Num++; //假设链末节点指向下一个Item
|
||||
|
for(i=0;i<=80;i++){ //将备份数据重新装载
|
||||
|
Base[i]=Backup[i]; |
||||
|
} |
||||
|
return true; //成功
|
||||
|
} |
||||
|
void Create_New_Point(){ //创建新的假设链节点
|
||||
|
Try.push_back(Empty_Point); |
||||
|
if(Try.size()==1){ //若为根节点
|
||||
|
Init_Point(Next_Empty_Block(0),0); //从第一格开始搜索未完成宫格
|
||||
|
} |
||||
|
else{ //若不是根节点
|
||||
|
Init_Point(Next_Empty_Block(Try[Try.size()-2].Block_Num+1),Try.size()-1); //从上一节点指向的宫格开始搜索未完成宫格
|
||||
|
} |
||||
|
} |
||||
|
void Init_Point(unsigned char Block_Num,unsigned char Point_Num){ //初始化假设链节点 Block_Num->被假设宫格的编号 Point_Num->节点的编号
|
||||
|
unsigned char i; |
||||
|
Try[Point_Num].Block_Num=Block_Num; |
||||
|
for(i=0;i<=8;i++){ |
||||
|
if(Base[Try[Point_Num].Block_Num].May[i]==true){ //遍历目标宫格的所有假设数并加入到该节点的Item中
|
||||
|
Try[Point_Num].Item.push_back(i+1); |
||||
|
} |
||||
|
} |
||||
|
Try[Point_Num].Point_Num=0; //指向Item中的第一个假设数
|
||||
|
} |
||||
|
unsigned char Next_Empty_Block(unsigned char Start){ //找到下一个未确定答案的宫格并返回其编号
|
||||
|
unsigned char i; |
||||
|
for(i=Start;i<=80;i++){ |
||||
|
if(Base[i].Data==0){return i;} |
||||
|
} |
||||
|
return 0; //没有未确定宫格
|
||||
|
} |
||||
|
bool Check_Error(){ //检查数独是否存在错误
|
||||
|
unsigned char kind,num,add,item; |
||||
|
for(kind=0;kind<=2;kind++){ //分别扫描行列宫
|
||||
|
for(num=0;num<=8;num++){ |
||||
|
for(item=1;item<=9;item++){ |
||||
|
add=0; |
||||
|
for(unsigned char k=0;k<=8;k++){ |
||||
|
if(Base[Addr_Kind[kind][num][k]].Data==item){add++;} |
||||
|
} |
||||
|
if(add>=2){return true;} //若一组行列宫中存在两个相同的数 -> 错误退出
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
for(num=0;num<=80;num++){ //扫描全部宫格
|
||||
|
if(Base[num].Data==0){ //若未完成
|
||||
|
add=0; |
||||
|
for(unsigned char k=0;k<=8;k++){ //遍历其所有假设数
|
||||
|
if(Base[num].May[k]==true){add++;} |
||||
|
} |
||||
|
if(add==0){return true;} //没有可能的数 -> 错误退出
|
||||
|
} |
||||
|
} |
||||
|
return false; //暂时未发现错误
|
||||
|
} |
||||
|
bool Check_Compete(){ //判断数独是否完成
|
||||
|
unsigned char i; |
||||
|
for(i=0;i<=80;i++){ |
||||
|
if(Base[i].Data==0){return false;} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
void Engine(){ //使用排除法
|
||||
|
unsigned char kind,num,item,add,dat; |
||||
|
bool Could_Solve; |
||||
|
Again:; |
||||
|
Analyse(); //每次排除前应先消去假设数
|
||||
|
Could_Solve=false; |
||||
|
for(kind=0;kind<=2;kind++){ //分别扫描行列宫
|
||||
|
for(num=0;num<=8;num++){ |
||||
|
for(item=0;item<=8;item++){ |
||||
|
add=0; |
||||
|
for(unsigned char k=0;k<=8;k++){ |
||||
|
if((Base[Addr_Kind[kind][num][k]].Data==0)&&(Base[Addr_Kind[kind][num][k]].May[item]==true)){add++;dat=k;} //记录一组行列宫中的可能数
|
||||
|
} |
||||
|
if(add==1){Base[Addr_Kind[kind][num][dat]].Data=item+1;Could_Solve=true;} //若仅有唯一可能数,则该宫格答案确定
|
||||
|
} |
||||
|
} |
||||
|
if(Could_Solve==true){goto Again;} //一直循环直到没有排除对象
|
||||
|
} |
||||
|
} |
||||
|
void Analyse(){ //消去假设数
|
||||
|
unsigned char num,kind,item; |
||||
|
for(num=0;num<=80;num++){ //遍历所有宫格
|
||||
|
if(Base[num].Data!=0){ //若该宫格已完成
|
||||
|
for(kind=0;kind<=2;kind++){ //分别对行列宫操作
|
||||
|
for(item=0;item<=8;item++){ |
||||
|
Base[Addr_Kind[kind][Addr_Block[num][kind]][item]].May[Base[num].Data-1]=false; //消去同行同列同宫的假设数
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
void Init(){ //初始化容器
|
||||
|
unsigned char i,j,x,y; |
||||
|
for(i=0;i<=8;i++){ //初始化行与列的位置表
|
||||
|
for(j=0;j<=8;j++){ |
||||
|
Addr_Kind[0][i][j]=i*9+j; |
||||
|
Addr_Kind[1][i][j]=j*9+i; |
||||
|
} |
||||
|
} |
||||
|
for(x=0;x<=2;x++){ //初始化九宫格的位置表
|
||||
|
for(y=0;y<=2;y++){ |
||||
|
for(i=0;i<=2;i++){ |
||||
|
for(j=0;j<=2;j++){ |
||||
|
Addr_Kind[2][y*3+x][j*3+i]=(y*3+j)*9+(x*3+i); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
for(i=0;i<=2;i++){ //初始化宫格所在行列宫的编号
|
||||
|
for(x=0;x<=8;x++){ |
||||
|
for(y=0;y<=8;y++){ |
||||
|
Addr_Block[Addr_Kind[i][x][y]][i]=x; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
for(i=0;i<=80;i++){ //清空所有假设数
|
||||
|
for(j=0;j<=8;j++){ |
||||
|
Base[i].May[j]=true; |
||||
|
} |
||||
|
} |
||||
|
for(i=0;i<=80;i++){ //清空所有数字
|
||||
|
Base[i].Data=0; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue