aboutsummaryrefslogtreecommitdiff
path: root/src/generation.rs
blob: 6af05473cfd2a2ba825e7478bf477b1da4c32a57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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
}