Lecture 6 - Guessing Game Part 2: VSCode & Completing the Game

Learning objectives

By the end of class today you should be able to:

  • Use VSCode with rust-analyzer and the integrated terminal for Rust development
  • Start using loops and conditional logic in Rust
  • Use match expressions and Ordering for comparisons
  • Keep your code tidy and readable with clippy, comments, and doc strings

Why VSCode for Rust?

  • Rust Analyzer: Real-time error checking, autocomplete, type hints
  • Integrated terminal: No more switching windows
  • Git integration: Visual diffs, staging, commits

Setting up VSCode for Rust

You'll need to have

  • Installed VSCode
  • Installed Rust
  • Installed the rust-analyzer extension

Joey covered this in discussions - if you need help with these come talk to us

Opening our project

From the terminal:

cd guessing_game
code .

or use File -> Open Folder from VSCode

VSCode Features Demo

File Explorer & Navigation

  • Side panel for project files
  • Quick switching with Cmd+P (Mac) / Ctrl+P (Windows)
  • Split editor views

Integrated Terminal

  • View → Terminal or Ctrl+`
  • Multiple terminals
  • Same commands as before: cargo run, cargo check

Rust Analyzer in Action

  • Red squiggles - Compiler errors
  • Yellow squiggles - Warnings
  • Hover tooltips - Type information
  • Autocomplete - As you type suggestions
  • Format on save - Automatic code formatting

Let's see it in action!

Cargo Clippy

  • Run with cargo clippy in terminal to see suggestions
  • Suggests stylistic changes that won't change the function of your code (ie refactoring suggestions)
  • cargo clippy --fix will automatically accept suggestions

Completing The Guessing Game

Highlights from the compiler errors activity

Let's chat about these together

  • Lots of folks hit on something like this - what happened?
"1. error ""error[E0433]: failed to resolve: use of unresolved module or unlinked crate `rand`
 --> main.rs:8:25"""
  • Then playing around, people found:
-  expected `;`, found keyword `let` (deleted a semicolon)
-  invalid basic string b/c removed ""
-  linking with `link.exe` failed: exit code: 1
-  expected function, found macro `println`   (got rid of ! in println!)
-  cannot borrow `guess` as mutable, as it is not declared as mutable   (got rid of mut in declaration)
-  this file contains an unclosed delimiter (deleted a curly bracket)
-  unresolved import `std::higang`
-  failed to resolve: use of unresolved module or unlinked crate `io`
-  unreachable expression (placed code after break)

Let's walk through an interesting one

One student used cargo add rand rather than manually adding rand to the dependencies (which is totally valid!), and go this. What's going on?

warning: use of deprecated function `rand::thread_rng`: Renamed to `rng`
 --> src\main.rs:8:31
  |
8 |     let secret_number = rand::thread_rng().gen_range(1..=100);
  |                               ^^^^^^^^^^
  |
  = note: `#[warn(deprecated)]` on by default
warning: use of deprecated method `rand::Rng::gen_range`: Renamed to `random_range`
 --> src\main.rs:8:44
  |
8 |     let secret_number = rand::thread_rng().gen_range(1..=100);
  |                                            ^^^^^^^^^

warning: `scavenger_hunt` (bin ""scavenger_hunt"") generated 2 warnings

Current state (from last class):

use std::io;
use rand::Rng;

fn main() {
    println!("Guess the number!");
    
    let secret_number = rand::thread_rng().gen_range(1..=100);
    println!("The secret number is: {secret_number}");
    
    println!("Please input your guess.");
    
    let mut guess = String::new();
    
    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");
    
    println!("You guessed: {}", guess);
}

Making it a real game:

  1. Remove the secret reveal - no cheating!
  2. Compare numbers - too high? too low?
  3. Add a loop - keep playing until correct
  4. Handle invalid input - what if they type "banana"?

Steps 0+1

Step 0: No cheating

We just need to delete:

#![allow(unused)]
fn main() {
println!("The secret number is: {secret_number}");
}

Step 1: Comparing Numbers

First, we need to convert the guess to a number and compare:

#![allow(unused)]
fn main() {
use std::cmp::Ordering; // typically crate :: module :: type or crate :: module :: function

// Add this after reading input:
let guess: u32 = guess.trim().parse().expect("Please enter a number!");

match guess.cmp(&secret_number) {
    Ordering::Less => println!("Too small!"),
    Ordering::Greater => println!("Too big!"),
    Ordering::Equal => println!("You win!"),
}
}

Step 2: Adding the Loop

Wrap the input/comparison in a loop:

#![allow(unused)]
fn main() {
loop {
    println!("Please input your guess.");
    
    // ... input code ...
    
    match guess.cmp(&secret_number) {
        Ordering::Less => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal => {
            println!("You win!");
            break;  // Exit the loop
        }
    }
}
}

Step 3: Handling Invalid Input

Replace .expect() with proper error handling:

#![allow(unused)]
fn main() {
let guess: u32 = match guess.trim().parse() {
    Ok(num) => num,
    Err(_) => {
        println!("Please enter a valid number!");
        continue;  // Skip to next loop iteration
    }
};
}

Back to VSCode

Completing the game

Let's paste the whole thing in and take a look

Comments & Documentation Best Practices

What would happen if you came back to this program in a month?

Inline Comments (//)

  • Explain why, not what the code does
  • Bad: // Create a random number
  • Good: // Generate secret between 1-100 for balanced difficulty
  • If it's not clear what the code does you should edit the code!

Doc Comments (///)

  • Document meaningful chunks of code like functions, structs, modules
  • Show up in cargo doc and IDE tooltips
#![allow(unused)]
fn main() {
/// Prompts user for a guess and validates input
/// Returns the parsed number or continues loop on invalid input
fn get_user_guess() -> u32 {
    // implementation...
}
}

The Better Comments extension

  • Color-codes different types of comments in VSCode - let's paste it into main.rs and see
#![allow(unused)]
fn main() {
// TODO: Add input validation here
// ! FIXME: This will panic on negative numbers
// ? Why does this work differently on Windows?
// * Important: This function assumes sorted input
}

Visual Git Features:

  • Source Control panel - See changed files
  • Diff view - Side-by-side comparisons
  • Stage changes - Click the + button
  • Commit - Write message and commit

Still use terminal for:

  • git status - Quick overview
  • git log - Commit history
  • git push / git pull - Syncing

Activity Time (20 minutes)

VSCode and GitHub Classroom

Wrap-up

What we've accomplished so far:

  • Can now use shell, git, and rust all in one place (VSCode)
  • We built a complete, functional game from scratch
  • Started learning key Rust concepts: loops, matching, error handling
  • We've practiced using GitHub Classroom - you'll use it for HW2!

Looking ahead

  • HW1 due tonight at midnight
  • HW2 released this evening
  • Discussions tomorrow will focus on getting started on HW2