やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rust自習(じゃんけんゲーム8)

 mainとlibに分離した。一応これで完成。

成果物

コード

  • janken/
    • src/
      • main.rs
      • lib.rs

main.rs

use std::io::Write;
use std::io::stdout;
fn main() {
    loop {
        println!("じゃんけんゲーム");
        print!("1:✊ 2:✌ 3:✋> ");
        stdout().flush();
        let player: u32 = read_stdin();
        let player = janken::Hand::from(player);
        let npc: janken::Hand = rand::random();
        println!("{} {}", player, npc);
        let res = player.jadge(npc);
        println!("{}", res);
    }
}
fn read_stdin<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

lib.rs

use rand::{distributions::{Distribution, Standard},Rng};
use std::io::Write;
use std::io::stdout;

#[derive(Debug,PartialEq)]
pub enum Result { Win, Lose, Draw }
impl std::fmt::Display for crate::Result {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            crate::Result::Win => write!(f, "Win!!"),
            crate::Result::Lose => write!(f, "Lose..."),
            crate::Result::Draw => write!(f, "Draw"),
        }
    }
}
#[derive(Debug,PartialEq)]
pub enum Hand { Rock, Scissors, Paper }
impl std::fmt::Display for Hand {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Hand::Rock => write!(f, "✊"),
            Hand::Scissors => write!(f, "✌"),
            Hand::Paper => write!(f, "✋"),
        }
    }
}
impl From<u32> for Hand {
    fn from(hand: u32) -> Hand {
        match hand {
            1 => Hand::Rock,
            2 => Hand::Scissors,
            3 => Hand::Paper,
            _ => panic!("手は1〜3のいずれかで指定してください。")
        }
    }
}
impl Distribution<Hand> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Hand {
        Hand::from(rng.gen_range(1, 4))
    }
}
impl Hand {
    pub fn jadge(&self, opponent: Hand) -> crate::Result {
        if *self == Hand::Rock && opponent == Hand::Scissors { crate::Result::Win }
        else if *self == Hand::Rock && opponent == Hand::Paper { crate::Result::Lose }
        else if *self == Hand::Scissors && opponent == Hand::Rock { crate::Result::Lose }
        else if *self == Hand::Scissors && opponent == Hand::Paper { crate::Result::Win }
        else if *self == Hand::Paper && opponent == Hand::Rock { crate::Result::Win }
        else if *self == Hand::Paper && opponent == Hand::Scissors { crate::Result::Lose }
        else { crate::Result::Draw }
    }
}

所感

 本当は最上位をjanken::Game.start();みたいにしたかった。でも、無駄に冗長になりそうなのでやめた。

 できればTUI版、GUI(GTK)版もつくってみたい。そうすれば、janken::{Cui,Tui,Gui}::start()みたいにできるかな?

 とりあえず、じゃんけんシリーズは一区切りついた。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで