16 puzzle game/autohotkey
AutoHotkey
16 Puzzle Game Gui with Solver <lang AutoHotkey>WW:= 44 Gui, font, S16 oHome := [], oLocation := [], oGrid := [], W := WW/2 IniRead, n, %A_ScriptFullPath%:Stream:$DATA, gridSize, gridSize, 4 loop % n**2
R := ((A_Index-1)//n) + 1 , C := Mod(A_Index-1, n) + 1 , oHome[A_Index] := {"R":R, "C":C}
- draw down arrows
x := WW loop % n {
Gui, add, button, x%x% y%W% w%WW% h%W% -TabStop garwBtn v%A_Index%_D, ? x := "+0"
}
- draw left and right arrows
cntr := 1 x := (n+1)*WW Loop % n {
R := A_Index Gui, add, button, xs-%W% y+0 w%W% h%WW% -TabStop garwBtn v%R%_R, ? loop % n ; draw oGrid Gui, add, button, x+0 yp w%WW% h%WW% -TabStop ggrdBtn v%R%_%A_Index%, % oGrid[R, A_Index]:=cntr++ Gui, add, button, x%x% yp w%W% h%WW% -TabStop garwBtn v%R%_L, ?
}
- darw up arrows
y := (n+1)*WW, x := "s" loop % n {
Gui, add, button, x%x% y%Y% w%WW% h%W% -TabStop garwBtn v%A_Index%_U, ? x := "+0"
} y := WW*(n+1) + W + 10 Gui, add, Button, % "xs y" Y " w" n * WW " h" W+10 " gShuffle", Shuffle Gui, add, Button, % "xs y+0 w" n * WW " h" W+10 " gReset", Reset Gui, add, Button, % "xs y+0 w" n * WW " h" W+10 " gSolve", Solve Gui, add, text,, Grid Size: Gui, add, Edit, x+5 w40 vN Center, % n Gui, add, button, x+0 w0 h0 hidden default gSubmit
- ~ Gui, +AlwaysOnTop
Gui, Show, % "w" (WW*(n+2)), 16 Puzzle SysGet, SM_CYCAPTION, 4 return
- ------------------------------
solve(lRow:=0){
global num := 0 slp := 500
; top row loop % n { num++ ToolTip, % "solving # " num, 0, 0 if (oHome[num, "R"] = oLocation[num, "R"]) && (oHome[num, "C"] = oLocation[num, "C"]) continue if (oHome[num, "R"] = oLocation[num, "R"]) && (oHome[num, "C"] <> oLocation[num, "C"]) && (num > 1) ; same row, different col Move(oLocation[num, "C"], "D") rowRev := false if (abs(oLocation[num, "C"] - oHome[num, "C"]) > n/2) rowRev := true if (oLocation[num, "C"] > oHome[num, "C"]) && !rowRev dir := "L" if (oLocation[num, "C"] > oHome[num, "C"]) && rowRev dir := "R" if (oLocation[num, "C"] < oHome[num, "C"]) && !rowRev dir := "R" if (oLocation[num, "C"] < oHome[num, "C"]) && rowRev dir := "L" while (oLocation[num, "C"] <> oHome[num, "C"]) Move(oLocation[num, "R"], dir) colRev := false if (abs(oLocation[num, "R"] - oHome[num, "R"]) > n/2) colRev := true
if (oLocation[num, "R"] > oHome[num, "R"]) && !colRev dir := "U" if (oLocation[num, "R"] > oHome[num, "R"]) && colRev dir := "D" if (oLocation[num, "R"] < oHome[num, "R"]) && !colRev dir := "D" if (oLocation[num, "R"] < oHome[num, "R"]) && colRev dir := "U" while (oLocation[num, "R"] <> oHome[num, "R"]) Move(oLocation[num, "C"], dir) update_buttons(oGrid) }
; general row loop % n**2 - 2*n { ;~ ToolTip % num num++ ToolTip, % "solving # " num, 0, 0 if (oLocation[num, "R"] = oHome[num, "R"]) && (oLocation[num, "C"] = oHome[num, "C"]) continue if (oLocation[num, "R"] = oHome[num, "R"]) && (oLocation[num, "C"] <> oHome[num, "C"]) ; same row, different col { c := oLocation[num, "C"] Move(oLocation[num, "C"], "D") Move(oLocation[num, "R"], "R") Move(c, "U") ; restore previous column } if (oLocation[num, "C"] = oHome[num, "C"]) Move(oLocation[num, "R"], "L") loop % oLocation[num, "R"] - oHome[num, "r"] Move(oHome[num, "C"], "D") while (oLocation[num, "C"] <> oHome[num, "C"]) Move(oLocation[num, "R"], "L") while (oLocation[num, "R"] <> oHome[num, "R"]) Move(oLocation[num, "C"], "U") update_buttons(oGrid) } update_buttons(oGrid) if lRow = 1 return lastRow() ToolTip
}
lastRow(){
global num++ loop % n-2 { num++ ToolTip, % "solving # " num, 0, 0 if (oLocation[num, "R"] <> n) { while (oLocation[num-1, "C"] <> n-1) Move(n, "R") loop % n - oLocation[num, "R"] Move(n, "D") Move(n, "L") Move(n, "U") continue } while (oLocation[num, "C"] <> n) && (oLocation[num, "R"] = n) Move(n, "R") Move(n, "D") while (oLocation[num-1, "C"] <> n-1) Move(n, "R") Move(n, "U") update_buttons(oGrid) } celln1 := n**2 - n + 1 while (oLocation[celln1, "C"] <> 1) Move(n, "L") update_buttons(oGrid) if !CheckSolved() solve()
}
- =====================================================================================
Submit: Gui, Submit, NoHide IniWrite, % n, %A_ScriptFullPath%:Stream:$DATA, gridSize, gridSize Reload return
- =====================================================================================
^Esc:: ExitApp
- ------------------------------
!1:: obj_map(oGrid) return
- =====================================================================================
- Solve By Using Arrow Buttons
- =====================================================================================
arwBtn: m := StrSplit(A_GuiControl, "_") Move(m[1], m[2]) CheckSolved() return
- =====================================================================================
- Solve By Using Mouse Drag
- =====================================================================================
- ------------------------------
- If ((mText := getButtonText()) ~= "^\d+$")
~LButton::
RR := oLocation[mText].R CC := oLocation[mText].C DragLR := DragUD := false CCF := RRF := 0
GuiControlGet, Pos, Pos, % RR "_" CC MouseGetPos, mx1, my1
while % GetKeyState("Lbutton", "P") {
CCF := CCF ? CCF : CC RRF := RRF ? RRF : RR MouseGetPos, mx2, my2 ; Drag Left / Right if (mx2<>mx1 && !DragUD) { loop % n { GuiControlGet, Pos%A_Index%, Pos, % RR "_" A_Index GuiControl, move, % RR "_" A_Index, % "x" Pos%A_Index%X +mx2-mx1 " y" PosY GuiControlGet, ButtonText%A_Index%,, % RR "_" A_Index } MouseGetPos, mx1, my1 DragLR := true } ; Drag Up / Down if (my2<>my1 && !DragLR) { loop % n { GuiControlGet, Pos%A_Index%, Pos, % A_Index "_" CC GuiControl, move, % A_Index "_" CC, % "x" PosX " y" Pos%A_Index%Y +my2-my1 GuiControlGet, ButtonText%A_Index%,, % A_Index "_" CC } MouseGetPos, mx1, my1 DragUD := true } ; Roll off Right Edge if DragLR GuiControlGet, Pos, Pos, % RR "_" n if (PosX > WW*n + W) && DragLR { loop % n { GuiControlGet, Pos%A_Index%, Pos, % RR "_" A_Index GuiControl, move, % RR "_" A_Index, % "x" Pos%A_Index%X - WW " y" PosY i := A_Index-1 GuiControl,, % RR "_" A_Index, % ButtonText%i% } GuiControl,, % RR "_" 1, % ButtonText%n% CCF++ ;~ GuiControl, focus, % RR "_" CCF MouseGetPos, mx1, my1 move(RR, "R") } ; Roll off Left Edge if DragLR GuiControlGet, Pos, Pos, % RR "_" 1 if (PosX < W) && DragLR { loop % n { GuiControlGet, Pos%A_Index%, Pos, % RR "_" A_Index GuiControl, move, % RR "_" A_Index, % "x" Pos%A_Index%X + WW " y" PosY i := A_Index+1 GuiControl,, % RR "_" A_Index, % ButtonText%i% } GuiControl,, % RR "_" n, % ButtonText1 CCF-- ;~ GuiControl, focus, % RR "_" CCF MouseGetPos, mx1, my1 move(RR, "L") } ; Roll off Bottom Edge if DragUD GuiControlGet, Pos, Pos, % n "_" CC if (PosY > WW*n + W) && DragUD { loop % n { GuiControlGet, Pos%A_Index%, Pos, % A_Index "_" CC GuiControl, move, % A_Index "_" CC, % "x" PosX " y" Pos%A_Index%Y - WW i := A_Index-1 GuiControl,, % A_Index "_" CC, % ButtonText%i% } GuiControl,, % 1 "_" CC, % ButtonText%n% RRF++ ;~ GuiControl, focus, % RRF "_" CC MouseGetPos, mx1, my1 move(CC, "D") } ; Roll off Top Edge if DragUD GuiControlGet, Pos, Pos, % 1 "_" CC if (PosY < W) && DragUD { loop % n { GuiControlGet, Pos%A_Index%, Pos, % A_Index "_" CC GuiControl, move, % A_Index "_" CC, % "x" PosX " y" Pos%A_Index%Y + WW i := A_Index+1 GuiControl,, % A_Index "_" CC, % ButtonText%i% } GuiControl,, % n "_" CC, % ButtonText1 RRF-- ;~ GuiControl, focus, % RRF "_" CC MouseGetPos, mx1, my1 move(CC, "U") }
} ; End Drag WinSet, Redraw,, A
if DragLR ; Place row in proper position after dragging
loop % n GuiControl, move, % RR "_" A_Index, % "x" WW*A_Index " y" PosY
if DragUD ; Place column in proper position after dragging
loop % n GuiControl, move, % A_Index "_" CC, % "x" PosX " y" WW*A_Index
Loop % n**2 { ; Update oGrid
R := ((A_Index-1)//n) + 1, C := Mod(A_Index-1, n) + 1 GuiControlGet, ButtonText,, % R "_" C oGrid[R, C] := ButtonText ; update oGrid based on button locations
}
- ~ Gui, show
CheckSolved() return
- If
- =====================================================================================
- Solve By Using Arrow Keys
- =====================================================================================
- ------------------------------
- If WinActive("16 Puzzle") && oGridR && oGridC
- ------------------------------
Right:: Move(oGridR, "R") GuiControl, focus, % oGridR "_" ++oGridC CheckSolved() return
- ------------------------------
Left:: Move(oGridR, "L") GuiControl, focus, % oGridR "_" --oGridC CheckSolved() return
- ------------------------------
Down:: Move(oGridC, "D") GuiControl, focus, % ++oGridR "_" oGridC CheckSolved() return
- ------------------------------
Up:: Move(oGridC, "U") GuiControl, focus, % --oGridR "_" oGridC CheckSolved() return
- If
- =====================================================================================
- SUBROUTINES
- =====================================================================================
- ------------------------------
GuiEscape: GuiClose: ExitApp return
- =====================================================================================
- FUNCTIONS
- =====================================================================================
- ------------------------------
Move(num, Dir, update:=1){
global local r, c, v if (Dir="R"){ ; move row # num right x := oGrid[num, n] loop, % n-1 oGrid[num, n+1-A_Index] := oGrid[num, n-A_Index] oGrid[num, 1] := x } if (Dir="L"){ ; move row # num left x := oGrid[num, 1] loop, % n-1 oGrid[num, A_Index] := oGrid[num, A_Index+1] oGrid[num, n] := x } if (Dir="U"){ ; move column # num up x := oGrid[1, Num] loop, % n-1 oGrid[A_Index, num] := oGrid[A_Index+1, num] oGrid[n, Num] := x } if (Dir="D"){ ; move column # num down x := oGrid[n, Num] loop, % n-1 oGrid[n+1-A_Index, num] := oGrid[n-A_Index, num] oGrid[1, Num] := x } for r, obj in oGrid for c, v in obj oLocation[v] := {"R" : r, "C" : c} if update update_buttons(oGrid) if !shuffled return Sleep % slp MovesCount++ ;~ WinSet, Redraw,, A return
}
- ------------------------------
CheckSolved(){
global local r, c, v if !Shuffled return cntr := 0 for R, obj in oGrid for C, v in obj if (oGrid[R, C]<>++cntr) return false Shuffled := 0 MsgBox Solved in %MovesCount% moves return true
}
- ------------------------------
update_buttons(oGrid){
for R, obj in oGrid for C, v in obj GuiControl,, % R "_" C, % oGrid[R, C] ; update buttons
}
- ------------------------------
getButtonText(){
MouseGetPos, mx, my, mw, mc if InStr(mc, "Button") GuiControlGet, ButtonText,, % mc return ButtonText
}
- ------------------------------
Reset(){
global local R, C, v for R, obj in oGrid for C, v in obj GuiControl,, % R "_" C, % oGrid[R,C] := C + (R-1)*n MovesCount := 0
}
- ------------------------------
Shuffle(){
global rows := ["R","L"], cols := ["U","D"], Shuffled := false loop, 200 { Random, num, 1, %n% Random, dir, 1,2 Move(num, rows[dir], 0) Move(num, cols[dir], 0) if !Mod(A_Index, n ) update_buttons(oGrid) } update_buttons(oGrid) Shuffled := true, MovesCount := 0
}
- ------------------------------
grdBtn(){
global m := StrSplit(A_GuiControl, "_") oGridR:= m[1], oGridC:= m[2] GuiControl, focus, % oGridR "_" oGridC
}
- ------------------------------</lang>