Redian新闻
>
通过这个简单的游戏学习 Tcl/Tk 和 Wish | Linux 中国

通过这个简单的游戏学习 Tcl/Tk 和 Wish | Linux 中国

科技
 
导读:以下是一个简单的编程项目,能够帮助你开始学习 Tcl/Tk。                           
本文字数:5760,阅读时长大约:8分钟

https://linux.cn/article-16170-1.html
作者:James Farrell
译者:ChatGPT

以下是一个简单的编程项目,能够帮助你开始学习 Tcl/Tk。

探索 Tcl/Tk 的基础构造,包括用户输入、输出、变量、条件评估、简单函数和基础事件驱动编程。

我写这篇文章的初衷源于我想更深入地利用基于 Tcl 的 Expect。这让我写下了以下两篇文章:通过编写一个简单的游戏学习 Tcl🔗 opensource.com 和 通过编写一个简单的游戏学习 Expect🔗 opensource.com

我进行了一些 Ansible🔗 www.redhat.com 自动化工作,逐渐积累了一些本地脚本。有些脚本我频繁使用,以至于以下循环操作变得有些烦人:

◈ 打开终端
◈ 使用 cd 命令跳转至合适的目录
◈ 输入一条带有若干选项的长命令启动所需的自动化流程

我日常使用的是 macOS。实际上我更希望有一个菜单项或者一个图标,能够弹出一个简单的界面接受参数并执行我需要的操作,这就像在 Linux 的 KDE 中一样🔗 opensource.com

经典的 Tcl 类书籍都包含了关于流行的 Tk 扩展的文档。既然我已经深入研究了这个主题,我尝试着对其(即 wish)进行编程。

虽然我并非一名 GUI 或者前端开发者,但我发现 Tcl/Tk 脚本编写的方式相当直接易懂。我很高兴能重新审视这个 UNIX 历史的古老且稳定的部分,这种技术在现代平台上依然有用且可用。

安装 Tcl/Tk

对于 Linux 系统,你可以按照下面的方式安装:

  1. $ sudo dnf install tcl
  2. $ which wish
  3. /bin/wish

而在 macOS 上,你可以通过 Homebrew🔗 opensource.com 来安装最新版的 Tcl/Tk:

  1. $ brew install tcl-tk
  2. $ which wish
  3. /usr/local/bin/wish

编程理念

许多编写游戏的教程都会介绍到典型的编程语言结构,如循环、条件判断、变量、函数和过程等等。

在此篇文章中,我想要介绍的是 事件驱动编程🔗 developers.redhat.com。当你的程序使用事件驱动编程,它会进入一个特殊的内置循环,等待特定的事件发生。当这个特定的事件发生时,相应的代码就会被触发,产生预期的结果。

这些事件可以包括键盘输入、鼠标移动、点击按钮、定时器触发,甚至是任何你的电脑硬件能够识别的事件(可能来自特殊的设备)。你的程序中的代码决定了用户看到了什么,以及程序需要监听什么输入,当这些输入被接收后程序会怎么做,然后进入事件循环等待输入。

这篇文章的理念并没有脱离我之前的 Tcl 文章太远。这里最大的不同在于用 GUI 设置和用于处理用户输入的事件循环替代了循环结构。其他的不同则是 GUI 开发需要采取的各种方式来制作一个可用的用户界面。在采用 Tk GUI 开发的时候,你需要了解两个基础的概念:部件(widget)几何管理器(geometry manager)

部件是构成可视化元素的 UI 元素,通过这些元素用户可以与程序进行交互。这其中包括了按钮、文本区域、标签和文本输入框。部件还包括了一些选项选择,如菜单、复选框、单选按钮等。最后,部件也包括了其他的可视化元素,如边框和线性分隔符。

几何管理器在放置部件在显示窗口中的位置上扮演着至关重要的角色。有一些不同的几何管理器可以供你使用。在这篇文章中,我主要使用了 grid 几何来让部件在整齐的行中进行布局。我会在这篇文章的结尾地方解释一些几何管理器的不同之处。

用 wish 进行猜数字游戏

这个示例游戏代码与我其他文章中的示例有所不同,我将它分解为若干部分以方便解释。

首先创建一个基本的可执行脚本 numgame.wish :

  1. $ touch numgame.wish
  2. $ chmod 755 numgame.wish

使用你喜欢的文本编辑器打开此文件,输入下列代码的第一部分:

  1. #!/usr/bin/env wish
  2. set LOW 1
  3. set HIGH 100
  4. set STATUS ""
  5. set GUESS ""
  6. set num [expr round(rand()*100)]

第一行定义了该脚本将通过 wish 执行。接下来,创建了几个全局变量。这里我使用全部大写字母定义全局变量,这些变量将绑定到跟踪这些值的窗口小部件(LOWHIGH等等)。

全局变量 num 是游戏玩家要猜测的随机数值,这个值是通过 Tcl 的命令执行得到并保存到变量中的:

  1. proc Validate {var} {
  2. if { [string is integer $var] } {
  3. return 1
  4. }
  5. return 0
  6. }

这是一个验证用户输入的特殊函数,它只接受整数并拒绝其他所有类型的输入:

  1. proc check_guess {guess num} {
  2. global STATUS LOW HIGH GUESS
  3. if { $guess < $LOW } {
  4. set STATUS "What?"
  5. } elseif { $guess > $HIGH } {
  6. set STATUS "Huh?"
  7. } elseif { $guess < $num } {
  8. set STATUS "Too low!"
  9. set LOW $guess
  10. } elseif { $guess > $num } {
  11. set STATUS "Too high!"
  12. set HIGH $guess
  13. } else {
  14. set LOW $guess
  15. set HIGH $guess
  16. set STATUS "That's Right!"
  17. destroy .guess .entry
  18. bind all <Return> {.quit invoke}
  19. }
  20. set GUESS ""
  21. }

这是主要的猜数逻辑循环。global 语句让我们能够修改在文件开头创建的全局变量(关于此主题后面将会有更多解释)。这个条件判断寻找入力范围在 1 至 100 之外以及已经被用户猜过的值。有效的猜测和随机值进行比较。LOW 和 HIGH 的猜测会被追踪,作为 UI 中的全局变量进行报告。在每一步,全局 STATUS 变量都会被更新,这个状态信息会自动在 UI 中显示。

对于正确的猜测,destroy 语句会移除 “Guess” 按钮以及输入窗口,并重新绑定回车键,以激活 “Quit” 按钮。

最后的语句 set GUESS "" 用于在下一个猜测之前清空输入窗口。

  1. label .inst -text "Enter a number between: "
  2. label .low -textvariable LOW
  3. label .dash -text "-"
  4. label .high -textvariable HIGH
  5. label .status -text "Status:"
  6. label .result -textvariable STATUS
  7. button .guess -text "Guess" -command { check_guess $GUESS $num }
  8. entry .entry -width 3 -relief sunken -bd 2 -textvariable GUESS -validate all \
  9. -validatecommand { Validate %P }
  10. focus .entry
  11. button .quit -text "Quit" -command { exit }
  12. bind all <Return> {.guess invoke}

这是设置用户界面的部分。前六个标签语句在你的 UI 上创建了不同的文本展示元素,-textvariable 选项监控给定的变量,并自动更新标签的值,这展示了全局变量 LOWHIGHSTATUS 的绑定。

button 行创建了 “Guess” 和 “Quit” 按钮, -command 选项设定了当按钮被按下时要执行的操作。按下 “Guess” 按钮执行了上面的 check_guess 函数以检查用户输入的值。

entry 部件更有趣。它创建了一个三字符宽的输入框,并将输入绑定到 GUESS 全局变量。它还通过 -validatecommand 选项设置了验证,阻止输入部件接收除数字以外的任何内容。

focus 命令是用户界面的一项改进,使程序启动时输入部件处于激活状态。没有此命令,你需要先点击输入部件才可以输入。

bind 命令允许你在按下回车键时自动点击 “Guess” 按钮。如果你记得 check_guess 中的内容,猜测正确之后会重新绑定回车键到 “Quit” 按钮。

最后,这部分设定了图形用户界面的布局:

  1. grid .inst
  2. grid .low .dash .high
  3. grid .status .result
  4. grid .guess .entry
  5. grid .quit

grid 几何管理器被逐步调用,以逐渐构建出预期的用户体验。它主要设置了五行部件。前三行是显示不同值的标签,第四行是 “Guess” 按钮和 entry 部件,最后是 “Quit” 按钮。

程序到此已经初始化完毕,wish shell 进入事件循环,等待用户输入整数并按下按钮。基于其在被监视的全局变量中找到的变化,它会更新标签。

注意,输入光标开始就在输入框中,而且按下回车键将调用适当且可用的按钮。

这只是一个初级的例子,Tcl/Tk 有许多可以让间隔、字体、颜色和其他用户界面方面更具有吸引力的选项,这超出了本文中简单 UI 的示例。

运行这个应用,你可能会注意到这些部件看起来并不很精致或现代。这是因为我正在使用原始的经典部件集,它们让人回忆起 X Windows Motif 的时代。不过,还有一些默认的部件扩展,被称为主题部件,它们可以让你的应用程序有更现代、更精致的外观和感觉。

启动游戏!

保存文件之后,在终端中运行它:

  1. $ ./numgame.wish

在这种情况下,我无法给出控制台的输出(LCTT 译注,GIF 图也帧数太多,不能上传)。

进一步了解 Tcl

Tcl 支持命名空间的概念,所以在这里使用的变量并不必须是全局的。你可以把绑定的部件变量组织进不同的命名空间。对于像这样的简单程序,可能并不太需要这么做。但对于更大规模的项目,你可能会考虑这种方法。

proc check_guess 函数体内有一行 global 代码我之前没有解释。在 Tcl 中,所有变量都按值传递,函数体内引用的变量的范围是局部的。在这个情况下,我希望修改的是全局变量,而不是局部范围的版本。Tcl 提供了许多方法来引用变量,在执行堆栈的更高级别执行代码。在一些情况下,像这样的简单引用可能带来一些复杂性和错误,但是调用堆栈的操作非常有力,允许 Tcl 实现那些在其他语言中实现起来可能较为复杂的新的条件和循环结构。

最后,在这篇文章中,我没有提到几何管理器,它们用于以特定的顺序展示部件。只有被某种几何管理器管理的部件才能显示在屏幕上。grid 管理器相当简洁,它按照从左到右的方式放置部件。我使用了五个 grid 定义来创建了五行。另外还有两个几何管理器:place 和 pack。pack 管理器将部件围绕窗口边缘排列,而 place 管理器允许固定部件的位置。除这些几何管理器外,还有一些特殊的部件,如 canvas ,text 和 panedwindow,它们可以容纳并管理其他部件。你可以在经典的 Tcl/Tk 参考指南,以及 Tk 命令🔗 tcl.tk 文档页上找到这些部件的全面描述。

继续学习编程

Tcl 和 Tk 提供了一个简单有效的方法来构建图形用户界面和事件驱动应用程序。这个简单的猜数游戏只是你能用这些工具做到的事情的起点。通过继续学习和探索 Tcl 和 Tk,你可以打开构建强大且用户友好的应用程序的无数可能性。继续尝试,继续学习,看看你新习得的 Tcl 和 Tk 技能能带你到哪里。

(题图:MJ/40621c50-6577-4033-9f3c-8013bd0286f1)


via: https://opensource.com/article/23/4/learn-tcltk-wish-simple-game

作者:James Farrell 选题:lkxed 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

欢迎遵照 CC-BY-SA 协议规定转载,
如需转载,请在文章下留言 “转载:公众号名称”,
我们将为您添加白名单,授权“转载文章时可以修改”。


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
12个简单的方法增加你的纤维摄入!10 分钟让你了解 Linux ABI | Linux 中国澳街头采访:这样一个简单的问题,竟难倒不少人……Fedora Linux 的家族(一):官方版本 | Linux 中国你的旧电脑是 “过时” 了,还是使用 Linux 的机会? | Linux 中国5 个专注于隐私保护的 Linux 发行版 | Linux 中国领导说“辛苦了”,只需要回复这几个简单的字,就足够了Ubuntu Linux 的 7 个最佳应用坞 | Linux 中国将 Linux 终端与 Nautilus 文件管理器结合起来 | Linux 中国在 Linux 中使用 cat 命令 | Linux 中国法国:骚乱尚未平息,欧洲:从此右转不可阻挡Linux 游戏的下一个秘密武器:Bottles Next | Linux 中国你好,我是筚(bì)篥( lì)!Fedora Linux 的家族(二):定制版 | Linux 中国这两个简单的设计小巧思,让你的PPT不止高级20倍!使用 Gamerzilla 分享你的游戏成就 | Linux 中国三星超台积电当一哥?全球前25国军事实力排名(worlds-most-powerful-militaries-2023)iPhone专家透露了两个简单的设置调整,可以让你的手机充电速度提高四倍开源朗读者 | Linux 只是一个内核:这是什么意思? | Linux 中国一生应该像一条河修复 Arch Linux 中的 “Bash: man command not found” 错误 | Linux 中国Fedora Linux 的家族(三):实验室 | Linux 中国2023 年最佳 Linux 视频编辑软件 | Linux 中国终端基础:在 Linux 中复制文件和目录 | Linux 中国罕见!华裔女子做个简单的过敏测试 没想到被送急诊室抢救一个简单的姿势就能轻松止鼾,让全家都睡个好觉40个简单但有效的Linux Shell脚本示例Bazzite:专为 Steam Deck 和 PC 上的 Linux 游戏打造的发行版 | Linux 中国代写代考不是简单的游戏!这些深层危害很多人都不知道!Linux 中退出码的含义 | Linux 中国超尴尬!一个简单的emoji却被外国同学理解偏了,差点“友尽”?Linux Shell 介绍:Bash、Zsh 和 Fish | Linux 中国如何在 Linux 主机和 KVM 中的 Windows 客户机之间共享文件夹 | Linux 中国Tent Ridge 拔草了
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。