Can I improve following code? Is it possible to avoid converting String to Vector?
use std::fs::File;
use std::borrow::Cow;
use std::io::{self, BufRead};
use std::io::Read;
use std::io::Write;
use std::path::Path;
use rand::Rng;
fn get_word<'a>(filename: &'a str) -> Option<String> {
match File::open(filename) {
Ok(file) => {
let lines = io::BufReader::new(file).lines();
let linesVec: Vec<_> = lines.map(|x| x.unwrap()).collect();
let mut rng = rand::thread_rng();
let num = rng.gen_range(0, linesVec.len() - 1);
// println!("{}", num);
//println!("{}", linesVec[num]);
return Some(linesVec[num].clone());
},
Err(e) => {
eprintln!("Could not open file: {}", e);
return None;
}
}
}
fn main() {
if let word = get_word("words.txt").unwrap() {
let mut guess = 7;
let mut length = word.len();
let mut gword : Vec<char> = word.chars().map(|x| '_').collect();
let mut oword : Vec<char> = word.chars().map(|x| x).collect();
loop {
if guess == 0 {
println!("Sorry you have run out of guesses :(");
println!("{:?}", oword);
break;
}
if length == 0 {
println!("Congratulations you have guess correct word: {}", word);
break;
}
println!("The word so far is: {:?}", gword);
println!("You have {} guesses left", guess);
print!("Please guess a character: ");
io::stdout()
.flush()
.expect("Error flushing stdout. ");
let mut c = String::new();
io::stdin()
.read_line(&mut c)
.expect("Error reading char.");
let ch = c.chars().nth(0).unwrap();
//println!("{}", ch);
match oword.iter().position(|& c| c == ch) {
Some(ind) => {
oword[ind] = '_';
gword[ind] = ch;
length -= 1;
},
None => {
guess -= 1;
}
}
}
println!("{:?}", gword);
}
}
Errors:
Compiling playground v0.0.1 (/playground)
warning: unused import: `std::borrow::Cow`
--> src/main.rs:2:5
|
2 | use std::borrow::Cow;
| ^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `std::io::Read`
--> src/main.rs:4:5
|
4 | use std::io::Read;
| ^^^^^^^^^^^^^
warning: unused import: `std::path::Path`
--> src/main.rs:6:5
|
6 | use std::path::Path;
| ^^^^^^^^^^^^^^^
warning: irrefutable if-let pattern
--> src/main.rs:28:5
|
28 | / if let word = get_word("words.txt").unwrap() {
29 | | let mut guess = 7;
30 | | let mut length = word.len();
31 | | let mut gword : Vec<char> = word.chars().map(|x| '_').collect();
... |
66 | | println!("{:?}", gword);
67 | | }
| |_____^
|
= note: `#[warn(irrefutable_let_patterns)]` on by default
warning: unused variable: `x`
--> src/main.rs:31:55
|
31 | let mut gword : Vec<char> = word.chars().map(|x| '_').collect();
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
= note: `#[warn(unused_variables)]` on by default
warning: variable `linesVec` should have a snake case name
--> src/main.rs:13:17
|
13 | let linesVec: Vec<_> = lines.map(|x| x.unwrap()).collect();
| ^^^^^^^^ help: convert the identifier to snake case: `lines_vec`
|
= note: `#[warn(non_snake_case)]` on by default
warning: 6 warnings emitted
Finished dev [unoptimized + debuginfo] target(s) in 1.00s
Running `target/debug/playground`
Could not open file: No such file or directory (os error 2)
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:28:41
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace