Version 5 of iKnow: a pocket quiz

Updated 2005-01-21 06:52:20 by suchenwi

if 0 {Richard Suchenwirth 2003-05-15 - As yet another Tcltoy (runnable on a PocketPC of course, and even there taking up only half of the screen), here is a quiz vaguely inspired by popular TV shows. You get a question and four possible answers, one of which is right. Click on the correct one to improve your statistics, as displayed at top. No money in the game (as appropriate for free software ;-), but you can use this for vocabulary testers or other things you want to test yourself or someone else with - just edit in your own questions!

http://mini.net/files/iKnow.jpg

Besides the fun and the cool name, what interested me in this is again the creation of a very little language which doesn't look like Tcl, but much more natural. The iKnow package creates two public commands:

  • Questions: without arguments (looks like headline, but creates the UI)
  • - q? ar? af? af? af?

The - command adds a question q to the database, with the right answer (ar) first and then three wrong ones (af), and uses question marks as separators between arguments, so the specification of questions looks very natural - see examples below.

Of course for practical usability, one would have to collect hundreds or thousands of questions... In the simplest case, the whole file (as shown here) is a standalone quiz. If you place it into a directory in your package path and (re)create a package index, more quiz files just need the package require iKnow as illustrated in the self-test/demo code below. }

 namespace eval iKnow {
        variable version 1.0 tries 0 right 0
 }
 proc Questions: {} {
    frame .f
    label .f.s -textvar stats -width 35
    button .f.x -text X -command exit
    eval pack [winfo chil .f] -side left
    label .q -textvar q -height 4 -bg white
    frame .a
    foreach i {0 1 2 3} {
       button .a.$i -textvar $i -width 18 \
          -command [list iKnow::judge .a.$i]
    }
    grid .a.0 .a.1 -sticky news
    grid .a.2 .a.3 -sticky news
    eval pack [winfo children .] -fill x
    after idle iKnow::ask
    if {$::tcl_platform(os)=="Windows CE"} {wm geometry . +0+0}
 }
 proc - args {
    lappend iKnow::questions [split [join $args] ?]
 }
 proc iKnow::ask {} {
    variable questions; variable correct
    if ![llength $questions] {
       set ::q "GAME OVER"; return
    }
    set question [ldraw questions]
    set ::q [lindex $question 0]?
    set correct1 [lindex $question 1]
    set ans [lrange $question 1 4]
    foreach i {0 1 2 3} {
       set ::$i [ldraw ans]
       if {[set ::$i]==$correct1} {set correct $i}
    }
 }
 proc iKnow::judge w {
    variable tries; variable right
    variable correct
    incr tries
    set number [string index $w end]
    set bg [$w cget -bg]
    if {$number==$correct} {
       incr right
       $w config -bg green
    } else {
       $w config -bg red
       set w2 [string range $w 0 end-1]$correct
       $w2 config -bg green
       after 1000 $w2 config -bg $bg
    }
    after 500 $w config -bg $bg
    set perc [expr {$tries? 100*$right/$tries: "--"}]
    set ::stats "$right / $tries = $perc %"
    after 1000 iKnow::ask
 }  
 proc ldraw varName {
    upvar 1 $varName var
    set pos [expr int(rand()*[llength $var])]
    set res [lindex $var $pos]
    set var [lreplace $var $pos $pos]
    set res
 }
 package provide iKnow $iKnow::version

 if {[info exists argv0] && [file tail $argv0]==[file tail [info script]]} {

#-- self-test and demo (data files would look like this):

 package require iKnow
 Questions:
 - Capital of Switzerland? Bern? Zurich? Basel? Geneva?
 - Who created the Tcl language? John Ousterhout? Larry Wall?\
     Guido van Rossum? Brent Welch?
 - National currency in Turkey? Lira? Pound? Peso? Dinar?
 - French 'canard' means? duck? dog? channel? ocean liner?
 - When did the 30-Years War end? 1648? 1789? 1618? 1918?

}


Unrelated, but same name: iKnow


Category Games | Arts and crafts of Tcl-Tk programming