array2ds 0.2.1

Simple Package for handling sized 2d arrays in rust, without the usage of the keyword unsafe cuz why not
Documentation

array2ds

May God let rust have better constant generics

Array2ds is a none-bloated library in rust for rust by rust for handling staticly sized 2d array/grids to run the examples: cargo run --example 'example_name'

  • Uses only Safe Rust, no usage of "unsafe"
  • Works I guess
  • ✨Magic ✨

Features

  • creating 2d arrays
  • iterating over rows both mutable and not
  • grid sized cant be changed after created
  • can index with (row,column) or [row,column] and easily overload to other ways
  • can iterate over columns
use array2ds::array2d::*;
use std::io::stdin;

struct Square {
    data: char,
}

impl Default for Square {
    fn default() -> Self {
        Square { data: '#' }
    }
}

fn main() {
    run_game();
}

fn run_game() {
    let mut board: Array2d<Square> = Array2d::filled_with_default(3, 3);
    println!("enter location as: row col, for example: `0 1`, row: 0 column 1");
    print_board(&board);

    let mut winner = false;
    let mut current_player = 'X';

    while !winner {
        let (row, column) = read_grid_location();

        if board[[row, column]].data == '#' {
            board[[row, column]].data = current_player;

            match current_player {
                'X' => current_player = 'O',
                'O' => current_player = 'X',
                _ => panic!("invalid data for square"),
            }
            println!();
            print_board(&board);
            winner = check_horizontal(&board)  || check_vertical(&board) || check_diagnol(&board);
        } else {
            println!("invalid location, try another");
        }
    }
}

fn read_grid_location() -> (usize, usize) {
    let mut buffer = String::new();
    stdin().read_line(&mut buffer).unwrap();
    let buffer = buffer.trim();
    let splitted: Vec<&str> = buffer.split(' ').collect();
    if splitted.len() < 2 {
        panic!("enter data as `row col` ");
    }
    let r = splitted[0].parse::<usize>().unwrap();
    let c = splitted[1].parse::<usize>().unwrap();
    (r, c)
}

fn check_diagnol(board: &Array2d<Square>) -> bool{
    
    let mid = &board[(1,1)];
    if mid.data == '#'{
        return false
    }
    if board[[0,0]].data == mid.data && mid.data == board[(2,2)].data{
        return true
    }
    if board[[2,0]].data == mid.data && mid.data == board[(0,2)].data{
        return true
    }
    false
}

fn check_vertical(board: &Array2d<Square>) -> bool {
    for col in 0..3 {
        let mut x_count = 0;
        let mut o_count = 0;
        for row in 0..3 {
            match board[[row, col]].data {
                'X' => x_count += 1,
                'O' => o_count += 1,
                _ => {}
            }
        }

        if x_count == 3 || o_count == 3 {
            return true;
        }
    }
    false
}

fn check_horizontal(board: &Array2d<Square>) -> bool {
    for row in board.iter_rows() {
        let mut o_count = 0;
        let mut x_count = 0;
        for player in row {
            match player.data {
                'O' => o_count += 1,
                'X' => x_count += 1,
                _ => {}
            }
        }
        if o_count == 3 || x_count == 3 {
            return true;
        }
    }
    false
}

fn print_board(board: &Array2d<Square>) {
    for row in board.iter_rows() {
        for square in row {
            print!("{}", square.data);
        }
        println!();
    }
}

License

MIT