[Arjen Markus] Inspired by RS's [A funny cookbook] I wrote down this script that implements a very basic memory game. In Holland it is actually known as "Memory" - I do not know whether that is the proper English name, though. The rules are simple: you have a number of pairs of cards and they are put on the table, face down. Each player turns around two of the cards and if he/she has a matching pair, he/she gets them. The winner is of course the player with most pairs. The script below implements a minimal version: * The pictures are replaced with prozaic numbers * The number of cards is fixed to 20 and the layout is hard-coded * There is only one player * There is no score card But most of these limitations are easy to fix - see the exercises. ---- ====== # memorygame.tcl -- # A basic implementation of the game of "Memory" # package require Tk # # Set up the buttons (they play the role of the picture cards) # set values [list] for { set i 1 } { $i <= 10 } { incr i } { lappend values $i $i } for { set i 1 } { $i <= 20 } { incr i } { set idx [expr {int(rand()*[llength $values])}] set label_text($i) [lindex $values $idx] set values [lreplace $values $idx $idx] button .b_$i -text " " -command [list showLabel $i] -width 3 } button .next -text "Next" -command nextMove label .empty -text " " grid .b_1 .b_2 .b_3 .b_4 .b_5 grid .b_6 .b_7 .b_8 .b_9 .b_10 grid .b_11 .b_12 .b_13 .b_14 .b_15 grid .b_16 .b_17 .b_18 .b_19 .b_20 grid .empty .next - - - # # Initialise # set click_count 0 set clicked_values [list] # # Handle selections # proc showLabel {label} { global click_count global clicked_values global label_text if { $click_count >= 2 } { return } incr click_count .b_$label configure -text $label_text($label) lappend clicked_values $label if { $click_count == 2 } { set label1 [lindex $clicked_values 0] set label2 [lindex $clicked_values 1] if { $label_text($label1) == $label_text($label2) } { foreach label $clicked_values { .b_$label configure -state disabled } set clicked_values [list] set click_count 0 } } } # # Handle next move # proc nextMove {} { global clicked_values global click_count foreach label $clicked_values { .b_$label configure -text " " } set clicked_values [list] set click_count 0 } ====== ---- Exercises for the young programmers for whom this is meant: * Use names instead of numbers * Can you adjust the game to, say, 15 pairs? 20 pairs? An arbitrary number? (the latter is a bit more difficult) What do you need to change in the code? * Can you come up with a strategy? What is the minimal number of steps? * Add a score card (showing the number of steps so far, and how pairs were found) * For the adventurous: add a second player * For the whizkids: turn this into a tic-tac-toe game ---- See also [Memory 2] which might be more appealing to play, but the code is less simple than the above (though with similarities). I'd however do away with the ''click_count'' variable above - the two places where it is tested can use [[llength $clicked_values]], which should give the same result in all cases, and make the thing simpler again. ---- ---- ***Screenshots*** [http://farm5.static.flickr.com/4032/4685168612_fd9b15c527_m.jpg] [gold] added pix <> Education | Games