Let's write β

プログラミング中にできたことか、思ったこととか

RustでLifeGame

前々からリージョン理論でメモリ管理を解決してるとかで理論的な興味はあったのですが
Rustでプログラムを書くということはしてませんでした.
が久々にホームページを見ましたらドキュメントも充実しているし,なかなか良さそうになっていたので
早速少しずつですが勉強してみています.
まだ,多少ドキュメントが不親切というか,一般的なタスクをこなすときにちょっと躓いてしまったりということが
あるのでそこは少し不安ですがポインタの扱いは確かに便利な気がします.
(Vecのindexで中身を取り出すときにusizeにキャストしていたりというところは最初はなぜエラーなのかわかりませんでした)

mutableなものと,そうでないものを一つのletでmutをつけるか付けないかで表現するというのと
そうでなく,var,とvalというように宣言に2種類を持たせるのどちらが視認性があるだろうかなどということを考えつつ書いています.
まだRustらしくない書き方をしてしまっている部分があると思うのでそこら辺を何かしら良い感じに出来たらなとも居ます.

extern crate rand;

use rand::Rng;

struct Board {
    width: i32,
    height: i32,
    data: Vec<i8>
}

impl Board {
    fn new(w: i32, h: i32) -> Board {
        let mut data: Vec<i8> = Vec::new();
        for _ in (0..(w*h)) {
            data.push(rand::thread_rng().gen_range(0,2));
        }
        Board {
            width: w,
            height: h,
            data: data
        }
    }

    fn show(&self) {
        for idx in (0..(self.width * self.height)) {
            let datum = self.data[idx as usize];
            if datum == 0 {
                print!(" ");
            } else if datum == 1 {
                print!("X");
            }
            if (idx + 1) % self.width == 0 {
                println!("");
            }
        }
    }

    fn get_cell(&self, x: i32, y: i32) -> i8 {

        let new_x = (x + self.width) % self.width;
        let new_y = (y + self.height) % self.height;

        let idx = new_x + new_y * self.width;
        return self.data[idx as usize];
    }

    fn calc_next_cell(&self, x: i32, y: i32) -> i8 {
        let mut neighbors = 0;
        neighbors += self.get_cell(x - 1, y - 1);
        neighbors += self.get_cell(x - 1, y);
        neighbors += self.get_cell(x - 1, y + 1);

        neighbors += self.get_cell(x, y - 1);
        neighbors += self.get_cell(x, y + 1);

        neighbors += self.get_cell(x + 1, y - 1);
        neighbors += self.get_cell(x + 1, y);
        neighbors += self.get_cell(x + 1, y + 1);

        if self.get_cell(x, y) == 0 {
            if neighbors == 3 {
                return 1;
            } else {
                return 0;
            }
        } else {
            if neighbors == 2 || neighbors == 3 {
                return 1;
            } else {
                return 0;
            }
        }
    }

    fn update_board(&self) -> Board {
        let mut new_data: Vec<i8> = Vec::new();
        for idx in (0..(self.width * self.height)) {
            let x = idx % self.width;
            let y = idx / self.height;
            new_data.push(self.calc_next_cell(x, y));
        }
        Board {
            width: self.width,
            height: self.height,
            data: new_data
        }
    }
}

fn main() {
    let mut board = Board::new(16, 16);
    board.show();
    for _ in (0..100) {
        board = board.update_board();
        println!("---------------------");
        board.show();
    }
}