Skip to content

Instantly share code, notes, and snippets.

@typebird
Last active September 6, 2020 14:30
Show Gist options
  • Save typebird/3159c961f0e8ccb43b83fe28a36f693f to your computer and use it in GitHub Desktop.
Save typebird/3159c961f0e8ccb43b83fe28a36f693f to your computer and use it in GitHub Desktop.
簡單的猜數字遊戲。
mod numbers;
mod process;
use process::GameProcess;
fn main() {
println!("請輸入你猜測的數字,或者輸入 exit 以退出:");
GameProcess::execute();
}
use rand::{thread_rng, Rng};
#[derive(Debug)]
pub struct Answer {
vals: [u32; 4],
}
impl Answer {
/// 隨機產生器
fn generator() -> [u32; 4] {
let mut rng = thread_rng();
let mut arr = [0; 4];
for idx in 0..4 {
loop {
let val: u32 = rng.gen_range(0, 10);
if !arr.contains(&val) {
arr[idx] = val;
break;
}
}
}
arr
}
/// 建立
pub fn new() -> Answer {
Answer {
vals: Answer::generator(),
}
}
/// 取值
pub fn get_values(&self) -> [u32; 4] {
self.vals
}
}
#[derive(Debug)]
pub struct Guess {
vals: [u32; 4],
}
impl Guess {
/// 檢查長度
fn check_len(len: usize) -> Result<(), String> {
if len == 4 {
return Ok(());
}
Err(String::from("輸入的參數僅能有四字元。"))
}
/// 檢查值
fn check_val(arr: [u32; 4], idx: usize, val: u32) -> Result<(), String> {
if arr.contains(&val) {
let pos = arr.iter().position(|&v| v == val).unwrap();
let msg = format!(
"第 {} 位的 {} 與第 {} 位數字重覆了。",
idx + 1,
val,
pos + 1
);
return Err(msg);
}
Ok(())
}
/// 建立結構
pub fn new(val: &str) -> Result<Guess, String> {
Guess::check_len(val.len())?;
let mut arr = [10; 4];
for (idx, num) in val.chars().enumerate() {
match num.to_digit(10) {
Some(v) => {
Guess::check_val(arr, idx, v)?;
arr[idx] = v;
}
None => {
let msg = format!("第 {} 個字不是數字,而是 {}。", idx + 1, num);
return Err(msg);
}
}
}
Ok(Guess { vals: arr })
}
/// 初始化
pub fn init() -> Guess {
Guess { vals: [10; 4] }
}
/// 轉為迭代器
pub fn iter(&self) -> std::slice::Iter<'_, u32> {
self.vals.iter()
}
/// 取得值
pub fn get_values(&self) -> [u32; 4] {
self.vals
}
}
use crate::numbers::{Answer, Guess};
use std::io::{self, prelude::*};
#[derive(Debug)]
struct A(u32);
#[derive(Debug)]
struct B(u32);
#[derive(Debug)]
enum GuessResult {
Rrite,
Wrong(A, B),
Start,
}
impl GuessResult {
/// 初始化
fn init() -> GuessResult {
GuessResult::Start
}
/// 建立
fn new(a: u32, b: u32) -> GuessResult {
match (a, b) {
(4, _) => GuessResult::Rrite,
(a, b) => GuessResult::Wrong(A(a), B(b)),
}
}
/// 轉為字串
fn to_string(&self) -> String {
match self {
GuessResult::Rrite => String::from("4 A, 0 B"),
GuessResult::Start => String::from("0 A, 0 B"),
GuessResult::Wrong(A(a), B(b)) => String::from(format!("{} A, {} B", a, b)),
}
}
}
#[derive(Debug)]
/// 記錄數據,執行邏輯
pub struct GameProcess {
guess: Guess,
answer: Answer,
result: GuessResult,
}
impl GameProcess {
/// 初始化
fn new() -> GameProcess {
GameProcess {
result: GuessResult::init(),
answer: Answer::new(),
guess: Guess::init(),
}
}
/// 取得使用者輸入值
fn get_input(pros: GameProcess) -> Option<GameProcess> {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let input = line.unwrap();
if input == "exit" {
println!("-| 再見~");
break;
}
match Guess::new(&input) {
Err(e) => println!(" | {}\n | 請重新輸入,或者輸入 exit 以退出。", e),
Ok(v) => {
return Some(GameProcess {
result: pros.result,
answer: pros.answer,
guess: v,
});
}
}
}
None
}
/// 確認結果
fn check_res(pros: GameProcess) -> GameProcess {
if let GuessResult::Rrite = pros.result {
return pros;
}
let answer = pros.answer.get_values();
let (a, b) = pros
.guess
.iter()
.enumerate()
.fold((0, 0), |res, (idx, val)| {
if let Some(ans) = answer.get(idx) {
match (ans == val, answer.contains(val)) {
(true, _) => return (res.0 + 1, res.1),
(_, true) => return (res.0, res.1 + 1),
(_, _) => return res,
}
}
res
});
GameProcess {
result: GuessResult::new(a, b),
answer: pros.answer,
guess: pros.guess,
}
}
/// 執行遊戲
pub fn execute() -> Option<GameProcess> {
let mut pros = GameProcess::new();
let mut turn = 0;
// println!("0| 答案:{:?}", pros.answer.get_values());
loop {
let step = GameProcess::get_input(pros).map(GameProcess::check_res);
if let Some(val) = step {
turn += 1;
println!(
"{}| 猜測:{:?}\t結果:{}",
turn,
val.guess.get_values(),
val.result.to_string()
);
if let GuessResult::Rrite = val.result {
println!(" | 猜對了,恭喜~");
break;
}
pros = val;
} else {
break;
}
}
None
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment