Keith Vetter 2025-04-17 : This is a game I wrote over a year ago and have been playing a lot ever since. I've wanted to post this to the Wiki earlier but the code grew too big and spread out over several files. Three other wiki pages are projects that were created for this game: Picture of the Day, Emoji, Unicode and Variation Selectors and First Sentence.
The code now lives on github, but I've included a short script that will automatically download a zip file of the code, extract it into a virtual directory then start the game.
Jigsaw Tiles is a variant of the classic jigsaw puzzle. Jigsaw Tiles takes any image, divides it into a set of similar tiles then shuffles the tiles. Your challenge is to unscramble the image by swapping tiles.
The actual code lives on github at http://github.com/kpvetter/jigsaw-tiles . The code below is a short script to let you quickly demo the game: it will automatically download, extract and start the game for you.
#!/bin/sh # Restart with tcl: -*- mode: tcl; tab-width: 8; -*- \ exec tclsh $0 ${1+"$@"} & \ exit ##+########################################################################## # # github_downloader.tcl -- Automatically download a github zip file # and launch the main file # by Keith Vetter 2025-04-01 # package require Tk package require vfs::zip package require http package require tls http::register http 443 [list ::tls::socket -tls1 1] package require uri set github http://github.com/kpvetter/jigsaw-tiles set zipMainFile jigsaw-tiles-main/jsTiles.tcl set github_url http://github.com/kpvetter/jigsaw-tiles/archive/refs/heads/main.zip # NB. if you test using curl you must add "-L" to follow redirects proc DownloadGithubZip {github_url} { # Downloads a given URL set token [geturl_followRedirects $github_url] set code [::http::ncode $token] set data [::http::data $token] ; list ::http::cleanup $token if {$code != 200} { puts stderr "ERROR: wrong http code ($code) downloading $github_url" exit 1 } return $data } proc SaveGithubZip {data} { # Saves data into a temporary file and returns that filename close [file tempfile tmpZipFile kpv.zip] set fout [open $tmpZipFile wb] puts -nonewline $fout $data close $fout return $tmpZipFile } proc geturl_followRedirects {url args} { # Calls http::geturl while following redirects array set URI [::uri::split $url] ;# Need host info from here set maxTries 10 while {[incr maxTries -1] >= 0} { set token [http::geturl $url {*}$args] if {![string match {30[1237]} [::http::ncode $token]]} {return $token} array set meta [set ${token}(meta)] if {![info exist meta(Location)]} { return $token } http::reset $token array set uri [::uri::split $meta(Location)] unset meta if {$uri(host) == ""} { set uri(host) $URI(host) } # problem w/ relative versus absolute paths set url [eval ::uri::join [array get uri]] } } proc Splash {title msg} { set bigger_bold_font [concat [font actual TkDefaultFont] -size 48 -weight bold] set big_font [concat [font actual TkDefaultFont] -size 24] destroy .splash toplevel .splash wm withdraw .splash wm overrideredirect .splash 1 ::ttk::frame .splash.f -padding .3i -borderwidth 3 -relief solid pack .splash.f -side left -fill both -expand 1 ::ttk::label .splash.f.title -text $title -font $bigger_bold_font ::ttk::label .splash.f.msg -text $msg -anchor c -justify c -font $big_font grid .splash.f.title -pady {0 .2i} grid .splash.f.msg update set x [expr {[winfo screenwidth .] / 2 - [winfo reqwidth .splash] / 2}] wm geom .splash +$x+200 wm deiconify .splash update raise .splash } ################################################################ ################################################################ wm withdraw . set title "Jigsaw Tiles Downloader" set msg "Downloading and expanding\nJigsaw Tiles from github" Splash $title $msg if {$tcl_interactive} return set data [DownloadGithubZip $github_url] ; list set tmpZipFile [SaveGithubZip $data] destroy .splash try { set zipVFS [::vfs::zip::Mount [file normalize $tmpZipFile] /__zip] cd /__zip/[file dirname $zipMainFile]/ wm deiconify . set S(inside,zip) 1 source [file tail $zipMainFile] if {$tcl_platform(platform) eq "windows"} { tkwait window . } } finally { catch {file delete $tmpZipFile} catch {::vfs::zip::Unmount $zipVFS /__zip} } return