diff --git a/src/components/board.rs b/src/components/board.rs new file mode 100644 index 0000000..721d7b3 --- /dev/null +++ b/src/components/board.rs @@ -0,0 +1,141 @@ +use leptos::*; +use leptos::prelude::*; +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Serialize, Deserialize)] +pub enum CellContent { + Empty, + Player, + Trap, +} + +#[derive(Clone, Serialize, Deserialize)] +pub struct Board { + grid: Vec>, + size: usize, +} + +impl Board { + pub fn new(size: usize) -> Self { + Board { + grid: vec![vec![CellContent::Empty; size]; size], + size, + } + } +} + +#[component] +pub fn BoardCreator( + #[prop(into)] on_cancel: Callback<()>, +) -> impl IntoView { + let board = RwSignal::new(Board::new(2)); + let current_turn = RwSignal::new(0); + let finished = RwSignal::new(false); + + let handle_cell_click = move |row: usize, col: usize| { + let mut current_board = board.get(); + if current_turn.get() == 0 && row == current_board.size - 1 { + // First turn - only allow placing player in bottom row + current_board.grid[row][col] = CellContent::Player; + board.set(current_board); + current_turn.set(1); + } else if !finished.get() { + // Subsequent turns - allow placing trap or moving player + let player_pos = find_player(¤t_board); + if let Some((player_row, player_col)) = player_pos { + if is_adjacent(player_row, player_col, row, col) { + if row == 0 { + // Reached top row - game can be finished + current_board.grid[row][col] = CellContent::Player; + board.set(current_board); + finished.set(true); + } else { + current_board.grid[row][col] = CellContent::Player; + current_board.grid[player_row][player_col] = CellContent::Empty; + board.set(current_board); + current_turn.update(|t| *t += 1); + } + } + } + } + }; + + let rows = move || (0..2).collect::>(); + let cols = move || (0..2).collect::>(); + + view! { +
+
+ "·", + CellContent::Player => "○", + CellContent::Trap => "×", + } + }; + + view! { + + } + } + /> + } + } + /> +
+
+ {move || if current_turn.get() == 0 { + "Place your piece in the bottom row" + } else if finished.get() { + "Board complete!" + } else { + "Move your piece or place a trap in adjacent squares" + }} +
+
+ + {move || finished.get().then(|| view! { + + })} +
+
+ } +} + +fn find_player(board: &Board) -> Option<(usize, usize)> { + for i in 0..board.size { + for j in 0..board.size { + if matches!(board.grid[i][j], CellContent::Player) { + return Some((i, j)); + } + } + } + None +} + +fn is_adjacent(x1: usize, y1: usize, x2: usize, y2: usize) -> bool { + let dx = if x1 >= x2 { x1 - x2 } else { x2 - x1 }; + let dy = if y1 >= y2 { y1 - y2 } else { y2 - y1 }; + (dx == 1 && dy == 0) || (dx == 0 && dy == 1) +} \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs new file mode 100644 index 0000000..90d1407 --- /dev/null +++ b/src/components/mod.rs @@ -0,0 +1 @@ +pub mod board; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6eef6b9..8e9e3f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,9 @@ use leptos::prelude::*; use web_sys::{MouseEvent, Storage, window}; use serde::{Serialize, Deserialize}; +mod components; +use components::board::BoardCreator; + #[derive(Serialize, Deserialize)] struct UserData { name: String, @@ -36,6 +39,7 @@ fn App() -> impl IntoView { let (name, set_name) = signal(String::new()); let (greeting, set_greeting) = signal(String::new()); let (show_form, set_show_form) = signal(true); + let (show_board_creator, set_show_board_creator) = signal(false); if let Some(data) = load_user_data() { set_name.set(data.name); @@ -97,7 +101,21 @@ fn App() -> impl IntoView {

"Boards"

- "+ Create New Board" + + "+ Create New Board" + + {move || show_board_creator.get().then(|| view! { + + })}
})}