Spaces:
Sleeping
Sleeping
| /* | |
| 此代码是一个React组件,用于实现一个五子棋游戏的棋盘。该棋盘能够响应用户点击,将点击位置转换为棋子坐标,并根据游戏状态更新棋盘上的棋子。 | |
| 它使用了React的hooks,Redux来管理状态,以及axios来与服务器通信。该组件还负责展现棋子的历史记录以及高亮最后一个落子位置。棋盘和棋子的样式通过CSS实现。 | |
| */ | |
| // 引入React的核心功能 | |
| import React, { useState, useEffect } from "react"; | |
| // 引入Redux的hook,用于派发action和选择器 | |
| import { useDispatch, useSelector } from 'react-redux'; | |
| // 引入Redux store中的动作 | |
| import { movePiece, tempMove } from '../store/gameSlice'; | |
| // 引入CSS样式文件 | |
| import './board.css'; | |
| // 引入背景图片 | |
| import bg from '../assets/bg.jpg'; | |
| // 引入棋盘大小的配置 | |
| import { board_size } from '../config'; | |
| // 引入游戏状态的常量 | |
| import { STATUS } from '../status'; | |
| // 引入axios库用于发起HTTP请求 | |
| import axios from 'axios'; | |
| // 定义Board组件 | |
| const Board = () => { | |
| // 使用Redux的hook来获取dispatch方法 | |
| const dispatch = useDispatch(); | |
| // 使用Redux的hook来从store中选取需要的游戏数据 | |
| const { board, currentPlayer, history, status, size, loading, winner, depth, index } = useSelector((state) => state.game); | |
| // 定义点击棋盘的事件处理函数 | |
| const handleClick = async (i, j) => { | |
| // 如果游戏正在加载或者不在游戏中,则不处理点击 | |
| if (loading || status !== STATUS.GAMING) { | |
| console.log(loading, status); | |
| console.log(' loading || status !== STATUS.GAMING '); | |
| return; | |
| } | |
| // 如果点击的位置没有棋子 | |
| if (board[i][j] === 0) { | |
| // 如果深度小于等于0,需要与服务器通信 | |
| if (depth <= 0) { | |
| try { | |
| // 先在本地进行临时移动 | |
| dispatch(tempMove([i, j])) | |
| // 向服务器发送步骤信息,并等待响应 | |
| const response = await axios.post('https://opendilabcommunity-gomoku.hf.space/gomoku_server_ui/', { | |
| command: 'step', | |
| argument: [i, j, depth], // [i,j] 表示玩家点击的动作,当depth<=0时,根据 depth 确定 Agent Type | |
| uid: ':1' // 如果需要的话,这里应填入玩家的唯一标识符 | |
| }); | |
| // 服务器响应的数据,这里假设服务器返回的 Agent 动作格式为 {'i': x, 'j': y } | |
| const agentAction = response.data.result.action; | |
| // 使用服务器返回的动作更新Redux store | |
| dispatch(movePiece({ position: [i, j, agentAction.i, agentAction.j], depth: depth })); | |
| } catch (error) { | |
| // 如果通信失败,则打印错误信息 | |
| console.error('Error communicating with the server: ', error.response || error); | |
| } | |
| } else { | |
| // 如果不需要与服务器通信,直接在本地执行移动 | |
| dispatch(tempMove([i, j])) | |
| dispatch(movePiece({ position: [i, j], depth })); | |
| console.log('depth > 0 '); | |
| } | |
| } | |
| }; | |
| // 使用effect hook来处理胜利者的出现 | |
| useEffect(() => { | |
| // 如果有胜利者出现,弹出提示框 | |
| if (winner === 1 || winner === -1) { | |
| window.alert(winner === 1 ? '黑棋获胜' : '白棋获胜') | |
| } | |
| }, [winner]); | |
| // 计算单个棋盘格子的样式 | |
| const cellStyle = { | |
| width: `${375 / board_size}px`, | |
| height: `${375 / board_size}px`, | |
| }; | |
| // 渲染棋盘组件 | |
| return ( | |
| <div className="board" style={{ backgroundImage: `url(${bg})` }}> | |
| {/* 遍历棋盘数组,渲染每一行 */} | |
| {board.map((row, i) => ( | |
| <div key={i} className="board-row"> | |
| {/* 遍历棋盘的每一列,渲染每一个格子 */} | |
| {row.map((cell, j) => { | |
| // 根据格子位置给格子添加不同的边界样式 | |
| let cellClassName = 'cell'; | |
| if (i === 0) { | |
| cellClassName += ' top'; | |
| } | |
| if (i === board_size - 1) { | |
| cellClassName += ' bottom'; | |
| } | |
| if (j === 0) { | |
| cellClassName += ' left'; | |
| } | |
| if (j === board_size - 1) { | |
| cellClassName += ' right'; | |
| } | |
| // 根据格子内棋子的状态给棋子添加不同的样式 | |
| let pieceClassname = 'piece'; | |
| if (cell === 1) { | |
| pieceClassname += ' black'; | |
| } else if (cell === -1) { | |
| pieceClassname += ' white'; | |
| } | |
| // 判断当前格子是否为最后落子的格子 | |
| let isLastCell = false; | |
| const lastMove = history[history.length - 1]; | |
| if (lastMove && (lastMove.i === i && lastMove.j === j)) { | |
| isLastCell = true; | |
| } | |
| // 如果显示历史记录索引,则计算当前棋子的序号 | |
| let number = 0; | |
| if (index) { | |
| for(let x = 0; x < history.length; x++) { | |
| if (history[x].i === i && history[x].j === j) { | |
| number = x + 1; | |
| break; | |
| } | |
| } | |
| } | |
| // 渲染每一个格子,包括棋子和最后落子的标记 | |
| return ( | |
| <div key={j} className={cellClassName} style={cellStyle} onClick={() => handleClick(i, j)}> | |
| {cell == 0 ? '' : <div className={pieceClassname}>{ number === 0 ? '' : number}</div>} | |
| {isLastCell && <div className="last" />} | |
| </div> | |
| ) | |
| })} | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| }; | |
| // 导出Board组件以便在其他文件中使用 | |
| export default Board; | |