Works on basic, L ANSI, and L Unicode
#NoEnv #SingleInstance, Force SetBatchLines, -1 w = 4 h = 4 lvl = 4 BkgCol = Silver TxtCol = Black EvnCol = Maroon OddCol = Navy ES := W . "_" . H Loop %W% { X := A_Index Loop %H% { Y := A_Index CX := ((X - 1) * 30) + 1 CY := ((Y - 1) * 30) CY2 := ((Y - 1) * 30) + floor((30 - 16) / 2) CID := X . "$" . Y CID2 := X . "_" . Y Num := CID2 = ES ? "" : ((Y - 1) * W) + X %CID2% := Num %X%@%Y% := Num Col = %EvnCol% if (mod(Num, 2)) Col = %OddCol% Gui, Font, c%Col% s22, WebDings Gui, Add, Text, x%CX% y%CY% v%CID% gClick, % CID2 = ES ? "" : "c" Gui, Font, c%TxtCol% s12, Verdana Gui, Add, Text, x%CX% y%CY2% v%CID2% BackgroundTrans w30 Center gClick, %Num% } } Shuffle(W * H * 10 * lvl) Display() GuiW := W * 30 + 1 GuiH := H * 30 + 1 Gui, Color, %BkgCol% Gui, +ToolWindow +E0x40000 Gui, Show, w%GuiW% h%GuiH%, 15 Puzzle ;info := "AHK Version:`tAHK" . ((SubStr(A_AHKVersion, 3, 1) = 0) ? " Basic" : "_L") ; . "`nUnicode:`t`t" (A_IsUnicode ? "Yes " ((A_PtrSize=8) ? "(64-bit)" : "(32-bit)") : "No") ;MsgBox, %info% return Click: Pos := A_GuiControl StringReplace, Pos, Pos, $, _, All if (Valid(Pos)) Swap(Pos) Display() if (HasWon()) MsgBox, You won! return GuiClose: ExitApp return Valid(Pos) { global ES StringSplit, ES, ES, _ StringSplit, XY, Pos, _ If ((Abs(XY1 - ES1) = 1 && XY2 = ES2) || (Abs(XY2 - ES2) = 1 && XY1 = ES1)) return 1 return 0 } Swap(Pos) { global %ES% := %Pos% ; change the number of the empty space to the nearby space %Pos% := ; change the the number of the nearby space to empty ES := Pos ; change the location of the empty space to the location of the nearby space return } Display() { global local x, y, Col Loop %W% { X := A_Index Loop %H% { Y := A_Index if (%X%@%Y% != %X%_%Y%) ; If the space has changed { Col = %EvnCol% if (mod(%X%_%Y%, 2)) Col = %OddCol% Gui, font, c%TxtCol% s12, Verdana GuiControl,, %X%_%Y%, % %X%_%Y% ; Update the space GuiControl, Font, %X%_%Y% Gui, font, c%Col% s22, WebDings if (%X%@%Y% = "" && %X%_%Y% != "") ; If it used to be the empty space and is not anymore GuiControl,, %X%$%Y%, c ; Add a background else if (%X%@%Y% != "" && %X%_%Y% = "") ; If it did not used to be the empty space and it is now GuiControl,, %X%$%Y% ; remove the background GuiControl, Font, %X%$%Y% %X%@%Y% := %X%_%Y% } } } } HasWon() { global Loop %W% { X := A_Index Loop %H% { Y := A_Index If (%X%_%Y% != "" && %X%_%Y% != ((Y - 1) * W) + X) return 0 } } return 1 } Shuffle(lvl) { global W, H, ES Loop %lvl% { StringSplit, ES, ES, _ R1 = 0 while (R1 = 0) Random, R1, -1, 1 Random, R2, 1, 2 if R2 = 1 { X := ES1 + R1 X := ((X > W) ? (ES1 - 1) : ((X < 1) ? (ES1 + 1) : (X))) Swap(X . "_" . ES2) } else if R2 = 2 { Y := ES2 + R1 Y := ((Y > H) ? (ES2 - 1) : ((Y < 1) ? (ES2 + 1) : (Y))) Swap(ES1 . "_" . Y) } } return }