Beruflich Dokumente
Kultur Dokumente
n = 0
FoundAt = 0
For Index = 1 To ncINDEXLEN
If Squares(Index).nRow = nRow Then
If Squares(Index).Possibles(ThisValue) > 0 Then
n = n + 1
FoundAt = Index
End If
End If
Next
PossiblesInRow = n
End Function
Public Function PossiblesInCol(ThisValue As Integer, nCol As Integer, ByRef Foun
dAt As Integer)
' Returns no of possibles for This Value in this col
' And sets FoundAt to be the index where we last found a possible for this value
Dim Index As Integer
Dim n As Integer
n = 0
FoundAt = 0
For Index = 1 To ncINDEXLEN
If Squares(Index).nCol = nCol Then
If Squares(Index).Possibles(ThisValue) > 0 Then
n = n + 1
FoundAt = Index
End If
End If
Next
PossiblesInCol = n
End Function
Public Function MissingValues() As Integer
' Returns number of squares not set. If zero we have a full solution.
Dim Index As Integer
Dim n As Integer
n = 0
For Index = 1 To ncINDEXLEN
If Squares(Index).Value = 0 Then
n = n + 1
End If
Next
MissingValues = n
End Function
Public Function SetKnownValues() As Boolean
' See if simple elimination of possibles yields us any solutions
' Returns True if made a change or False if no change on this pass
Dim Index As Integer
Dim iValue As Integer
Dim bChanged As Boolean
bChanged = False
For Index = 1 To ncINDEXLEN
If CountPossibles(Index) = 1 And Squares(Index).Value = 0 Then
' Found another answer
iValue = ThePossible(Index)
Debug.Print "Found Value(" & GetRow(Index) & "," & GetCol(Index) & "
)=" & iValue
' Set the value (and remove more possibles)
Call SetSquare(iValue, Index)
bChanged = True
End If
Next
Debug.Print "SetKnownValues: " & IIf(bChanged, "FOUND MORE...", "NO CHANGES
this round")
SetKnownValues = bChanged
End Function
Public Function CountPossibles(Index As Integer) As Integer
' Count no of values that are possible for this square
' If one, we have the solution
' If zero, we have an error
Dim i As Integer
Dim n As Integer
n = 0
For i = 1 To ncSIZE
n = n + Squares(Index).Possibles(i)
Next
CountPossibles = n
End Function
Public Function ThePossible(Index As Integer) As Integer
' Assumes only one possible value
Dim i As Integer
For i = 1 To ncSIZE
If Squares(Index).Possibles(i) = 1 Then
ThePossible = i
Exit For
End If
Next
End Function
Public Function TheNthPossible(Index As Integer, n_th As Integer) As Integer
' Finds the nth possible value for this square (1-based)
Dim i As Integer
Dim nValue As Integer
Dim n As Integer
n = n_th
For i = 1 To ncSIZE
If Squares(Index).Possibles(i) = 1 Then
n = n - 1
If n = 0 Then
nValue = i
Exit For
End If
End If
Next
TheNthPossible = nValue
End Function
Public Function IsDataOK() As Integer
' Returns zero if data is OK, else index of first error
Dim Index As Integer
IsDataOK = 0 ' Innocent until proven guilty
For Index = 1 To ncINDEXLEN
If Squares(Index).Value > ncSIZE Or Squares(Index).Value < 0 Or CountPos
sibles(Index) <= 0 Then
IsDataOK = Index
Exit For
End If
Next
End Function
Public Function SetSquare(iValue As Integer, ThisIndex As Integer) As Boolean
' Set the square value and eliminate all possibles in same row, col and box
Dim i As Integer
Squares(ThisIndex).Value = iValue
Squares(ThisIndex).GuessLevel = mnGuessLevel
For i = 1 To ncINDEXLEN
If Squares(i).nRow = Squares(ThisIndex).nRow Then
Squares(i).Possibles(iValue) = 0
End If
If Squares(i).nCol = Squares(ThisIndex).nCol Then
Squares(i).Possibles(iValue) = 0
End If
If Squares(i).nBox = Squares(ThisIndex).nBox Then
Squares(i).Possibles(iValue) = 0
End If
Next
' And make sure this square's Possibles are set properly
For i = 1 To ncSIZE
Squares(ThisIndex).Possibles(i) = 0
Next
Squares(ThisIndex).Possibles(iValue) = 1
SetSquare = True
End Function
Public Function SetSquareRC(iValue As Integer, iRow As Integer, iCol As Integer,
Optional IsGiven As Boolean) As Boolean
' Set square value given (row,col). Optionally set the Given tag.
Dim Index As Integer
Index = GetIndex(iRow, iCol)
Squares(Index).Given = IsGiven
SetSquareRC = SetSquare(iValue, Index)
End Function
Public Function FillInResults()
Dim rng As Range
Dim iRow As Integer, iCol As Integer
Dim iValue As Integer
Dim Index As Integer
Set rng = Range("Puzzle")
For iRow = 1 To ncSIZE
For iCol = 1 To ncSIZE
Index = GetIndex(iRow, iCol)
If Squares(Index).Given Then
' Just reformat to show it was a given
rng(iRow, iCol).Interior.ColorIndex = 6
rng(iRow, iCol).Font.Bold = True
ElseIf Squares(Index).Value > 0 Then
' Found a solution
rng(iRow, iCol).Value = Squares(Index).Value
rng(iRow, iCol).Interior.ColorIndex = xlNone
rng(iRow, iCol).Font.Bold = False
End If
Next
Next
End Function
Public Function ClearGrid()
Dim rng As Range
Dim iRow As Integer, iCol As Integer
Dim iValue As Integer
Dim Index As Integer
Set rng = Range("Puzzle")
For iRow = 1 To ncSIZE
For iCol = 1 To ncSIZE
Index = GetIndex(iRow, iCol)
rng(iRow, iCol).Value = ""
rng(iRow, iCol).Interior.ColorIndex = xlNone
rng(iRow, iCol).Font.Bold = False
Next
Next
End Function
Public Function ReadInput() As Integer
' 0 if OK else index of square with problem
Dim rng As Range
Dim wkb As Workbook
Dim iRow As Integer, iCol As Integer
Dim iValue As Integer
Set wkb = ActiveWorkbook
Set rng = Range("Puzzle")
For iRow = 1 To ncSIZE
For iCol = 1 To ncSIZE
iValue = Val(rng.Item(iRow, iCol))
If iValue > 0 Then
' Store given value in array
If Not SetSquareRC(iValue, iRow, iCol, True) Then
MsgBox "Invalid input at (" & iRow & "," & iCol & ")!"
Exit Function
End If
End If
Next
Next
ReadInput = IsDataOK()
End Function
Public Function InitPuzzle()
' Initialise the Squares matrix
Dim iRow As Integer, iCol As Integer
Dim Index As Integer
Dim i As Integer
' Init all values
For Index = 1 To ncINDEXLEN
Squares(Index).Given = False
Squares(Index).GuessLevel = 0
Squares(Index).Value = 0
Next
For i = 1 To ncGUESSEDMAX
Guessed(i) = 0
Next
' Set all possibles to 1
For Index = 1 To ncINDEXLEN
For i = 1 To ncSIZE
Squares(Index).Possibles(i) = 1
Next
Next
' Set global guess level
mnGuessLevel = 0
mnDifficulty = 0
' Initialise the row, col and box numbers
' to speed up lookups
' (These could be done with constants, but this is easier)
' Stored row x column, base-1
For iCol = 1 To 9
For iRow = 1 To 9
Index = GetIndex(iRow, iCol)
Squares(Index).nRow = iRow
Squares(Index).nCol = iCol
Next
Next
' Set box numbers 1..9
' (there's surely a simpler algorithm but this works...)
For iRow = 1 To 3
For iCol = 1 To 3
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 1
Next
For iCol = 4 To 6
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 2
Next
For iCol = 7 To 9
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 3
Next
Next
For iRow = 4 To 6
For iCol = 1 To 3
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 4
Next
For iCol = 4 To 6
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 5
Next
For iCol = 7 To 9
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 6
Next
Next
For iRow = 7 To 9
For iCol = 1 To 3
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 7
Next
For iCol = 4 To 6
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 8
Next
For iCol = 7 To 9
Index = GetIndex(iRow, iCol)
Squares(Index).nBox = 9
Next
Next
End Function
Public Function GetIndex(iRow As Integer, iCol As Integer) As Integer
' Given (iRow, iCol) return value of index (1..81)
GetIndex = (iRow - 1) * ncSIZE + iCol
End Function
Public Function GetRow(iIndex As Integer) As Integer
GetRow = ((iIndex - 1) \ ncSIZE) + 1
End Function
Public Function GetCol(iIndex As Integer) As Integer
GetCol = ((iIndex - 1) Mod ncSIZE) + 1
End Function
Public Function GetBox(iIndex As Integer) As Integer
Dim nRow As Integer, nCol As Integer
Dim nBand As Integer
Dim nStack As Integer
nRow = GetRow(iIndex)
nCol = GetCol(iIndex)
nBand = (nRow - 1) \ 3 + 1
nStack = (nCol - 1) \ 3 + 1
GetBox = (nBand - 1) * 3 + nStack
End Function
Public Function InThisRow(TheValue As Integer, TheIndex As Integer) As Boolean
Dim Index As Integer
Dim nRow As Integer
InThisRow = False
nRow = GetRow(TheIndex)
For Index = 1 To ncINDEXLEN
If Squares(Index).nRow = nRow Then
If Squares(Index).Value = TheValue Then
InThisRow = True
Exit For
End If
End If
Next
End Function
Public Function InThisCol(TheValue As Integer, TheIndex As Integer) As Boolean
Dim Index As Integer
Dim nCol As Integer
InThisCol = False
nCol = GetCol(TheIndex)
For Index = 1 To ncINDEXLEN
If Squares(Index).nCol = nCol Then
If Squares(Index).Value = TheValue Then
InThisCol = True
Exit For
End If
End If
Next
End Function
Public Function InThisBox(TheValue As Integer, TheIndex As Integer) As Boolean
Dim Index As Integer
Dim nBox As Integer
InThisBox = False
nBox = GetBox(TheIndex)
For Index = 1 To ncINDEXLEN
If Squares(Index).nBox = nBox Then
If Squares(Index).Value = TheValue Then
InThisBox = True
Exit For
End If
End If
Next
End Function
Sub Button1_Click()
DoPuzzle
End Sub
Sub Button3_Click()
ClearGrid
End Sub