TK/TCL,无法理解这个井字游戏代码片段 [英] TK/TCL, trouble understanding this tic tac toe code snippet

查看:29
本文介绍了TK/TCL,无法理解这个井字游戏代码片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能帮我解释一下下面的代码片段是做什么的.此代码片段取自 http://wiki.tcl.tk/12374.它旨在创建一个井字游戏.用于理解 Tk/Tcl 的资源并不多,所以这给我带来了很大的困难.

Can anyone help explain to me what the snippet below does. This code snippet is taken from http://wiki.tcl.tk/12374. It is meant to create a tic tac toe game. There are not many resources out there for understanding Tk/Tcl so this is giving me significant difficulty.

proc DrawBoard {{redraw 0}} { 
    global S B GAME C 

    if {$redraw} {                              ;# Must redraw everything
        .c delete all
        set w2 [expr {$B(w2) - 15}]             ;# Make a little margins
        set h2 [expr {$B(h2) - 15}]
        set hbar [expr {$h2 / 3.0}]   
        set vbar [expr {$w2 / 3.0}]

        set B(0) [list -$w2   -$h2   -$vbar -$hbar] ;# All 9 cells
        set B(1) [list -$vbar -$h2    $vbar -$hbar]
        set B(2) [list  $vbar -$h2    $w2   -$hbar]
        set B(3) [list -$w2   -$hbar -$vbar  $hbar]
        set B(4) [list -$vbar -$hbar  $vbar  $hbar]
        set B(5) [list  $vbar -$hbar  $w2    $hbar]
        set B(6) [list -$w2    $hbar -$vbar  $h2]
        set B(7) [list -$vbar  $hbar  $vbar  $h2]
        set B(8) [list  $vbar  $hbar  $w2    $h2]

        for {set i 0} {$i < 9} {incr i} {       ;# Rectangle for each cell
            .c create rect $B($i) -tag b$i -fill {} -outline {}
            .c bind b$i <Button-1> [list DoClick $i]
            set B($i) [ShrinkBox $B($i) 25]
        }
        .c create line -$w2 $hbar $w2 $hbar -tag bar ;# Draw the cross bars
        .c create line -$w2 -$hbar $w2 -$hbar -tag bar
        .c create line $vbar -$h2 $vbar $h2 -tag bar
        .c create line -$vbar -$h2 -$vbar $h2 -tag bar
        .c itemconfig bar -width 20 -fill $::C(bars) -capstyle round
    }
    .new config -state [expr {$GAME(tcnt) == 0 ? "disabled" : "normal"}]

    for {set i 0} {$i < 9} {incr i} {
        .c itemconfig b$i -fill {}              ;# Erase any win lines
        DrawXO $GAME(board,$i) $i
    }
    foreach i $GAME(win) {                      ;# Do we have a winner???
        .c itemconfig b$i -fill $C(win)
    }
}

好的,我最重要的问题是关于 w2, h2, hbar, vbar 变量.特别是如何声明它们.例如,set w2 [expr {$B(w2) - 15}].w2 如何定义为引用自身???作者使用这些变量来绘制井字游戏线,但我什至不知道这些变量是什么意思.这些变量是否指定了画布的某个维度,以便作者可以使用它来将特定区域绑定到点击活动?

Ok, the most significant question I have regards w2, h2, hbar, vbar variables. Particularly with how they are declared. For instance, set w2 [expr {$B(w2) - 15}]. How can w2 be defined referring to itself??? The author uses these variables to draw the tic tac toe lines, but I don't even know how what these variables mean. Does these variables specify some dimension of the canvas so that the author can use it to bind particular regions to click activities?

如果我理解了这四个变量,其他一切就都说得通了!

If I understand these four variables, everything else will make sense!

这是板子的图像:

推荐答案

Tcl 中的变量(Tk 只是一个位于 Tcl 之上的窗口绘制工具包)是在写入时定义的;通常没有明确的声明.唯一的例外是直接在命名空间中使用变量,最好在第一次使用之前使用 variable 命令声明它们,如下所示:

Variables in Tcl (Tk is just a window drawing toolkit that lives on top of Tcl) are defined when they are written to; there's usually no explicit declaration. The only exception to this is with variables directly in a namespace, where it is best practice to use the variable command to declare them before first use, like this:

namespace eval exampleNamespace {
    variable xmpl1 "abc def"

    # Or equivalently...

    variable xmpl2
    set xmpl2 "abc def"

    # You have to use the second style with arrays...

    variable arrayXmpl
    set arrayXmpl(1) "pqr stu"
    set arrayXmpl(2) "qwerty uiop"
}

过程中的局部变量不需要声明,但是如果你想访问一个不是局部的变量你必须使用一个命令(通常globalupvar) 将其引入范围.

Local variables in procedures don't need declaring, though if you want to access a variable that isn't local you have to use a command (often global or upvar) to bring it into scope.

proc variableExample {formalArgument1 formalArgument2} {
    set localVar1 "abc"
    set localVar2 "def"
    global thisOtherVar
    append thisOtherVar "ghi" $formalArgument1
    puts "Currently, got $localVar1 $localVar2 and '$thisOtherVar'"
}

global 放在程序的顶部是很传统的做法,但这完全没有必要.它的效果从您执行的位置一直持续到过程调用结束.Tcl 的语义是严格操作的,具有极其严格定义的评估顺序(从左到右,总是).

It's pretty conventional to put the global at the top of the procedure, but it's totally not necessary. It's effect persists from where you do it until the end of the procedure call. Tcl's semantics are strictly operational with extremely tightly defined evaluation order (it's left-to-right, always).

现在,数组是聚合变量.数组的每个元素本身就是一个变量.它们与普通的简单变量不同,尽管整个数组的名称与简单变量的命名方案相同.你不能在同一个范围内有一个简单的 foo 和一个 foo(bar)(没有 unsetting 一个,这会删除变量).元素的键是字符串——幕后的实现是一个高性能的哈希表——完全不是变量,这意味着B(w2)w2 变量是完全不同的;它们根本不是一回事.但是,我们可以使用变量(和其他 Tcl 替换)来计算用作键的字符串,因此我们可以这样做:

Now, arrays are aggregate variables. Each element of an array is a variable itself. They're distinct from normal simple variables, though the name of the overall array is in the same naming scheme as the simple variables. You can't have a simple foo and a foo(bar) in the same scope (without unsetting one first, which removes the variable). The keys into the elements are strings — the implementation behind the scenes is a high-performance hash table — that are entirely not variables and this means that the B(w2) and w2 variables are entirely distinct; they're not the same thing at all. However, we can use variables (and other Tcl substitutions) in computing the string to use as a key, so we can do this:

set name "w2"
set B($name) "example of "
append B(w2) "array key handling"
puts "this is an $B($name)"

<小时>

让我们看一下你一直困惑的例子:


Let's look at the example that you were puzzling over:

set w2 [expr {$B(w2) - 15}]

把它分成几块:

set w2 […]

它将写入变量 w2.这就是带有两个参数的 set 命令所做的.将要写入的内容是评估另一个命令的结果.我们需要更深入地研究.

It's going to write to the variable w2. That's what the set command does with two arguments. The thing that is going to be written in is the result of evaluating another command. We need to look deeper.

expr {$B(w2) - 15}

把它分成几块:

expr {…}

这产生了对大括号中的表达式求值的结果.强烈建议您将大括号括在所有表达式中;它更安全,更快.表达方式是什么?(请注意,表达式使用与 Tcl 其余部分不同的语法.)

That yields the result of evaluating the expression in the braces. It's strongly recommended that you put braces around all your expressions; it's safer and much faster. What's the expression? (Note that expressions use a different syntax to the rest of Tcl.)

$B(w2) - 15

好的,那就是从从数组的 w2 元素读取的值(因为 $)减去 15(数字)B.这里的 w2 只是一个字符串.其他地方有一个同名变量纯属巧合.

OK, that's subtracting 15 (the number) from the value read (because of the $) from the w2 element of the array B. The w2 here is just a string. That there's a variable elsewhere with the same name is coincidence.

就是这样.重新组装这些部件,我们看到:

And that's it. Reassembling the pieces, we see that:

set w2 [expr {$B(w2) - 15}]

B(w2)的内容减去15的结果赋值给变量w2.这就是全部.(数组B 是一个全局数组;请参阅过程顶部的global.)

Assigns the result of subtracting 15 from the contents of B(w2) to the variable w2. That's all it does. (The array B is a global array; see the global at the top of the procedure.)

行:

    set w2 [expr {$B(w2) - 15}]             ;# Make a little margins
    set h2 [expr {$B(h2) - 15}]
    set hbar [expr {$h2 / 3.0}]   
    set vbar [expr {$w2 / 3.0}]

这些从全局数组B中获取画布的一半高度和宽度,删除15个像素作为边距,然后设置hbar/vbar 到该值的三分之一,以便绘制坐标更容易.一旦您意识到画布的绘图原点已移动(类似于滚动)到其窗口的中心,它会有所帮助.并且要注意,做 -$hbar 实际上有点顽皮,虽然很可爱;它使用字符串连接来否定一个值,当该值是正数并且没有明确的符号时这是可以的,但如果它发生变化就会很脆弱.与执行 [expr {-$hbar}] 相比,它很慢,尽管它更长;计算成本与命令长度不完全匹配.

These get the half height and width of the canvas from the global array B, remove 15 pixels for a margin, and then set hbar/vbar to a third of that value so that the coordinates for drawing are easier. It helps once you realize that the canvas has had its drawing origin moved (similar to in scrolling) to the center of its window. And be aware that doing -$hbar is actually being a bit naughty, though cute; it's using string concatenation to negate a value, which is OK when the value is positive and doesn't have an explicit sign, but would be fragile if that ever changed. And it's slow by comparison with doing [expr {-$hbar}], though that's longer; the cost of computation isn't exactly matched with the length of the command.

这篇关于TK/TCL,无法理解这个井字游戏代码片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆