~athorp96/conway.rs

ref: 63995b3124f8e1724bb46b13c9110fbc6378887a conway.rs/src/conway/board.rs -rw-r--r-- 2.8 KiB
63995b31Andrew Thorp Minor refactor 1 year, 16 days ago
                                                                                
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
use rand::prelude::*;
use std::fmt;

use crate::conway::cell::{Cell, CellState, SimpleCell, Coordinate};

pub struct Board {
    width: usize,
    height: usize,
    cells: Vec<Vec<SimpleCell>>,
}

impl Board {
    pub fn new(width: usize, height: usize) -> Self {
        let mut cells: Vec<Vec<SimpleCell>> = Vec::with_capacity(height);

        // Initialize vectors
        for i in 0..height {
            let mut row = Vec::with_capacity(width);
            for j in 0..width {
                row.push(SimpleCell::new(Coordinate::new(i as i32, j as i32)));
            }
            cells.push(row);
        }

        Board {
            width,
            height,
            cells: cells,
        }
    }

    pub fn get(&self, x: i32, y: i32) -> Option<SimpleCell> {
        if x < self.width as i32 && x >= 0 && y < self.height as i32 && y >= 0 {
            Some(self.cells[x as usize][y as usize].clone())
        } else {
            None
        }
    }

    pub fn set(&mut self, x: usize, y: usize, state: CellState) {
        self.cells[x][y].set_state(state);
    }

    pub fn step(&mut self) {
        let mut cells = self.cells.clone();
        let mut display = String::new();
        for i in 0..cells.len() {
            for j in 0..cells[i].len() {
                let cell = cells[i][j].clone();
                cells[i][j].set_state(self.next_cell_step(cell));
            }
        }
        self.cells = cells;
    }

    fn next_cell_step(&self, cell: SimpleCell) -> CellState {
        let adj = cell.get_adjecent();
        let neighbors = self.get_cells(adj);
        let live_neighbors = neighbors.iter().filter(|c| c.is_alive()).count();

        // birth
        if !cell.is_alive() && live_neighbors == 3 {
            CellState::Alive
            // Starvation
        } else if cell.is_alive() && live_neighbors > 3 {
            CellState::Dead
            // Isolation
        } else if cell.is_alive() && live_neighbors <= 1 {
            CellState::Dead
            // Survival
        } else {
            cell.state
        }
    }

    fn get_cells(&self, coordinates: Vec<Coordinate>) -> Vec<SimpleCell> {
        let mut cells = Vec::new();
        for c in coordinates {
            if let Some(cell) = self.get(c.x, c.y) {
                cells.push(cell);
            }
        }
        cells
    }
}

impl fmt::Display for Board {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let cells = self.cells.clone();
        let mut display = String::new();
        for row in cells {
            for cell in row {
                if cell.is_alive() {
                    display.push_str("()");
                } else {
                    display.push_str("__");
                }
            }
            display.push('\n');
        }
        write!(f, "{}", display)
    }
}