首页 > 其他分享 >Rust学习笔记——基于官网和Rust语言圣经(二、猜数游戏)

Rust学习笔记——基于官网和Rust语言圣经(二、猜数游戏)

时间:2023-06-25 13:22:25浏览次数:42  
标签:std guess 猜数 Ordering number let println 官网 Rust

前面的hello world项目还是太old school了,这样用一个猜数字的游戏来快速了解下rust语言,以及为啥cargo那么好用的原因。不要拘束新的语法点,后面都会详细介绍!

2.1猜数游戏:一次猜测

-本节您将学会:

·let、match等方法

·相关的函数

·外部的crate

·...

猜数游戏-目标

-生成一个1到100间的随机数

-提示玩家输入一个猜测

-猜完之后,程序会提示猜测是太小了还是太大了

-如果猜测正确,那么打印出一个庆祝信息,程序退出

代码1

use std::io; // prelude
​
fn main() {
    println!("猜数!");
​
    println!("猜测一个数");
​
    let mut guess = String::new(); //设置guess为可变的 rust默认情况下变量不可变
​
    io::stdin().read_line(&mut guess).expect("无法读取行"); // 引入一个stdin库,通过read_line获得用户输入,并放入guess中,guess也需要可变的(随着用户的输入而改变),&取地址符号:表示引用,在代码不同地方访问同一个数据。expect:若是错误就会终止运行
​
    println!("你猜测的数是:{}",guess); //{},按照后面顺序,显示
​
}

代码说明:

默认变量不可变如:

    let foo = 1;
    let bar = foo; // immutable
    foo = 2;

read_line()返回一个io::Result

io::Result Ok,Err

ok表示操作成功

Err表示操作失败,还包括失败的原因

运行结果:

2.2猜数游戏:生成神秘数字

库的网站:https://crates.io/

比如我们要用生成随机数的库及其介绍

如何添加包

在cargo.toml的dependencies下添加需要的包

由于我们装了vs插件所以自己都安装了,不然是需要自己cargo build更新的

这里更新下,改成rand = "0.7.3"

更新完后,可以打开cargo.lock中可以看到更新好的包。类似于npm思想

这样的好处:如果有新的包会对项目产生冲突,但是这个lock记录了开发者用的包,这样所有人拿到你的项目都可以直接运行。cargo lock不要自己手动修改!

代码

use std::io; // prelude
use rand::Rng; // trait
​
fn main() {
    println!("猜数游戏!");
​
    let secret_number = rand::thread_rng().gen_range(1, 101);
​
    println!("神秘数字是:{}",secret_number);
​
    println!("猜测一个数");
​
    let mut guess = String::new(); 
​
    io::stdin().read_line(&mut guess).expect("无法读取行");
​
    println!("你猜测的数是:{}",guess);
​
}

运行结果

2.3猜数游戏:比较猜测数字与神秘数字

引入std::cmp::Ordering: 他有三个枚举类型,分别是大小等于。

use std::io; // prelude
use rand::Rng; // trait
use std::cmp::Ordering;
​
fn main() {
    println!("猜数游戏!");
    let secret_number = rand::thread_rng().gen_range(1, 101);
    println!("神秘数字是:{}",secret_number);
    println!("猜测一个数");
    let mut guess = String::new(); 
    io::stdin().read_line(&mut guess).expect("无法读取行");
    println!("你猜测的数是:{}",guess);
​
    match guess.cmp(&secret_number){
        std::cmp::Ordering::Less => println!("Too small!"),
        std::cmp::Ordering::Equal => println!("You win!"),
        std::cmp::Ordering::Greater => println!("Too big!"),
    }
}
​

若直接运行会报错,因为比较两个值的类型不一样。

代码

use std::io; // prelude
use rand::Rng; // trait
​
​
fn main() {
    println!("猜数游戏!");
    let secret_number = rand::thread_rng().gen_range(1, 101); //i32 u32 i64
    println!("神秘数字是:{}",secret_number);
    println!("猜测一个数");
    let mut guess = String::new(); 
    io::stdin().read_line(&mut guess).expect("无法读取行");
    println!("你猜测的数是:{}",guess);
​
    // shadow
    let guess:u32 = guess.trim().parse().expect("Please type a number!"); //trim把前后空格去掉(包括回车\n) parse把字符串解析成某种数字类型
​
    match guess.cmp(&secret_number){
        std::cmp::Ordering::Less => println!("Too small!"),
        std::cmp::Ordering::Equal => println!("You win!"),
        std::cmp::Ordering::Greater => println!("Too big!"),
    }
}

rust为静态的强类型语言

需要把guess从string变成u32,这里修改后,本来是i32的secret_number也会变成u32,此外我们可以看到,rust中可以使用重复变量,来减少损耗,且智能上下文推理的能力。

运行结果

猜数游戏:允许多次猜测

如要无限猜测需要加入无限循环

代码

use std::io; // prelude
use rand::Rng; // trait
​
​
fn main() {
    println!("猜数游戏!");
    let secret_number = rand::thread_rng().gen_range(1, 101); //i32 u32 i64
    println!("神秘数字是:{}",secret_number);
​
    loop {
        println!("猜测一个数");
        let mut guess = String::new(); 
        io::stdin().read_line(&mut guess).expect("无法读取行");
        println!("你猜测的数是:{}",guess);
​
        // shadow
        let guess:u32 = guess.trim().parse().expect("Please type a number!");
​
        match guess.cmp(&secret_number){
            std::cmp::Ordering::Less => println!("Too small!"),
            std::cmp::Ordering::Equal => println!("You win!"),
            std::cmp::Ordering::Greater => println!("Too big!"),
        }
    }
   
}

将猜测部分代码放入loop循环中,即可完成。

运行结果

我们可以看到可以实现,但是还有一点点不健壮性。比如我们输入的不是数字呢?还有猜测都成功了,应该退出程序啊!

修改

先处理不能退出循环的问题:

use std::io; // prelude
use rand::Rng; // trait
use std::cmp::Ordering;
​
​
fn main() {
    println!("猜数游戏!");
    let secret_number = rand::thread_rng().gen_range(1, 101); //i32 u32 i64
    println!("神秘数字是:{}",secret_number);
​
    loop {
        println!("猜测一个数");
        let mut guess = String::new(); 
        io::stdin().read_line(&mut guess).expect("无法读取行");
        println!("你猜测的数是:{}",guess);
​
        // shadow
        let guess:u32 = guess.trim().parse().expect("Please type a number!");
​
        match guess.cmp(&secret_number){
            Ordering::Less => println!("Too small!"),
            Ordering::Equal => {
                println!("You win!");
                break; //rust退出循环也是break
            },
            Ordering::Greater => println!("Too big!"),
        }
    }
   
}

在判断等于的时候加入break跳出循环!

修复非数字输入:

我们可以利用expect返回ok和err来进行一个match选择。

use std::io; // prelude
use rand::Rng; // trait
use std::cmp::Ordering;
​
​
fn main() {
    println!("猜数游戏!");
    let secret_number = rand::thread_rng().gen_range(1, 101); //i32 u32 i64
    // println!("神秘数字是:{}",secret_number);
​
    loop {
        println!("猜测一个数");
        let mut guess = String::new(); 
        io::stdin().read_line(&mut guess).expect("无法读取行");
        println!("你猜测的数是:{}",guess);
​
        // shadow
        let guess:u32 = match guess.trim().parse(){
            Ok(num) => num, // ok就正常赋值
            Err(_) => continue, // 错误就重新输入,_表示不关心错误信息
        };
​
        match guess.cmp(&secret_number){
            Ordering::Less => println!("Too small!"),
            Ordering::Equal => {
                println!("You win!");
                break; //rust退出循环也是break
            },
            Ordering::Greater => println!("Too big!"),
        }
    }
   
}

未完待续

标签:std,guess,猜数,Ordering,number,let,println,官网,Rust
From: https://www.cnblogs.com/lightwower/p/17502696.html

相关文章

  • pgcat 基于rust 开发类似pgbouncer 的数据库链接池以及proxy 工具
    pgcat是postgresml团队开源的,pg链接池以及proxy工具,包含了不少特性特性事物pool,类似pgbouncer,对于异常客户端以及遗弃事物处理做了提升sessionpool类似pgbouncer多线程运行时读查询负载均衡,对于primary以及replicas进行自动负载均衡故障转移,支持健康检查admin统计数据库,类......
  • QNX-9—QNX官网文档翻译—Understanding QNX Virtual Environments
    注:翻译自QNXHypervisor-->QNXHypervisor2.2User's-->UnderstandingQNXVirtualEnvironmentshttps://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.hypervisor.user/topic/virt/virt.html一、概述QNX虚拟机管理程序旨在满足Popek/Goldberg(波佩克/戈德堡)......
  • QNX-9—QNX官网文档翻译—Programming Overview
    注:翻译网址QNXSoftwareDevelopmentPlatform-->Programming-->Programmer'sGuide-->ProgrammingOverviewhttps://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.prog/topic/overview.html一、概述QNXNeutrinoRTOS架构由微内核和一些协作进程组......
  • rust 集合、错误处理、泛型、Trait、生命周期、包
    集合组织特性相同的数据;泛型可以定义任何抽象数据类型;生命周期限制所有权的作用域范围;错误处理使程序更健壮。集合一组特性相同的数据集合,除了基本数据类型的元组、数组。rust标准库提供了一些非常有用的数据结构。Vector存储列表通过类型Vec<T>定义。只能存储相同类型的值,......
  • 霸道总裁式:不准使用Rust商标
    由拥有Rust和Cargo商标的Rust基金会起草的一项拟议新商标政策在更广泛的Rust社区中引起不满情绪,这要归功于限制,包括禁止自定义Rust工具或用Rust编写的软件使用Rust为名字,或在域名或子域的部分内容中使用名字Rust。4月7日,基金会发布了新政策草案,并通过谷歌表格征求意见,......
  • 聊一聊 Rust 的 stack overflow
    早上看到了这篇文章智能指针有可能会让你的应用崩溃,下面分析一下会导致stackoverflow的代码structNode<T>{val:T,next:Option<Box<Node<T>>>,}structLinkedList<T>{head:Option<Box<Node<T>>>,}impl<T>LinkedList<T&......
  • Rust语言 - 接口设计的建议之受约束(Constrained)
    Rust语言-接口设计的建议之受约束(Constrained)RustAPI指南GitHub:https://github.com/rust-lang/api-guidelinesRustAPI指南中文:https://rust-chinese-translation.github.io/api-guidelines/RustAPI指南:https://rust-lang.github.io/api-guidelines/受约束(Constrai......
  • rust进阶手册(1)
    目录安装管理和配置工具项目管理类型字面值格式输出位置参数格式化文本命名参数类型转换浮点字面值字符类型数组元组安装不管OS是否带有rust,都应使用rustup来安装rustlinux/freebsdcurlhttps://sh.rustup.rs-sSf|shwindowshttps://www.rust-lang.org/tools/install......
  • Rust语言 - 接口设计的建议之显而易见(Obvious)
    Rust语言-接口设计的建议之显而易见(Obvious)RustAPI指南GitHub:https://github.com/rust-lang/api-guidelinesRustAPI指南中文:https://rust-chinese-translation.github.io/api-guidelines/RustAPI指南:https://rust-lang.github.io/api-guidelines/显而易见(Obvious)......
  • CMake官网教程学习
    简介本文档是根据CMake的官方教程学习的笔记,同时将教程中C++实现的代码更改为C语言实现。当前还未学习完。教程官网:CMakeTutorial—CMake3.27.0-rc1Documentation中文教程:教程—CMake3.26.4Documentation(cmake-doc.readthedocs.io)官方教程源码下载:https://cmake.o......