diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gameloop.rs | 70 | ||||
| -rw-r--r-- | src/generation.rs | 120 | ||||
| -rw-r--r-- | src/main.rs | 163 |
3 files changed, 195 insertions, 158 deletions
diff --git a/src/gameloop.rs b/src/gameloop.rs new file mode 100644 index 0000000..d573868 --- /dev/null +++ b/src/gameloop.rs @@ -0,0 +1,70 @@ +use crate::generation::*; + +use colored::Colorize; +use crossterm::{ + cursor::{Hide, MoveTo, Show}, + event, + event::{poll, Event, KeyCode, KeyEvent}, + style::Stylize, + terminal, + terminal::{EnterAlternateScreen, LeaveAlternateScreen}, + ExecutableCommand, QueueableCommand, +}; +use rand::{thread_rng, Rng}; +use std::{ + io::{self, Write}, + thread::sleep, + time::Duration, +}; + + +pub fn run() { + let mut stdout = io::stdout(); + let mut frame: Gen = new_gen(); + let mut nxt; + + terminal::enable_raw_mode().unwrap(); + stdout.execute(EnterAlternateScreen).unwrap(); + stdout.execute(Hide).unwrap(); + + 'gameloop: loop { + while event::poll(Duration::default()).unwrap() { + if let Event::Key(key_event) = event::read().unwrap() { + match key_event.code { + KeyCode::Esc | KeyCode::Char('q') => { + break 'gameloop; + } + KeyCode::Char('s') => { + frame = new_gen(); + render_gen(&mut stdout, &frame) + } + + KeyCode::Char('n') => { + nxt = next_gen(&mut frame); + render_gen(&mut stdout, &nxt) + } + KeyCode::Char('a') => 'animate: loop { + nxt = next_gen(&mut frame); + render_gen(&mut stdout, &nxt); + sleep(Duration::from_millis(16)); + if (poll(Duration::from_millis(1))).unwrap() { + if let Event::Key(k) = event::read().unwrap() { + match k.code { + KeyCode::Char('q') => break 'animate, + _ => {} + } + } + } else { + } + }, + _ => {} + } + } + } + } + + stdout.execute(Show).unwrap(); + stdout.execute(LeaveAlternateScreen).unwrap(); + terminal::disable_raw_mode().unwrap(); + +} diff --git a/src/generation.rs b/src/generation.rs new file mode 100644 index 0000000..6af0547 --- /dev/null +++ b/src/generation.rs @@ -0,0 +1,120 @@ +#![allow(unused_imports, unused_variables, unused_mut)] + +use colored::Colorize; +use crossterm::{ + cursor::{Hide, MoveTo, Show}, + event, + event::{poll, Event, KeyCode, KeyEvent}, + style::Stylize, + terminal, + terminal::{EnterAlternateScreen, LeaveAlternateScreen}, + ExecutableCommand, QueueableCommand, +}; +use rand::{thread_rng, Rng}; +use std::{ + io::{self, Write}, + thread::sleep, + time::Duration, +}; + +pub type Gen = Vec<Vec<Cell>>; + +#[derive(Clone, Copy, Debug)] +pub enum Cell { + Alive, + Dead, +} + +pub fn render_gen(stdout: &mut io::Stdout, gen: &Gen) { + for i in 0..gen.len() { + for j in 0..gen[0].len() { + stdout.queue(MoveTo(i as u16, j as u16)).unwrap(); + match gen[i][j] { + // Cell::Alive => print!("😎"), + // Cell::Alive => print!("🦀"), + Cell::Alive => print!("{}", "X".color("blue")), + Cell::Dead => print!("{}", "-".color("red")), + } + stdout.flush().unwrap(); + } + } +} + +pub fn new_gen() -> Gen { + let cells = vec![Cell::Dead, Cell::Dead, Cell::Alive, Cell::Dead, Cell::Alive]; + let rows: u16 = terminal::size().unwrap().1; + let cols: u16 = terminal::size().unwrap().0; + let mut colums: Vec<Vec<Cell>> = Vec::new(); + for _ in 0..cols { + let mut col: Vec<Cell> = Vec::new(); + for _ in 0..rows { + let rand = thread_rng().gen_range(0..10); + col.push(cells[rand % 5]); + } + colums.push(col); + } + colums +} + +pub fn is_valid_idx(i: i32, j: i32, m: i32, n: i32) -> bool { + i >= 0 && i < m && j >= 0 && j < n +} + +pub fn get_alive(x: i32, y: i32, cur_gen: &Gen) -> i32 { + let mut alive_cnt: i32 = 0; + + let m: i32 = cur_gen.len() as i32; + let n: i32 = cur_gen[0].len() as i32; + let dx: [i8; 8] = [0, 1, 0, -1, 1, -1, -1, 1]; + let dy: [i8; 8] = [1, 0, -1, 0, 1, -1, 1, -1]; + + for i in 0..8 { + let nx: i32 = x as i32 + dx[i] as i32; + let ny: i32 = y as i32 + dy[i] as i32; + if is_valid_idx(nx, ny, m, n) { + let cur_cell = cur_gen[nx as usize][ny as usize]; + match cur_cell { + Cell::Alive => alive_cnt += 1, + Cell::Dead => (), + } + } + } + + alive_cnt +} + +pub fn next_gen(cur_gen: &mut Gen) -> Gen { + let m: i32 = cur_gen.len() as i32; + let n: i32 = cur_gen[0].len() as i32; + let mut nxt_gen: Gen = Gen::new(); + for _ in 0..m { + let mut col: Vec<Cell> = Vec::new(); + for _ in 0..n { + col.push(Cell::Dead); + } + nxt_gen.push(col); + } + + for i in 0..m { + for j in 0..n { + let alive = get_alive(i, j, cur_gen); + + match cur_gen[i as usize][j as usize] { + Cell::Alive => { + if alive == 2 || alive == 3 { + nxt_gen[i as usize][j as usize] = Cell::Alive; + } else { + nxt_gen[i as usize][j as usize] = Cell::Dead; + } + } + Cell::Dead => { + if alive == 3 { + nxt_gen[i as usize][j as usize] = Cell::Alive; + } + } + } + } + } + *cur_gen = nxt_gen.clone(); + nxt_gen +} diff --git a/src/main.rs b/src/main.rs index 3e20d50..85f9eb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,164 +1,11 @@ #![allow(unused_imports, unused_variables, unused_mut)] -use colored::Colorize; -use crossterm::cursor::{Hide, MoveTo, Show}; -use crossterm::event::{Event, KeyCode, KeyEvent, poll}; -use crossterm::style::Stylize; -use crossterm::terminal::*; -use crossterm::{event, terminal, ExecutableCommand, QueueableCommand}; -use rand::{thread_rng, Rng}; -use std::io::{self, Write}; -use std::thread::sleep; -use std::time::Duration; +mod generation; +mod gameloop; +use gameloop::*; +use generation::*; -type Gen = Vec<Vec<Cell>>; - -#[derive(Clone, Copy, Debug)] -enum Cell { - Alive, - Dead, -} - -fn render_gen(stdout: &mut io::Stdout, gen: &Gen) { - for i in 0..gen.len() { - for j in 0..gen[0].len() { - stdout.queue(MoveTo(i as u16, j as u16)).unwrap(); - match gen[i][j] { - // Cell::Alive => print!("😎"), - // Cell::Alive => print!("🦀"), - Cell::Alive => print!("{}", "X".color("blue")), - Cell::Dead => print!("{}", "-".color("red")), - } - stdout.flush().unwrap(); - } - } -} - -fn new_gen() -> Gen { - let cells = vec![Cell::Dead, Cell::Dead, Cell::Alive, Cell::Dead, Cell::Alive]; - let rows: u16 = terminal::size().unwrap().1; - let cols: u16 = terminal::size().unwrap().0; - let mut colums: Vec<Vec<Cell>> = Vec::new(); - for _ in 0..cols { - let mut col: Vec<Cell> = Vec::new(); - for _ in 0..rows { - let rand = thread_rng().gen_range(0..10); - col.push(cells[rand % 5]); - } - colums.push(col); - } - colums -} - -fn is_valid_idx(i: i32, j: i32, m: i32, n: i32) -> bool { - i >= 0 && i < m && j >= 0 && j < n -} - -fn get_alive(x: i32, y: i32, cur_gen: &Gen) -> i32 { - let mut alive_cnt: i32 = 0; - - let m: i32 = cur_gen.len() as i32; - let n: i32 = cur_gen[0].len() as i32; - let dx: [i8; 8] = [0, 1, 0, -1, 1, -1, -1, 1]; - let dy: [i8; 8] = [1, 0, -1, 0, 1, -1, 1, -1]; - - for i in 0..8 { - let nx: i32 = x as i32 + dx[i] as i32; - let ny: i32 = y as i32 + dy[i] as i32; - if is_valid_idx(nx, ny, m, n) { - let cur_cell = cur_gen[nx as usize][ny as usize]; - match cur_cell { - Cell::Alive => alive_cnt += 1, - Cell::Dead => (), - } - } - } - - alive_cnt -} - -fn next_gen(cur_gen: &mut Gen) -> Gen { - let m: i32 = cur_gen.len() as i32; - let n: i32 = cur_gen[0].len() as i32; - let mut nxt_gen: Gen = Gen::new(); - for _ in 0..m { - let mut col: Vec<Cell> = Vec::new(); - for _ in 0..n { - col.push(Cell::Dead); - } - nxt_gen.push(col); - } - - for i in 0..m { - for j in 0..n { - let alive = get_alive(i, j, cur_gen); - - match cur_gen[i as usize][j as usize] { - Cell::Alive => { - if alive == 2 || alive == 3 { - nxt_gen[i as usize][j as usize] = Cell::Alive; - } else { - nxt_gen[i as usize][j as usize] = Cell::Dead; - } - } - Cell::Dead => { - if alive == 3 { - nxt_gen[i as usize][j as usize] = Cell::Alive; - } - } - } - } - } - *cur_gen = nxt_gen.clone(); - nxt_gen -} fn main() { - let mut stdout = io::stdout(); - let mut frame: Gen = new_gen(); - let mut nxt; - - terminal::enable_raw_mode().unwrap(); - stdout.execute(EnterAlternateScreen).unwrap(); - stdout.execute(Hide).unwrap(); - - 'gameloop: loop { - while event::poll(Duration::default()).unwrap() { - if let Event::Key(key_event) = event::read().unwrap() { - match key_event.code { - KeyCode::Esc | KeyCode::Char('q') => { - break 'gameloop; - } - KeyCode::Char('s') => { - frame = new_gen(); - render_gen(&mut stdout, &frame) - } - - KeyCode::Char('n') => { - nxt = next_gen(&mut frame); - render_gen(&mut stdout, &nxt) - } - KeyCode::Char('a') => - 'animate: loop { - nxt = next_gen(&mut frame); - render_gen(&mut stdout, &nxt); - sleep(Duration::from_millis(16)); - if(poll(Duration::from_millis(1))).unwrap() { - if let Event::Key(k) = event::read().unwrap() { - match k.code { - KeyCode::Char('q') => break 'animate, - _ => {} - } - } - } else {} - }, - _ => {} - } - } - } - } - - stdout.execute(Show).unwrap(); - stdout.execute(LeaveAlternateScreen).unwrap(); - terminal::disable_raw_mode().unwrap(); + run(); } |
