- 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
# 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.


