Fixed recursion issue, enabled right click to flag
This commit is contained in:
26
src/app.rs
26
src/app.rs
@@ -1,7 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
// use serde_wasm_bindgen::to_value;
|
||||
use wasm_bindgen::prelude::*;
|
||||
// use web_sys::EventTarget;
|
||||
use web_sys::AddEventListenerOptions;
|
||||
// use wasm_bindgen_futures::spawn_local;
|
||||
use yew::{prelude::*, html::Scope};
|
||||
|
||||
@@ -19,7 +19,8 @@ extern "C" {
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
Discover{cell: Cell}
|
||||
Discover{ cell: Cell },
|
||||
Flag{ cell: Cell }
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
@@ -33,10 +34,12 @@ impl Component for App {
|
||||
type Properties = ();
|
||||
|
||||
fn create(ctx: &Context<Self>) -> Self {
|
||||
let mut game = Game::new(10, 10, 10);
|
||||
game.start_board();
|
||||
let height = 100;
|
||||
let width = 41;
|
||||
let num_mines =(height * width / 10) as usize;
|
||||
|
||||
// info!("\n{}", game.get_board().to_string());
|
||||
let mut game = Game::new(height, width, num_mines);
|
||||
game.start_board();
|
||||
|
||||
Self {
|
||||
link: ctx.link().clone(),
|
||||
@@ -46,10 +49,12 @@ impl Component for App {
|
||||
|
||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
let b = self.game.get_board().clone();
|
||||
|
||||
html!{
|
||||
<main class="container">
|
||||
<BoardComponent onsignal={self.link.callback(|cell| Msg::Discover{cell})} board={b}/>
|
||||
// Disable context menu
|
||||
// <button class="restart-button">Restart</button>
|
||||
<script>{"document.addEventListener('contextmenu', event => event.preventDefault());"}</script>
|
||||
<BoardComponent onsignal={self.link.callback(|cell| Msg::Discover{cell})} flagsignal={self.link.callback(|cell| Msg::Flag{cell})} board={b}/>
|
||||
</main>
|
||||
}
|
||||
}
|
||||
@@ -57,11 +62,10 @@ impl Component for App {
|
||||
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::Discover {cell} => {
|
||||
// info!("Pos (from App): {}", format!("{:?}", cell.get_pos()));
|
||||
self.game.show(cell.get_pos());
|
||||
|
||||
// info!("celhid (from App): {}", format!("{:?}", self.game.get_cell(cell.get_pos()).is_hidden()));
|
||||
// info!("\n{}", self.game.get_board().to_string())
|
||||
},
|
||||
Msg::Flag {cell} => {
|
||||
self.game.set_flag(cell.get_pos(), !self.game.get_cell(cell.get_pos()).is_flagged());
|
||||
}
|
||||
}
|
||||
true
|
||||
|
||||
@@ -10,17 +10,20 @@ use wasm_bindgen::JsValue;
|
||||
pub struct BoardComponent {
|
||||
link: Scope<Self>,
|
||||
board: Board,
|
||||
onsignal: Callback<Cell>
|
||||
onsignal: Callback<Cell>,
|
||||
flagsignal: Callback<Cell>
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
Discover{ cell: Cell },
|
||||
Flag{ cell: Cell }
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Properties)]
|
||||
pub struct Props {
|
||||
pub board: Board,
|
||||
pub onsignal: Callback<Cell>,
|
||||
pub flagsignal: Callback<Cell>
|
||||
}
|
||||
|
||||
impl Component for BoardComponent {
|
||||
@@ -32,7 +35,8 @@ impl Component for BoardComponent {
|
||||
Self {
|
||||
link: ctx.link().clone(),
|
||||
board: ctx.props().board.clone(),
|
||||
onsignal: ctx.props().onsignal.clone()
|
||||
onsignal: ctx.props().onsignal.clone(),
|
||||
flagsignal: ctx.props().flagsignal.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +51,7 @@ impl Component for BoardComponent {
|
||||
<>
|
||||
{row.into_iter().map(|c| {
|
||||
html! {
|
||||
<Button onsignal={self.link.callback(move |_| Msg::Discover{cell: c})} cell={c}/>
|
||||
<Button onsignal={self.link.callback(move |_| Msg::Discover{cell: c})} flagsignal={self.link.callback(move |_| Msg::Flag{cell: c})} cell={c}/>
|
||||
}
|
||||
}).collect::<Html>()}
|
||||
<br/>
|
||||
@@ -61,9 +65,11 @@ impl Component for BoardComponent {
|
||||
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::Discover {cell} => {
|
||||
// info!("Pos (from board): {}", format!("{:?}", cell.get_pos()));
|
||||
self.onsignal.emit(cell);
|
||||
}
|
||||
Msg::Flag {cell} => {
|
||||
self.flagsignal.emit(cell);
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ pub struct Button {
|
||||
link: Scope<Self>,
|
||||
cell: Cell,
|
||||
onsignal: Callback<Cell>,
|
||||
flagsignal: Callback<Cell>
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
@@ -19,6 +20,7 @@ pub enum Msg {
|
||||
pub struct Props {
|
||||
pub cell: Cell,
|
||||
pub onsignal: Callback<Cell>,
|
||||
pub flagsignal: Callback<Cell>
|
||||
}
|
||||
|
||||
impl Component for Button {
|
||||
@@ -29,7 +31,8 @@ impl Component for Button {
|
||||
Self {
|
||||
link: ctx.link().clone(),
|
||||
cell: ctx.props().cell.clone(),
|
||||
onsignal: ctx.props().onsignal.clone()
|
||||
onsignal: ctx.props().onsignal.clone(),
|
||||
flagsignal: ctx.props().flagsignal.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +46,25 @@ impl Component for Button {
|
||||
<button
|
||||
class={if self.cell.is_hidden() {"button-hidden"} else {"button-shown"}}
|
||||
onclick={self.link.callback(|_| Msg::Clicked)}
|
||||
// oncontextmenu={self.link.callback(|_| Msg::Clicked)}
|
||||
oncontextmenu={self.link.callback(|e: MouseEvent| {drop(e); Msg::RightClicked})}
|
||||
// style={(if !self.cell.is_hidden() {format!("background-color: #2f2f2f; transition: background-color 0.5s; transition-delay: {}s;", self.cell.get_delay())} else {"".to_string()}).as_str()}
|
||||
oncontextmenu={self.link.callback(|e: MouseEvent| {Msg::RightClicked})}
|
||||
style={style}>
|
||||
if self.cell.is_flagged() {
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-pennant-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M10 2a1 1 0 0 1 .993 .883l.007 .117v.35l8.406 3.736c.752 .335 .79 1.365 .113 1.77l-.113 .058l-8.406 3.735v7.351h1a1 1 0 0 1 .117 1.993l-.117 .007h-4a1 1 0 0 1 -.117 -1.993l.117 -.007h1v-17a1 1 0 0 1 1 -1z" stroke-width="0" fill="#ffffff"></path>
|
||||
</svg>
|
||||
} else {
|
||||
if self.cell.is_mine() && !self.cell.is_hidden(){
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-bomb-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||
<path d="M14.499 3.996a2.2 2.2 0 0 1 1.556 .645l3.302 3.301a2.2 2.2 0 0 1 0 3.113l-.567 .567l.043 .192a8.5 8.5 0 0 1 -3.732 8.83l-.23 .144a8.5 8.5 0 1 1 -2.687 -15.623l.192 .042l.567 -.566a2.2 2.2 0 0 1 1.362 -.636zm-4.499 5.004a4 4 0 0 0 -4 4a1 1 0 0 0 2 0a2 2 0 0 1 2 -2a1 1 0 0 0 0 -2z" stroke-width="0" fill="#ffffff"></path>
|
||||
<path d="M21 2a1 1 0 0 1 .117 1.993l-.117 .007h-1c0 .83 -.302 1.629 -.846 2.25l-.154 .163l-1.293 1.293a1 1 0 0 1 -1.497 -1.32l.083 -.094l1.293 -1.292c.232 -.232 .375 -.537 .407 -.86l.007 -.14a2 2 0 0 1 1.85 -1.995l.15 -.005h1z" stroke-width="0" fill="#ffffff"></path>
|
||||
</svg>
|
||||
} else {
|
||||
{&self.cell.to_string()}
|
||||
}
|
||||
}
|
||||
// { }
|
||||
</button>
|
||||
|
||||
}
|
||||
@@ -56,11 +73,10 @@ impl Component for Button {
|
||||
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::Clicked => {
|
||||
// info!("hid (from cell): {}", format!("{:?}", self.cell.is_hidden()));
|
||||
self.onsignal.emit(self.cell);
|
||||
}
|
||||
Msg::RightClicked => {
|
||||
self.onsignal.emit(self.cell);
|
||||
self.flagsignal.emit(self.cell);
|
||||
},
|
||||
}
|
||||
false
|
||||
|
||||
@@ -83,6 +83,10 @@ impl Board {
|
||||
pub fn set_delay(&mut self, pos: (usize, usize), delay: f32) {
|
||||
self.board[pos.0][pos.1].set_delay(delay)
|
||||
}
|
||||
|
||||
pub fn set_flag(&mut self, pos: (usize, usize), flag: bool) {
|
||||
self.board[pos.0][pos.1].set_flag(flag)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Board {
|
||||
|
||||
@@ -42,6 +42,7 @@ impl Cell {
|
||||
|
||||
pub fn show(&mut self) {
|
||||
self.hidden = false;
|
||||
self.flagged = false;
|
||||
}
|
||||
|
||||
pub fn is_hidden(&self) -> bool {
|
||||
@@ -53,6 +54,10 @@ impl Cell {
|
||||
}
|
||||
|
||||
pub fn set_flag(&mut self, new_flag: bool) {
|
||||
if !self.hidden {
|
||||
self.flagged = false;
|
||||
return;
|
||||
}
|
||||
self.flagged = new_flag;
|
||||
}
|
||||
|
||||
@@ -72,11 +77,12 @@ impl ToString for Cell {
|
||||
return " ".to_string();
|
||||
}
|
||||
if self.is_mine() {
|
||||
return "*".to_string();
|
||||
return " ".to_string();
|
||||
}
|
||||
if self.value == 0 {
|
||||
return " ".to_string();
|
||||
}
|
||||
|
||||
return self.value.to_string();
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ impl Game {
|
||||
}
|
||||
}
|
||||
|
||||
// Set values
|
||||
for i in 0..self.board.get_height() {
|
||||
for j in 0..self.board.get_width() {
|
||||
self.board.set_value((i, j), self.board.calculate_value((i, j)))
|
||||
@@ -52,10 +51,11 @@ impl Game {
|
||||
|
||||
cells_to_show.push(init_pos);
|
||||
|
||||
self.board.get_cell(init_pos).set_delay(0.0);
|
||||
|
||||
let mut added_cells = 1;
|
||||
|
||||
while added_cells > 0 {
|
||||
// info!("{:?}", cells_to_show.len() - added_cells);
|
||||
let new_cells = cells_to_show.len() - added_cells;
|
||||
added_cells = 0;
|
||||
|
||||
@@ -77,51 +77,41 @@ impl Game {
|
||||
cells_to_show.push(new_pos);
|
||||
added_cells += 1;
|
||||
}
|
||||
self.board.set_delay(new_pos, f32::sqrt(((init_pos.0 as isize - new_pos.0 as isize).pow(2) + (init_pos.1 as isize - new_pos.1 as isize).pow(2)) as f32) * 0.05);
|
||||
|
||||
// let delay = f32::sqrt(((init_pos.0 as isize - new_pos.0 as isize).pow(2) + (init_pos.1 as isize - new_pos.1 as isize).pow(2)) as f32) * 0.05;
|
||||
|
||||
let delay = self.board.get_cell(pos).get_delay() + 0.05;
|
||||
|
||||
self.board.set_delay(new_pos, delay);
|
||||
self.board.show_cell(new_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for pos in cells_to_show {
|
||||
// self.board.show_cell(pos);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
// self.board.show_cell(pos);
|
||||
// if self.board.get_value(pos) == 0 {
|
||||
// for i in -1..=1 {
|
||||
// for j in -1..=1 {
|
||||
// if pos.0 as isize + i >= 0 &&
|
||||
// pos.0 as isize + i < self.get_height() as isize &&
|
||||
// pos.1 as isize + j >= 0 &&
|
||||
// pos.1 as isize + j < self.get_width() as isize &&
|
||||
// self.board.get_cell(((pos.0 as isize + i) as usize , (pos.1 as isize + j) as usize)).is_hidden() {
|
||||
// self.show(((pos.0 as isize + i) as usize , (pos.1 as isize + j) as usize))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
pub fn get_height(&self) -> usize {
|
||||
return self.board.get_height();
|
||||
self.board.get_height()
|
||||
}
|
||||
|
||||
pub fn get_width(&self) -> usize {
|
||||
return self.board.get_width();
|
||||
self.board.get_width()
|
||||
}
|
||||
|
||||
pub fn get_board(&self) -> &Board {
|
||||
return &self.board;
|
||||
&self.board
|
||||
}
|
||||
|
||||
pub fn get_cell(&self, pos: (usize, usize)) -> Cell {
|
||||
self.board.get_cell(pos)
|
||||
}
|
||||
|
||||
pub fn is_flagged(&self, pos: (usize, usize)) -> bool {
|
||||
self.board.get_cell(pos).is_flagged()
|
||||
}
|
||||
|
||||
pub fn set_flag(&mut self, pos: (usize, usize), flag: bool) {
|
||||
self.board.set_flag(pos, flag);
|
||||
}
|
||||
|
||||
}
|
||||
13
styles.css
13
styles.css
@@ -4,7 +4,7 @@
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
/* Verdana , Avenir, Helvetica, Arial, sans-serif */
|
||||
color: #0f0f0f;
|
||||
color: #0f0f0f98;
|
||||
background-color: #f6f6f6;
|
||||
|
||||
font-synthesis: none;
|
||||
@@ -67,8 +67,9 @@ button {
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
font-weight: 500;
|
||||
color: #0f0f0f98;
|
||||
/* font-weight: 500; */
|
||||
font-size: 25px;
|
||||
color: rgba(15, 15, 15, 0.0);
|
||||
background-color: #0f0f0f98;
|
||||
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
|
||||
height: 50px;
|
||||
@@ -84,9 +85,9 @@ button {
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
/* color: #2f2f2f; */
|
||||
font-size: 25px;
|
||||
font-weight: 700;
|
||||
color: #0f0f0f98;
|
||||
background-color: #2f2f2f;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
|
||||
Reference in New Issue
Block a user