Open2

Dioxusで遊ぶ(v0.4.3~

_5da_5da

https://dioxuslabs.com/

Dioxusはv0.4.2がリリースされていたので、〇×ゲームを作ってみました

〇×じゃなく1,2と表示されているのは実装力不足です
あと、見映えとか動作も色々改善したいです...


main.rs
#![allow(non_snake_case)]
use dioxus::{prelude::*, html::GlobalAttributes};
use futures_util::StreamExt;

fn main() {
    dioxus_web::launch(App);
}

const ROW_MAX:usize = 3;
const COL_MAX:usize = 3;
const ARRAY:[[u8;COL_MAX];ROW_MAX] = [[0,0,0],[0,0,0],[0,0,0]];
const DEBUG:bool = false;

fn App(cx: Scope) -> Element {
    let turn_from_clicks = use_state(cx, ||0);
    let board = use_state(cx, ||ARRAY);

    let tx_turn_from_clicks = use_coroutine(cx, |mut rx: UnboundedReceiver<usize>| {
        to_owned![turn_from_clicks];
        async move {
            while let Some(n) = rx.next().await {
                turn_from_clicks.set(n)
            }
        }
    });
    
    let tx_board = use_coroutine(cx, |mut rx: UnboundedReceiver<[[u8;3];3]>| {
        to_owned![board];
        async move {
            while let Some(arr) = rx.next().await {
                board.set(arr);
            }
        }
    });

    cx.render(rsx! {
        style { include_str!("./test.css") }
        div {
            class:"center board",
            for r in 0..ROW_MAX {
                div {
                    for c in 0..COL_MAX {
                        Square {
                            is_clicked:use_state(cx, || false),
                            r:r,
                            c:c,
                            board:board,
                            sign:board[r][c],
                            turn:**turn_from_clicks,
                            app_tx_turn_from_clicks:tx_turn_from_clicks.clone(),
                            app_tx_board:tx_board.clone(),
                        }
                    }
                } 
            }
        }
        
        if {check_arr(board)} != 0 {
            rsx!(h1{
                "{check_arr(board)}の勝ち"
            })   
        }
                
        if DEBUG == true {
            rsx!(div {
                for r in board {
                    div {
                        for c in r {
                            span {"{c}"}
                        }
                    }
                }
            })
        }
    })
}
    
fn check_arr (arr:&UseState<[[u8;3];3]>)-> u8{
    let v = [
        eval(arr[0][0],arr[0][1],arr[0][2]),
        eval(arr[0][0],arr[1][0],arr[2][0]),
        eval(arr[0][0],arr[1][1],arr[2][2]),
        eval(arr[0][1],arr[1][1],arr[2][1]),
        eval(arr[0][2],arr[1][2],arr[2][2]),
        eval(arr[0][2],arr[1][1],arr[2][0]),
        eval(arr[1][0],arr[1][1],arr[1][2]),
        eval(arr[2][0],arr[2][1],arr[2][2])
    ];

    for item in v {
        if item != 0 {
            return  item;
        }
    }

    return 0;

    fn eval(r:u8,m:u8, l:u8) -> u8{
        if r == m && r == l && r != 0 {
            return r;
        } 
        0
    }
}

#[derive(PartialEq, Props)]
struct SquareProps<'a> {
    is_clicked: &'a UseState<bool>,
    r:usize,
    c:usize,
    board:&'a UseState<[[u8;3];3]>,
    sign:u8,
    turn:usize,
    app_tx_turn_from_clicks:Coroutine<usize>,
    app_tx_board:Coroutine<[[u8;3];3]>,
}

fn Square<'a>(cx: Scope<'a,SquareProps>) -> Element<'a> {
    let v = match cx.props.turn % 2 {
        0 => 1,
        _ => 2
    };
    if **cx.props.is_clicked == true {
        cx.render(rsx!(
            div {
                class:"square",
                input {
                    r#type:"text", class:"char", maxlength:1,value:"{cx.props.sign}",readonly:true
                }
            })
        )
    } else {
        cx.render(rsx!(
            div {
                class:"square",
                input {
                    r#type:"text", class:"char", maxlength:1,value:"",readonly:true,
                    onclick: move |_| {
                        cx.props.is_clicked.set(true);
                        cx.props.app_tx_turn_from_clicks.send(cx.props.turn+1);
                        let mut tmp_arr = *cx.props.board.clone();
                        tmp_arr[cx.props.r][cx.props.c] = v;
                        cx.props.board.set(tmp_arr);
                    },
                }
            })
        )
    }
}
test.css
.container{
    position: absolute;
    bottom: 0; top: 0; left: 0; right: 0;
    text-align: center;
}

.char {
    font-family: sans-serif;
    font-size: 24px;
    text-transform: uppercase;
    outline: 0;
    border: 0;
    padding: 0;
    margin: 1px 0 0 -1px;
    width: 1.25em;
    height: 1.25em;
    text-align: center;
    background-color: rgb(200, 200, 200);
}

.square {
    margin: 0 1px 1px 0;
    display: inline-block;
    position: relative;
    font: 24px Calibri;
    width: 1.25em;
    height: 1.25em;
    line-height: 1.25em;
    vertical-align: top;
}
.board{
    display: block;  
    background-color: rgb(32,32,32); 
    align-content: baseline;
    text-align: left; 
    width: max-content;
}
Cargo.toml
[package]
name = "demo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dioxus = "0.4.3"
dioxus-signals = "0.4.3"
dioxus-web = "0.4.3"
futures-util = "0.3.30"
tokio = { version = "1.35.1", features = ["time"] }



以下の記事を参考にさせて頂きました
https://zenn.dev/etoal83/scraps/aa158dd703c287

exampleのコードはcargo run --example [compose]などと入力すると実行できるというのを初めて知りました(参考リンク

https://github.com/DioxusLabs/dioxus/tree/master/examples

年明けも暇しているはずなので進捗があれば更新したいと思います
読んで頂きありがとうございました!

_5da_5da
  • Discordのアイコン見かけたので参加してみました

  • サーバー絵文字にポケモンのデオキシス見つけたのでやっぱりかと(かわですね

  • #welcomeチャンネルでご挨拶をしておきました

  • 投稿も活発なのとググっても得られない情報がコミュニティ内に蓄積されていそうなので眺めてようとおもいます