c语言编写猜灯谜程序,Rust学习笔记#1:一个猜谜游戏小项目

2023-11-20 16:59

本文主要是介绍c语言编写猜灯谜程序,Rust学习笔记#1:一个猜谜游戏小项目,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在深刻探索Rust语法的细枝末节以前,先经过一个麻雀虽小但五脏俱全的小项目来总体把握Rust,这样能够避免迷失在细节的海洋中。咱们可能会经过这个小项目一会儿接触到不少新概念,但没必要惊慌,咱们只需浅尝辄止对这些概念有个印象便可。git

《TRPL》(Rustaceans对《The Rust Programming Language》的爱称)中就给出了一个经典的猜谜游戏的例子,咱们一块儿来学习它。编程

猜谜游戏:程序将会随机生成一个 1 到 100 之间的随机整数。接着它会请玩家猜一个数并输入,而后提示猜想是大了仍是小了。若是猜对了,它会打印祝贺信息并退出。安全

Rust如何管理项目

并非全部的代码都像hello_world.rs同样,一个文件就能够搞定。一个项目每每具备复杂的代码,咱们须要一种机制来管理这种复杂性,将一个项目切分红若干小部分,每一个部分再进行切分,层层抽象,直到达到人脑能够处理的规模。每种编程语言都有这样的机制,例如Java的package机制,Rust也不例外。编程语言

Rust用了两个概念来管理项目:一个是crate(项目),一个是mod(模块)。模块是用于在crate内部进行分层和封装的机制,模块内部能够包含模块。函数

crate:能够简单理解为一个项目,crate是Rust中的独立编译单元(compile unit),每一个crate对应生成一个库或者可执行文件。做为对比,咱们比较熟悉的C语言中,一个单独的.c文件和其全部的include文件组成一个编译单元,每一个.c生成一个.o,而后将这些.o连接起来生成可执行文件。

mod:能够简单理解为命名空间。mod能够嵌套(注意crate之间不能出现循环引用),还能够控制内部元素的可见性。

说到可见性问题,在Rust中,元素默认都是私有的,用pub关键字修饰的才是公开的。公开和私有的访问权限规定以下:oop

若是一个元素是私有的,那么只有本模块内的元素以及它的子模块能够访问

若是一个元素是公开的,那么能够在本模块外的做用域访问它。

模块是一种抽象的概念,文件是承载这个概念的实体,可是模块和文件并非简单的一一对应关系。在一个crate内部建立mod的方式有下面三种:学习

在一个rs文件中建立内嵌模块,直接使用mod关键字便可。

独立的一个rs文件就是一个模块,文件名便是模块名。

一个文件夹也能够建立一个模块,文件夹内部要有一个xxx.rs文件,这个文件是这个模块的入口。必需要在这个xxx.rs中声明其子模块,不然子模块没法被当成这个项目的源码进行编译。

新建项目

cargo不只是Rust的包管理器,还能够用于建立项目。使用下列命令能够建立一个名为guessing_game的项目:优化

cargo new guessing_game --bin

注意,后面的--bin意味着咱们但愿项目生成的是可执行程序,若是但愿是library,则可使用--lib选项。ui

以上为在命令行中手工建立项目,在Clion中能够点击File->New Project后以下图填写,而后点击Create按钮:编码

beab521291aa44ba25c095fdc8350852.png

项目结构

咱们可使用tree .命令或者直接在Clion中查看当前的文件夹结构,以下图所示:

11d36191517bdb9cc6a94d9242960ce2.png

src/main.rs:这是cargo自动生成的rs文件。还记得前面讲的crate和mod的概念吗?在这个项目中,guessing_game是crate,src文件夹是mod,main.rs是srcmod的入口。咱们能够在srcmod中建立子模块,但注意,这些子模块都要在main.rs中声明,不然没法参与编译。

.gitignore:这是git忽略文件,不懂其做用的同窗能够自行搜索。这里重点要说的是经过cargo new建立的项目自然就是一个git项目,这也印证了Rust对开源的拥护。

Cargo.toml:这是项目管理配置文件。TOML是一种很是简洁好用的配置文件格式,TOML是Tom's Obvious, Minimal Language的首字母缩写,这里的Tom是Github的联合创始人之一,感兴趣的同窗能够进一步自行了解TOML配置文件的写法。

Cargo.lock:该文件包含项目依赖项的确切信息,由Cargo维护,咱们无须关心它。

编译执行

在src/main.rs里cargo已经自动生成了输出Hello, world!的代码,咱们来运行一下它看可否正常输出。

插一句题外话,在你往后漫长的Rust编码生涯中,你会发现,你将在处理编译错误上耗费大量的时间。还记得吗,Rust 的一大特点是保证内存安全,这保证了Rust代码只要运行起来就几乎不会发生内存错误,这么诱人的效果的背后的代价就是,咱们要在编码时付出额外的努力。Rust为了保证内存安全设计了一套复杂的规则,这致使咱们的代码一不留神就会编译不过。因此,在你往后常常用的一个操做就是检查可否编译经过,而不是直接编译,由于直接编译还要作代码优化等会相对费时。可使用下列命令检查编译错误:

cargo check

在Clion中须要新加一个Configuration来执行cargo check命令,以下图所示:

f28091b596679958954b74abaf2cdf19.png

确保cargo check经过后,能够执行cargo build来执行编译。编译后会产生一个target文件夹,在target/debug下会有一个和crate同名的可执行文件。但通常为了方便,能够直接执行cargo run,这条命令等价于先编译后执行。下图是执行cargo run后Clion的控制台输出:

ad154ec855513a69c41406052c150d8e.png

猜谜游戏

在完成了项目搭建后,接下来就要开始猜谜游戏的代码编写了,我将它们分红六部分:建立变量、输入、输出、错误处理、随机数生成、完整代码。

建立变量

使用let语句建立变量,须要注意的是,在Rust中,变量默认是不可变的,能够在变量名前使用mut来使得变量可变:

let a = 5; // 不可变

let mut b = 10; // 可变

在上面的let语句中,咱们并无显示声明变量的类型,但这并不表明Rust是动态类型的,Rust仍然是静态类型的,只不过Rust有一个能够经过上下文推断类型的强大编译器。

输出

咱们早已在hello_world.rs中见识过了最基本的输出方式:

println!("Hello, world!");

须要注意的是,这里的println!是一个宏,而非一个函数,println后面的感叹号就是宏的标志。Rust中的宏与C/C++中的宏是彻底不同的东西,简单说,能够把它理解为一种安全版的编译期语法扩展。这里之因此使用输出宏而非函数,是由于标准输出宏能够完成编译期格式检查,更加安全。

若是须要输出某个变量的值,可使用占位符{},例如:

let x = 0;

let y = 10;

println!("x = {} and y = {}", x, y);

其输出结果为:

x = 0 and y = 10

输入

为了从控制台中获取用户的输入,须要使用标准库std::io。使用use语句将该库引入当前做用域:

use std::io;

咱们可使用io库中的函数stdin:

let mut guess = String::new(); // 建立一个字符串类型的可变变量

io::stdin().read_line(&mut guess).expect("Failed to read line");

stdin函数返回一个std::io::Stdin的实例,这表明终端标准输入句柄的类型。而后调用read_line方法,能够从标准输入中读取一行并存入到guess变量中去。&表示这是一个引用,这是一个复杂的特性,咱们如今无须了解它。

读取用户输入后,咱们须要判断用户是否正确输入了数字。String类型带有处理字符串处理的一些方法:

let guess: u32 = guess.trim().parse().expect("Please type a number!");

字符串的 parse方法将字符串解析成数字。由于这个方法能够解析多种数字类型,所以须要告诉 Rust 具体的数字类型,这里经过 let guess: u32 指定。guess后的冒号:告诉 Rust 咱们指定了变量的类型。Rust 有一些内建的数字类型,u32 是一个无符号的 32 位整型。trim方法用于消除回车空格等符号。

错误处理

上一小节代码中还有一个expect没有分析,而这就涉及到Rust中的错误处理机制了。read_line的返回值类型是io::Result,它是Result类型在io模块的特化版本。Result是枚举类型,其成员为Ok和Err,Ok 成员表示操做成功,内部包含成功时产生的值。Err成员则意味着操做失败,而且包含失败的来龙去脉。

Result类型的做用是编码错误处理信息。Result类型像其余类型同样,拥有定义于其上的方法。io::Result的实例拥有expect方法。若是 io::Result实例的值是 Err,expect 会致使程序崩溃,并打印参数传递给 expect的信息。若是io::Result实例的值是 Ok,expect会获取 Ok中的值并返回。在本例中,这个值是用户输入到标准输入中的字节数。

随机数生成

猜谜游戏须要可以自动生成随机数。Rust标准库中还没有包含随机数功能,但咱们能够经过引入外部crate来得到随机数功能。还记得Rust的官方开源仓库吗,那里但是有不少宝贝的。打开https://crates.io/,在搜索框中键入rand来搜索具备随机数功能的crate,出来的第一个结果就是咱们须要的crate。

9682de6dbddfe57f71a706f6b2959698.png

如今咱们将这个库引入到咱们的项目中。打开Cargo.toml,在[dependencies]下添加:

[dependencies]

rand = "0.8.3"

[dependencies] 告诉 Cargo 本项目依赖了哪些外部 crate 及其版本。

下面使用rand库来产生随机数。首先,使用use语句引入rand,use rand::Rng;。而后调用下列函数产生一个1和100之间的数:

let number = rand::thread_rng().gen_range(1..=100);

完整代码

猜谜游戏的完整代码以下。

use std::io;

use std::cmp::Ordering;

use rand::Rng;

fn main() {

println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1..=100);

loop {

println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)

.expect("Failed to read line");

let guess: u32 = match guess.trim().parse() {

Ok(num) => num,

Err(_) => continue,

};

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {

Ordering::Less => println!("Too small!"),

Ordering::Greater => println!("Too big!"),

Ordering::Equal => {

println!("You win!");

break;

}

}

}

}

其中,涉及控制流操做的loop、match、continue、break等语法,你们应当可以望文生义。对于这个完整代码,你们可以阅读并知道每一行干了啥便可,没必要纠结于语法细节。

猜谜游戏运行结果以下:

6989fcb626d848b122794d2c59c8990f.png

参考文献

《The Rust Programming Language》

《Rust编程之道》张汉东

《深刻浅出Rust》范长春

这篇关于c语言编写猜灯谜程序,Rust学习笔记#1:一个猜谜游戏小项目的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/396094

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss