Jump to content

Su Do Ku


MattyD
 Share

Recommended Posts

Yeah, I know it's been done before but this is my attempt at the game.

The puzzles are pretty easy cause I didn't bother looking up a proper algorithm to determine which clues to keep. I was going to fix it after finishing the UI but lost interest and hit the pub instead :graduated:

anyway here is some code,

Matt

#include <guibutton.au3>
#include <guiconstants.au3>
GUICreate("", 510, 360)
GUISetState()
Global $Buttons[9][9], $Game, $Work[9][9], $mode[9][9], $focus[2]
Local $x, $y
For $i = 0 To 80
 $x = Int($i / 9)
 $y = Mod($i, 9)
 $mode[$x][$y] = "0              "
 If IsInt($x / 3) And IsInt($y / 3) Then GUICtrlCreateGraphic($x * 40, $y * 40, 120, 120, 0x00800000)
 $Buttons[$x][$y] = GUICtrlCreateButton("", $x * 40 + 1, $y * 40 + 1, 38, 38, 0x01)
 GUICtrlSetFont($Buttons[$x][$y], 20, -1, -1, "Courier New")
Next
Local $NewBoard = GUICtrlCreateButton("New Game {F5}", 380, 20, 110, 20)
GUICtrlCreateLabel("Arrows" & @TAB & "Move" & @CRLF & @CRLF & "1 - 9" & @TAB & "Enter number" & @CRLF & @CRLF & "0, Del" & @TAB & "Clear number" & @CRLF & @CRLF & _
 "Space" & @TAB & "Add note" & @CRLF & @CRLF _
, 380, 250, 110, 100)
Local $NavU, $NavD, $NavL, $NavR
$NavU = GUICtrlCreateDummy()
$NavD = GUICtrlCreateDummy()
$NavL = GUICtrlCreateDummy()
$NavR = GUICtrlCreateDummy()
Local $accel[17][2]
$accel[0][0] = "{f5}"
$accel[0][1] = $NewBoard
$accel[1][0] = "{left}"
$accel[1][1] = $NavL
$accel[2][0] = "{right}"
$accel[2][1] = $NavR
$accel[3][0] = "{up}"
$accel[3][1] = $NavU
$accel[4][0] = "{down}"
$accel[4][1] = $NavD
Global $NumDummies[10]
For $i = 0 To 9
 $NumDummies[$i] = GUICtrlCreateDummy()
 $accel[$i + 5][0] = String($i)
 $accel[$i + 5][1] = $NumDummies[$i]
Next
$accel[15][0] = "{bs}"
$accel[15][1] = $NumDummies[0]
$accel[16][0] = "{DEL}"
$accel[16][1] = $NumDummies[0]
GUISetAccelerators($accel)
Local $Game = _NewBoard()
_RmvNums()
while 1
 $Msg = GUIGetMsg()
 Switch $Msg
  Case -3
   exit
  Case $NewBoard
   $Game = _NewBoard()
   _RmvNums()
  Case $NavU
   _Nav("U")
  Case $NavD
   _Nav("D")
  Case $NavL
   _Nav("L")
  Case $NavR
   _Nav("R")
  Case $Buttons[0][0] To $Buttons[8][8]
   _Flip($Msg)
  Case $NumDummies[0] To $NumDummies[9]
   _Num($Msg)
 EndSwitch
WEnd

Func _NewBoard()
 Local $Array[9][9], $redo = 0
 Local $Numbers[9] = [1,2,3,4,5,6,7,8,9]
 Local $rnd
 Local $errorcnt
 For $x = 0 To 8
  For $y = 0 To 8
   GUICtrlSetColor($Buttons[$x][$y], 0)
   GUICtrlSetBkColor($buttons[$x][$y], 0xEEEEEE)
   $Work[$x][$y] = ""
   $mode[$x][$y] = "0                "
   For $i = 0 To $x - 1
    If $Array[$i][$y] Then $Numbers[$Array[$i][$y] - 1] = 0
   Next
   For $i = 0 To $y - 1
    If $Array[$x][$i] Then $Numbers[$Array[$x][$i] - 1] = 0
   Next
   For $i = Int($x / 3) * 3 To Int($x / 3) * 3 + 2
    For $j = Int($y / 3) * 3 To Int($y / 3) * 3 + 2
     If $i = $x And $j = $y Then
      ExitLoop 2
     EndIf
     If $Array[$i][$j] Then $Numbers[$Array[$i][$j] - 1] = 0
    Next
   Next
   $rnd = ""
   For $i = 0 To 8
    If $Numbers[$i] Then
     $rnd &= $Numbers[$i]
    EndIf
    $Numbers[$i] = $i + 1
   Next
   If $rnd Then
    $Array[$x][$y] = StringMid($rnd, Random(1, StringLen($rnd), 1), 1)
    If Not $Array[$x][$y] Then $Array[$x][$y] = $rnd
    GUICtrlSetData($Buttons[$x][$y], $Array[$x][$y])
   Else
    $errorcnt += 1
    If $errorcnt = 50 Then Return _NewBoard()
    $redo = Random(0, $y - 1, 1)
    If $Array[$x][$redo] Then
     $Numbers[$Array[$x][$redo] - 1] = 0
     For $i = $redo To $y
      $Array[$x][$i] = ""
      GUICtrlSetData($Buttons[$x][$i], $Array[$x][$i])
     Next
     $y = $redo -1
    Else
     Return _NewBoard()
    EndIf
   EndIf
  Next
 Next
 Return $Array
EndFunc
func _RmvNums()
 $Work = $Game
 Local $x, $y, $removed
 For $x = 0 To 8
  For $y = 0 To 8
   If $work[$x][$y] Then GUICtrlSetState($buttons[$x][$y], $GUI_ENABLE)
  Next
 Next
 For $x = 0 To 8
  For $y = 0 To 8
   If Not $work[$x][$y] Then ContinueLoop
   If _Test($work, $x, $y, 8) Then
    $work[$x][$y] = ""
    GUICtrlSetData($Buttons[$x][$y], "")
    $removed += 1
   EndIf
  Next
 Next
 For $x = 0 To 8
  For $y = 0 To 8
   If Not $work[$x][$y] Then ContinueLoop
   If _Test($work, $x, $y, 10) Then
    $work[$x][$y] = ""
    GUICtrlSetData($Buttons[$x][$y], "")
    $removed += 1
   EndIf
  Next
 Next
 GUICtrlSetState($Buttons[0][0], $GUI_FOCUS)
 _GUICtrlButton_SetFocus(GUICtrlGetHandle($Buttons[0][0]))
EndFunc
func _Nav($direction)
 Local $x, $y
 For $x = 0 To 8
  For $y = 0 To 8
   If _GUICtrlButton_GetFocus(GUICtrlGetHandle($Buttons[$x][$y])) Then
    If $direction = "U" Then
     $y -= 1
    ElseIf $direction = "D" Then
     $y += 1
    ElseIf $direction = "L" Then
     $x -= 1
    ElseIf $direction = "R" Then
     $x += 1
    EndIf
    If $y = -1 Then $y = 8
    If $y = 9 Then $y = 0
    If $x = -1 Then $x = 8
    If $x = 9 Then $x = 0
    While BitAND(GUICtrlGetState($Buttons[$x][$y]), $GUI_DISABLE)
     If $direction = "U" Then
      $y -= 1
     ElseIf $direction = "D" Then
      $y += 1
     ElseIf $direction = "L" Then
      $x -= 1
     ElseIf $direction = "R" Then
      $x += 1
     EndIf
     If $y = -1 Then $y = 8
     If $y = 9 Then $y = 0
     If $x = -1 Then $x = 8
     If $x = 9 Then $x = 0
    Wend
    GUICtrlSetState($Buttons[$x][$y], $GUI_FOCUS)
    _GUICtrlButton_SetFocus(GUICtrlGetHandle($Buttons[$x][$y]))
    $focus[0] = $x
    $focus[1] = $y
    Return
   EndIf
  Next
 Next
EndFunc
func _Num($num)
 For $i = 0 To 9
  If $num = $NumDummies[$i] Then $num = $i
 Next
 If Not $num Then $num = ""
 Local $x, $y
 For $x = 0 To 8
  For $y = 0 To 8
   If _GUICtrlButton_GetFocus(GUICtrlGetHandle($Buttons[$x][$y])) Then
    If StringLeft($mode[$x][$y], 1) = "0" Then
     If $Game[$x][$y] = String($num) Then
      $Work[$x][$y] = String($num)
      GUICtrlSetColor($Buttons[$x][$y], 0)
     ElseIf Not $Game[$x][$y] Then
      GUICtrlSetStyle($Buttons[$x][$y], 0)
     Else
      If $Work[$x][$y] Then Return
      GUICtrlSetColor($Buttons[$x][$y], 0xFF0000)
     EndIf
     GUICtrlSetState($Buttons[$x][$y], $GUI_FOCUS)
     _GUICtrlButton_SetFocus(GUICtrlGetHandle($Buttons[$x][$y]))
     $focus[0] = $x
     $focus[1] = $y
     GUICtrlSetData($Buttons[$x][$y], String($num))
     Return _CheckWin()
    Else
     If StringInStr(StringTrimLeft($mode[$x][$y], 1), $num) Then
      $mode[$x][$y] = StringLeft($mode[$x][$y], 1) & StringReplace(StringTrimLeft($mode[$x][$y], 1), String($num), " ")
     Else
      $mode[$x][$y] = StringLeft($mode[$x][$y], $num * 2 - 1) & $num & StringTrimLeft($mode[$x][$y], $num * 2)
     EndIf
     If $num = 0 Then $mode[$x][$y] = "1                 "
     Return GUICtrlSetData($Buttons[$x][$y], StringTrimLeft($mode[$x][$y], 1))
    EndIf
   EndIf
  Next
 Next
EndFunc
Func _Test($Array, $x, $y, $spreadLimit = 9)
 Local $Numbers[9] = [1,2,3,4,5,6,7,8,9], $Possibs
 local $spread
 For $i = 0 To 8
  If $Array[$i][$y] And $i <> $x Then $Numbers[$Array[$i][$y] - 1] = 0
 Next
 For $i = 0 To 8
  If $Array[$x][$i] And $i <> $y Then $Numbers[$Array[$x][$i] - 1] = 0
 Next
 For $i = Int($x / 3) * 3 To Int($x / 3) * 3 + 2
  For $j = Int($y / 3) * 3 To Int($y / 3) * 3 + 2
   If $i <> $x And $j <> $y Then
    If $Array[$i][$j] Then $Numbers[$Array[$i][$j] - 1] = 0
   EndIf
   If Not $Array[$i][$j] Then $spread += 1
   If $spread < 9 Then
    If Random(0, 8) > $spreadLimit - 1 Then Return 0
   EndIf
  Next
 Next
 $Possibs = ""
 For $i = 0 To 8
  If $Numbers[$i] Then
   $Possibs &= $Numbers[$i]
  EndIf
  $Numbers[$i] = $i + 1
 Next
 If StringLen($Possibs) = 1 Then Return $Possibs
EndFunc
Func _Flip($MSG)
 Local $x, $y
 For $x = 0 To 8
  For $y = 0 To 8
   If $MSG = $Buttons[$x][$y] Then ExitLoop 2
  Next
 Next
 If $focus[0] <> $x Or $focus[1] <> $y Then
  $focus[0] = $x
  $focus[1] = $y
  Return
 EndIf
 If StringLeft($mode[$x][$y], 1) = "0" Then
  If $work[$x][$y] Then Return
  $mode[$x][$y] = "1" & StringTrimLeft($mode[$x][$y], 1)
  GUICtrlSetFont($Buttons[$x][$y], 6, -1, -1, "Courier New")
  GUICtrlSetData($Buttons[$x][$y], StringTrimLeft($mode[$x][$y], 1))
  GUICtrlSetStyle($Buttons[$x][$y], 0x2000)
 Else
  $mode[$x][$y] = "0" & StringTrimLeft($mode[$x][$y], 1)
  GUICtrlSetFont($Buttons[$x][$y], 20, -1, -1, "Courier New")
  GUICtrlSetData($Buttons[$x][$y], $work[$x][$y])
  GUICtrlSetStyle($Buttons[$x][$y], 0x300)
  GUICtrlSetBkColor($buttons[$x][$y], 0xEEEEEE)
 EndIf
 $focus[0] = $x
 $focus[1] = $y
 GUICtrlSetState($Buttons[$x][$y], $GUI_FOCUS)
 _GUICtrlButton_SetFocus(GUICtrlGetHandle($Buttons[$x][$y]))
EndFunc
Func _CheckWin()
 For $x = 0 To 8
  For $y = 0 To 8
   If Not $work[$x][$y] Then Return
  Next
 Next
 Local $x, $y, $Words[6] = ["One Up! ", "Winner! ", "Solved! ", "Hooray! ", "You Won ", " ~ :) ~ "], $rnd
 Local $word = $Words[Random(0,5,1)]
 For $i = 0 To 8
  For $j = 0 To 8
   If Not $i And not $j Then $rnd = Random(0,1, 1)
   If $rnd Then
    $x = $i
    $y = $j
   Else
    $x = $j
    $y = $i
   EndIf
   GUICtrlSetData($Buttons[$x][$y], StringMid($word, Mod($x + $y, 8) + 1, 1))
   GUICtrlSetState($buttons[$y][$x], $GUI_ENABLE)
   GUICtrlSetColor($Buttons[$y][$x], Random(0, 0xffffff, 1))
   GUICtrlSetBkColor($Buttons[$x][$y], 0xffffff)
   Sleep(25)
  Next
 Next
 $Game = _NewBoard()
 _RmvNums()
EndFunc
Link to comment
Share on other sites

  • 2 weeks later...

Really? It was supposed to be intuitive... maybe I was off the mark with this one.

Edit: ahh.. an oversight. Only the numbers across the top work (my laptop doesn't have a numpad).

It can easilly be fixed but in the end there is probably no point.

Edited by MattyD
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...