0基础从前端到Web3 —— Mine Clearance Frontend(一)

  • Nigdle
  • 更新于 2024-05-24 15:49
  • 阅读 968

0基础从前端到Web3 —— Mine Clearance Frontend(一) —— Vite + React + TS

初始化项目以及通过dapp-kit连接钱包的部分就不再赘述,具体可以点击查看,如果篇幅当中遇到了一些未添加的依赖项,直接通过pnpm add -D <name>一般都可以解决。

一:链上网络切换

这里提供一个最简单的切换方式,不需要放置下拉框,也不需要添加任何其它更多的设置,只需要在调用SuiClientProvider的时候增加一个参数onNetworkChange={(network) => setNetwork(network)},它的作用是当Sui钱包插件改变链上网络的时候触发setNetwork方法,并将新的链上网络传入设置。

function App() {
    const queryClient = new QueryClient();
    const [network, setNetwork] = React.useState("testnet");
    const networks = {
        testnet: { url: getFullnodeUrl('testnet') },
        mainnet: { url: getFullnodeUrl('mainnet') },
    };

    return (
        <div>
            <QueryClientProvider client={queryClient}>
                <SuiClientProvider networks={networks} network={network as keyof typeof networks} onNetworkChange={(network) => setNetwork(network)}>
                    <WalletProvider>
                        <div className='ConnectButton'>
                            <ConnectButton />
                        </div>
                        <MineClearance />
                        <FeedBack />
                    </WalletProvider>
                </SuiClientProvider>
            </QueryClientProvider>
        </div>
    );
}

二:游戏区域

首先是一个开始游戏的按钮,它的运行逻辑要在连接钱包之后,因为后面与链上的交互都需要事先明确“我是谁”。

function MineClearance() {
    const account = useCurrentAccount();

    const StartGame = () => {
        document.getElementById('NotConnect')!.hidden = true;

        if (!account) {
            document.getElementById('NotConnect')!.hidden = false;
            return;
        }

        // console.log("Connected");
        return;
    };

    return (
        <div className='Game'>
            <div className='StartButton'>
                <Button variant="contained" onClick={StartGame}>Game</Button>
                <br></br>
                <i id="NotConnect" hidden={true}>Please Connect First!!!</i>
            </div>
            <div id='Checkerboard'>
                <DrawCheckerboard />
            </div>
        </div>
    );
}

其次我们来考虑扫雷区域该如何进行描绘,很自然联想到,它是由一个又一个小方块依次拼接而成的,而mui正好又提供了一系列的ButtonGroup,所以问题就简化成了如何通过循环进行处理这些个按钮,包括放置、点击以及后续得到反馈后实时更改按钮状态等等。<br>本篇只涉及放置以及最基本的点击逻辑,而链上调用以及反馈信息处理等部分将留到下一篇文章。

function DrawCheckerboard() {
    const clickBoard = (event: any) => {
        const r = event.target.getAttribute('button-key')
        const l = event.target.parentElement.getAttribute('button-key');
        console.log(`(${r}, ${l})`);

        let str1 = event.currentTarget.innerHTML.split('&lt;', 1)[0];
        const str2 = event.currentTarget.innerHTML.substring(str1.length);
        str1 = str1 == "x" ? "1" : "x";
        const str = str1.concat(str2);
        console.log(str);
        event.currentTarget.innerHTML = str;

        event.target.disabled = true;

        HiddenFeedBack();
        ShowFeedBack("circular_progress");
        // ShowFeedBack("success_alert");
        // ShowFeedBack("encourage_alert");
        // ShowFeedBack("failure_alert");
    }

    const childboard = [];
    let i = 1;
    while (i &lt;= MaxRow) {
        childboard.push(&lt;Button key={i} button-key={i} size="large" onClick={clickBoard} sx={{width: "1px"}}>&nbsp;&lt;/Button>);
        i += 1;
    }

    const checkerboard = [];
    let j = 1;
    while (j &lt;= MaxList) {
        checkerboard.push(&lt;ButtonGroup orientation='vertical' aria-label='Vertical button group' variant='outlined' key={j} button-key={j}>{childboard}&lt;/ButtonGroup>);
        j += 1;
    }

    return (
        &lt;Box>
            {checkerboard}
        &lt;/Box>
    );
}

三:提示信息

mui提供了加载等待、成功失败提示等ui选择,我们直接选取其中的一些进行调用,目的是当后续实现了链上调用后的信息反馈,包括但不限于游戏成功、游戏失败等提示信息。

这些信息出现的位置应当是游戏区域下方,而且若非特殊需求,应当一次只出现一个,其它的都应该隐藏,这里就需要令写函数对这系列的&lt;div>标签进行统一管理。

function FeedBack() {
    return (
        &lt;div className='FeedBack'>
            &lt;div id="circular_progress" hidden={true}>
                &lt;CircularProgress />
            &lt;/div>
            &lt;div id="success_alert" className='SuccessAlert' hidden={true}>
                &lt;Alert variant="outlined" severity="success">
                    Congratulations on your successful mine clearance!
                &lt;/Alert>
            &lt;/div>
            &lt;div id="encourage_alert" className='EncourageAlert' hidden={true}>
                &lt;Alert variant="outlined" severity="info">
                    Fortunately you didn't touch a landmine, please consider your next step!
                &lt;/Alert>
            &lt;/div>
            &lt;div id="failure_alert" className='FailureAlert' hidden={true}>
                &lt;Alert variant="outlined" severity="error">
                    Unfortunately, the minesweeper failed!
                &lt;/Alert>
            &lt;/div>
        &lt;/div>
    );
}

function ShowFeedBack(id: string) {
    // document.getElementById(id)!.hidden = false;
    if (id == "circular_progress")
        document.getElementById(id)!.hidden = false;
    else
        document.getElementById(id)!.style.display = "inline-flex";
}

function HiddenFeedBack() {
    document.getElementById("circular_progress")!.hidden = true;
    // document.getElementById("success_alert")!.hidden = true;
    // document.getElementById("encourage_alert")!.hidden = true;
    // document.getElementById("failure_alert")!.hidden = true;
    document.getElementById("success_alert")!.style.display = "none";
    document.getElementById("encourage_alert")!.style.display = "none";
    document.getElementById("failure_alert")!.style.display = "none";
}

这里的实现方式多样,呈现的只是其中一种也绝非是最优解,毕竟自己看着都有点累赘(后面可能会视情况更改)。

四:其它

完整代码可以点击查看,下面是几张实际运行图。

main.png

click.png

五:加入组织,共同进步!

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Nigdle
Nigdle
0xa745...Fe19
江湖只有他的大名,没有他的介绍。