Rust: Guess the Number ;)
Specially, writing this blog for someone who knows C and wants to learn rust.
Hello Rust Enthusiast! And if you’re not one already, let me tell you — Rust is the future. Just kidding 😆! In this blog post, I’ll be sharing the first program I developed while learning Rust. As per their official documentation, it is recommended to start with the Guessing Game, so that’s what I did. PS: I mostly follow documentation 🫡.
About Rust
Rust is a programming language that is distinct from the ones I’ve previously studied, such as CPP, Java, and Python. While Rust is a little similar to C in that it is a low-level language with direct access to hardware resources, the syntax differs significantly.
The interesting thing about Rust programming language is that all of its variables are immutable by default. After reading from a few sources, I came to know the reason behind it. This feature prevents the programmer from accidentally reassigning a value to a variable (which they do not intend to do), which is also known as Shadowing in technical terms. It alerts the programmer that they may have modified something that they did not want to.
Let’s begin coding
To set up the Rust environment, you can refer to their official documentation. Alternatively, you can also use the Rust playground.
Similar to C programming language, Rust also has a main function. When you hit the run button, the execution begins from the main()
function. Therefore, for this program, we will write all our code in the main()
function.
fn main() {
// Your code goes here
}
Observe how the functions are declared in Rust. We use the keyword fn
which is then followed by the function name. Then the name is followed by parenthesis in which we can declare the parameters of the function.
Importing Crates
Crates are containers that hold a piece of code designed to perform a specific task and can be readily used in a program like inbuilt modules. For our program, we will require three crates: std::io
, rang::Rng
and std::cmp
. We can include all of these crates using the use
keyword
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("Guessing Game");
}
As you may have guessed from their name, the std::io
crate is used to scan input that is entered by the user, while the rand::Rng
function generates a random number that makes our game interesting by requiring the user to guess a new number each time. The std::cmp
is used to implement the if-else
in Rust since we are not using the if-else
statement directly in our program. 😞
After compiling and executing the above code you’ll get the following output:
Note that we use, the println!()
function for printing the output on the screen.
Reading the input
In this program, we need to read the number that the user guesses. To achieve this, we will first declare a variable to store the number. As I mentioned above in Rust, variables are immutable by default. Therefore, we need to make it mutable using the mut
keyword.
// Declaring variable in RUST
let mut guess = String::new();
In the upcoming blogs, we will discuss variable declarations in more detail. Moving on, our next step is to take the user input and store it in the 'guess' variable. We can do this by using the read_line()
function of the stdin
module. Additionally, we can use an expect()
function to raise an exception in case of errors.
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("Guessing Game");
println!("Enter you guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Could not read the line.");
}
As you can see in the code above, we have declared the variable guess
as a string. This is because when we read input from the standard input in Rust, it is read as a string by default. However, we need to convert this string into an integer using the parse()
function. This is necessary so that we can compare the integer value of the guess with our secret number.
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("Guessing Game");
println!("Enter you guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Could not read the line.");
let guess: u32 = guess.trim().parse().expect("Please enter number.");
}
Generating Random Number
To make our game more fun, we need to generate a random number each time the user runs the program. To achieve this, we have already imported the random number library.
Now you have to open the cargo.toml
file and add rand to the dependencies.
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"
Declare a variable called _secretkey
as shown below:
let _secretkey = rand::thread_rng().gen_range(1..=10);
// The thread_rng() is used to select a number randomly
// The gen_range() fuction gives the upper and lower limit for selecting a number
// For this program the range is 1 to 10.
Adding the above line of the code to your program, you’ve created a _secretkey
which the user has to guess.
Comparing the guess
Unfortunately, we are not using the if-else statement in Rust. Hence, we have to use the std::cmp::Ordering
type. The Ordering is a type of enum that has the variants Less
, Greater
, and Equal
. We can get any of the above-mentioned outputs by comparing two values.
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("Guessing Game");
let _secretkey = rand::thread_rng().gen_range(1..=10);
println!("Enter you guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Could not read the line.");
let guess: u32 = guess.trim().parse().expect("Please enter number.");
// Comparing guess with the secretkey
match guess.cmp(&_secretkey) {
Ordering::Less => println!("Guessed to low"),
Ordering::Equal => println!("You win"),
Ordering::Greater => println!("Guessed to high"),
}
}
In the above code, we use the match
expression consisting of a pattern to match against, and the code that should be run if the value given to match
fits that arm’s pattern.
In the given code snippet, we use the cmp()
function to compare the two values. We pass the _secretkey
as reference to the cmp()
that compares it’s value with the guess
variable.
Basically, We use a
match
expression to decide what to do next based on which variant ofOrdering
was returned from the call tocmp
with the values inguess
andsecret_number
.
Loop
Now, our code works fine. But isn’t it frustrating that you don’t get another chance after you guess the number once? So let’s make the game more efficient by adding a loop. To add a loop in Rust, we simply use the loop
keyword. Note that you have to include a break
statement within the loop, otherwise, it'll turn into an infinite loop.
loop{
// Your code goes here
// if someting happens
break;
}
So, let’s modify our guessing game accordingly. We’ll break out of the loop once the user wins the game.
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
println!("Guessing Game");
let _secretkey = rand::thread_rng().gen_range(1..=10);
loop {
println!("Enter you guess:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Could not read the line.");
let guess: u32 = guess.trim().parse().expect("Please enter number.");
match guess.cmp(&_secretkey) {
Ordering::Less => println!("Guessed to low"),
Ordering::Equal => {
println!("You win");
break;
}
Ordering::Greater => println!("Guessed to high"),
}
}
}
Voila! You’ve created a guessing game in Rust. 🥳
Conclusion
That’s all for today. I will be writing more blogs on Rust in the upcoming weeks, so please make sure to hit the follow button. If you notice any mistakes in this blog or have suggestions on how to optimize the code, please leave your comments below. I am eagerly waiting for your feedback and would love to hear whether you found this blog helpful or not. If you are facing any problems with the code, feel free to message me on my socials. Thank you and stay tuned for more. 😄