在 Zig 中学习编写一个简单的游戏

通过编写“猜数字”游戏来练习 Zig 编程。
1 位读者喜欢这篇文章。
Woman sitting in front of her computer

Ray Smith

用多种语言编写相同的应用程序是学习新的编程方式的好方法。大多数编程语言都有一些共同之处,例如

  • 变量
  • 表达式
  • 语句

这些概念是大多数编程语言的基础。一旦你理解了它们,你就可以花时间去弄清楚其余的部分。

此外,编程语言通常有一些相似之处。一旦你掌握了一种编程语言,你就可以通过识别其差异来学习另一种语言的基础知识。

学习新语言的一个好工具是通过练习一个标准的程序。
这使您可以专注于语言,而不是程序的逻辑。我在本系列文章中使用“猜数字”程序来做到这一点,在这个程序中,计算机选择一个 1 到 100 之间的数字,并要求您猜测。程序循环直到您猜对数字为止。

这个程序练习了编程语言中的几个概念

  • 变量
  • 输入
  • 输出
  • 条件评估
  • 循环

这是一个学习新编程语言的绝佳实践实验。

Zig 基础猜数字

Zig 仍处于 alpha 阶段,可能会发生变化。本文在 zig 版本 0.11 时是正确的。通过访问 downloads 目录并下载适合您的操作系统和架构的版本来安装 zig

const std = @import("std");

fn ask_user() !i64 {
    const stdin = std.io.getStdIn().reader();
    const stdout = std.io.getStdOut().writer();

    var buf: [10]u8 = undefined;

    try stdout.print("Guess a number between 1 and 100: ", .{});

    if (try stdin.readUntilDelimiterOrEof(buf[0..], '\n')) |user_input| {
        return std.fmt.parseInt(i64, user_input, 10);
    } else {
        return error.InvalidParam;
    }
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    var prng = std.rand.DefaultPrng.init(blk: {
        var seed: u64 = undefined;
        try std.os.getrandom(std.mem.asBytes(&seed));
        break :blk seed;
    });
    const value = prng.random().intRangeAtMost(i64, 1, 100);
    while (true) {
        const guess = try ask_user();
        if (guess == value) {
            break;
        }
        const message =
            if (guess < value)
            "low"
        else
            "high";
        try stdout.print("Too {s}\n", .{message});
    }
    try stdout.print("That's right\n", .{});
}

第一行 const std = @import("std"); 导入 Zig 标准库
几乎所有程序都需要它。

Zig 中的 ask_user 函数

函数 ask_user() 返回一个 64 位整数一个错误。这就是 ! (感叹号)的含义。这意味着如果存在 I/O 问题或用户输入无效输入,则该函数返回一个错误。

try 运算符调用一个函数并返回其值。如果它返回一个错误,它会立即从调用函数返回一个错误。这允许显式但简单的错误传播。ask_user 中的前两行别名包含来自 std 的一些常量。
这使得以下 I/O 代码更简单。

这行代码打印提示符

try stdout.print("Guess a number between 1 and 100: ", .{});

如果打印失败(例如,写入已关闭的终端),它会自动返回失败。

这行代码定义了读取用户输入的缓冲区

var buf: [10]u8 = undefined;

if 子句内的表达式将用户输入读取到缓冲区中

(try stdin.readUntilDelimiterOrEof(buf[0..], '\n')) |user_input|

该表达式返回读取到缓冲区的切片。这被分配给变量 user_input,它仅在 if 块内有效。

如果无法解析数字,函数 std.fmt.parseInt 返回一个错误。
此错误会传播给调用者。如果没有读取任何字节,则该函数会立即返回错误。

main 函数

该函数首先获取一个随机数。它使用 std.rand.DefaultPrng

该函数使用 std.os.getrandom 初始化随机数生成器。然后它使用生成器获取 1100 范围内的数字。

while 循环在 true 为真时继续,也就是永远。唯一的退出方式是使用 break,当猜测等于随机值时发生。

guess 不相等时,if 语句返回字符串 lowhigh,具体取决于猜测。这被插入到给用户的消息中。

请注意,main 定义为 !void,这意味着它也可以返回错误。这允许在 main 内部使用 try 运算符。

示例输出

示例运行,在将程序放入 main.zig

$ zig run main.zig 
Guess a number between 1 and 100: 50
Too high
Guess a number between 1 and 100: 25
Too low
Guess a number between 1 and 100: 37
Too low
Guess a number between 1 and 100: 42
Too high
Guess a number between 1 and 100: 40
That's right

总结

这个“猜数字”游戏是学习新编程语言的一个很好的入门程序,因为它以一种非常直接的方式练习了几个常见的编程概念。通过用不同的编程语言实现这个简单的游戏,您可以演示这些语言的一些核心概念并比较它们的细节。

您有最喜欢的编程语言吗?您会如何用它编写“猜数字”游戏?关注本系列文章,了解您可能感兴趣的其他编程语言!

接下来阅读什么
标签
Moshe sitting down, head slightly to the side. His t-shirt has Guardians of the Galaxy silhoutes against a background of sound visualization bars.
Moshe 自 1998 年以来一直参与 Linux 社区,帮助举办 Linux“安装派对”。他自 1999 年以来一直编写 Python 程序,并为核心 Python 解释器做出了贡献。Moshe 在这些术语出现之前就一直是 DevOps/SRE,非常关心软件可靠性、构建可重现性等。

评论已关闭。

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.