Rust 入门 猜数字小游戏

使用 Rust 开发一个猜数字小游戏

这个小游戏你会认识到那些知识点?

  • 变量如何声明
  • 程序的流程控制
  • 方法、关联函数
  • 项目依赖 (crate)

猜数字游戏的设计目标

  • 生成一个 1 - 100 的随机数
  • 提示玩家输入一个猜测
  • 对比猜测结果并提示玩家猜测结果
  • 如果猜测正确 让程序输出一个庆祝信息并退出程序

项目准备

  • 在项目存放目录打开命令行并输入cargo new guessing_game
  • 使用你熟悉的编辑器打开我们刚刚创建的项目

生成一个神秘数字

  • 打开 Cargo.toml 文件, 添加项目依赖
# 包配置
[package]
name = "guessing_game" # 项目名称
version = "0.1.0" # 项目版本
authors = ["Your Name <you@example.com>"] # 作者
edition = "2018" # rust 版本

# 外部依赖
[dependencies]
# 导入rand包, 用于生成随机数
rand = "^0.7.3"
  • 打开 main.rs 文件, 编写代码
use rand::Rng; // 引入 rand 包下的一个 trait(特性)

fn main() {
    // 生成一个神秘数字
    let secret_number = rand::thread_rng().gen_range(1, 101);
    // 输出这个数字
    println!("神秘数字是: {}", secret_number);
}
  • 编译运行
> cargo run
   Compiling getrandom v0.1.16
   Compiling cfg-if v1.0.0
   Compiling ppv-lite86 v0.2.10
   Compiling rand_core v0.5.1
   Compiling rand_chacha v0.2.2
   Compiling rand v0.7.3
   Compiling guessing_game v0.1.0 (D:\rust\projects\guessing_game)
    Finished dev [unoptimized + debuginfo] target(s) in 3.72s
     Running `target\debug\guessing_game.exe`
神秘数字是: 75

获取用户输入结果

  • 编写代码
use std::io; // 引入标准库的IO模块
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);
    println!("神秘数字是: {}", secret_number);
    
    // 提示用户输入猜测内容
    println!("请输入:");
    // 创建一个可变的空字符串实例 用于接收用户输入的内容
    let mut guess = String::new();
    // 从控制台读入一行内容 将读入的内容存放在变量 guess 中
    // 这个函数返回一个枚举类型, 它有两个变体, OK 和 Err
    let result = io::stdin().read_line(&mut guess);
    // 处理可能存在的错误, 如果这个变体是Err 程序就会触发 panic (恐慌)
    result.expect("无法读取您输入的内容!");
    
    // 因为我们读入的内容是字符串类型, 所以我们来将字符串转换为整数类型
    let guess: u32 = match guess.trim().parse() {
    //  ^^^^^ 注: 这里标识符的重名在 rust 内是允许的, 此时上一个同名的标识符将被隐藏起来
        Ok(number) => number, // 如果转换成功则将转换成功的结果返回给变量
        _ => { // 如果转换失败就提示用户输入的不正确
            println!("您输入的不是一个正整数!");
            return;
        }
    };
    // 打印一下看看对不对
    println!("您猜测的数字是: {}", guess);
}
  • 编译运行
> cargo run
......
神秘数字是: 13
请输入:
5
您猜测的数字是: 5

> cargo run
......
神秘数字是: 62
请输入:
hello
您输入的不是一个正整数!

进行一次猜测

  • 编写代码
use std::io;
use std::cmp::Ordering; // 引入标准库下的一个 enum(枚举)
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);
    println!("神秘数字是: {}", secret_number);
    
    println!("请输入:");
    let mut guess = String::new();
    let result = io::stdin().read_line(&mut guess);
    result.expect("无法读取您输入的内容!");
    
    let guess: u32 = match guess.trim().parse() {
        Ok(number) => number,
        _ => {
            println!("您输入的不是一个正整数!");
            return;
        }
    };
    println!("您猜测的数字是: {}", guess);
    
    // match 表达式与 Java 中的 switch 表达式很相似
    // 但是 match 不需要手动使用 break 跳出分支
    match guess.cmp(&secret_number) {
        Ordering::Less => println!("猜小了"),
        Ordering::Greater => println!("猜大了"),
        Ordering::Equal => println!("恭喜您猜对了!")
    }
}
  • 编译运行
> cargo run
......
神秘数字是: 13
请输入:
5
您猜测的数字是: 5
猜小了

多次猜测

  • 编写代码
use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);
    println!("神秘数字是: {}", secret_number);
    loop { // loop 是一个死循环(无限循环代码块) 需要在合适的位置调用 break 跳出循环
        println!("请输入:");
        let mut guess = String::new();
        let result = io::stdin().read_line(&mut guess);
        result.expect("无法读取您输入的内容!");

        let guess: u32 = match guess.trim().parse() {
            Ok(number) => number,
            _ => {
                println!("您输入的不是一个正整数!");
                continue; // 跳出本次循环
            }
        };
        println!("您猜测的数字是: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("猜小了"),
            Ordering::Greater => println!("猜大了"),
            Ordering::Equal => {
                println!("恭喜您猜对了!");
                break; // 跳出循环
            }
        }
    }
}
  • 编译运行
> cargo run
......
神秘数字是: 66
请输入:
5
您猜测的数字是: 5
猜小了
请输入:
67
您猜测的数字是: 67
猜大了
请输入:
66
您猜测的数字是: 66
恭喜您猜对了!

去掉打印信息并且微调代码

  • 最终的到的代码
// 默认情况下 Rust 会将 prelude 模块中少量的类型引入到每个程序的作用域中
// 如果需要的类型不在 prelude 模块中
// 就必须使用 use 语句显式地将其引入作用域
// prelude: 预导入模块

// 引入标准库的IO模块
use std::io;
// 引入标准库下的一个 enum(枚举)
use std::cmp::Ordering;
// 引入rand包下的一个 trait(特性) 与 Java 中的接口类似
use rand::Rng;

// main是入口函数
// 这是绝大多数编程语言的惯用启动入口
fn main() {
    // 带有 ! 的是宏, 不是函数/方法
    println!("========== 猜数游戏 ==========");
    // 生成一个随机数
    let secret_number = rand::thread_rng().gen_range(1, 101);
    // loop 是个死循环, 需要在合适的位置调用 break 跳出循环
    loop {
        println!("\n请输入:");
        // 创建一个可变的空字符串实例 用于接收用户输入的内容
        let mut guess = String::new();
        // 从控制台(标准输入流)读取一行内容
        let result = io::stdin().read_line(&mut guess);
        // 处理可能存在的错误
        result.expect("无法读取您输入的内容!");
        // 将字符串类型转换为整数类型
        let guess: u32 = match guess.trim().parse() {
        //  ^^^^^ 这里标识符的重名在 rust 内是允许的, 此时上一个同名的标识符将被隐藏起来
            Ok(number) => number,
            _ => {
                println!("您输入的不是一个正整数!");
                continue; // 跳出本次循环
            }
        };
        // match 表达式与 Java 中的 switch 表达式很相似
        // 但是 match 不需要手动使用 break 跳出分支
        match guess.cmp(&secret_number) {
            Ordering::Less => println!("猜小了"),
            Ordering::Greater => println!("猜大了"),
            Ordering::Equal => {
                println!("恭喜您猜对了!");
                break; // 跳出循环
            }
        }
    }
}
  • 编译运行看看最终效果
> cargo run
......
========== 猜数游戏 ==========

请输入:
50
猜小了

请输入:
80
猜小了

请输入:
90
猜小了

请输入:
95
恭喜您猜对了!

这是一个 rust 入门程序

需要关注的地方我已经在代码注释中详细标注

如果对我分享的内容感兴趣的话  记得关注我得动态
求推荐  求收藏  求转发  求关注
posted @ 2021-02-01 19:34  Delayer  阅读(247)  评论(0)    收藏  举报