react class类组件、react-hook函数组件分别实现五子棋
前言:使用create-react-app脚手架简单搭建,不用安装其他依赖,纯
js、css
实现。这里就只是简单的说明目录结构和思路,具体的代码实现请转到 Github 查看
Git仓库(觉得可的,进去点亮星星🌟):https://github.com/chen-zuo/gobang.git
新增: 用React Hook 重写了原来的class 组件,现在可以点击按钮进行 函数组件 和 类组件 的切换
1、Class 组件
分三步:1、画出了UI,棋盘棋子 。2、点击下棋落子。 3、落子后判断输赢
![](https://i-blog.csdnimg.cn/blog_migrate/692eba52e57424a9ae7d69ca1288b2b8.png)
1.1 画出UI
在state中 初始化一个长度为20的得数组 border: Array(20).fill(null)
通过数组去循环2次生成20*20的一个棋盘,在每个格子中放入一个<div className="chessboard-cell"></div>
,
// jsx 去实现棋盘
render() {
const { border, palyArr } = this.state;
return (
<div className="chessboard-wrapper">
<div className="chessboard">
{border.map((row, rowIndex) => (
<div className="chessboard-row" key={`row + ${rowIndex}`}>
{border.map((col, colIndex) => (
<div className="chessboard-col" key={`col + ${colIndex}`}>
<div className="chessboard-cell">
{/* 这里去渲染不同类型棋子 */}
</div>
</div>
))}
</div>
))}
</div>
</div>
);
}
1.2 点击落子
首先要明确state中要保存哪些状态,当点击事件 play
落子时候要记录下面的内容
palyArr: [ /* { row: 0, col: 0, chess: 1, } */ ], //已落子的位置 chess: null, //当前棋子颜色1:黑 2:白, row: 0, //当前点击的横坐标 col: 0, //当前点击的纵坐标
![](https://i-blog.csdnimg.cn/blog_migrate/59a676d6f2b8397f4476781854d39159.png)
- 落子后根据palyArr数组去渲染已经落下的棋子
![](https://i-blog.csdnimg.cn/blog_migrate/804e7d16c312991f74103ec97ed7b312.png)
1.3 判断输赢
下面是逻辑代码, chessArr
是componentDidMount的时候生成的20* 20的数组,与棋盘的位置一一对应,其中每项为空字符串“”,当下棋后,将playArr
中的对象 放入chessArr
对应的位置中
componentDidMount() {
//生命周期初始化棋盘数组
let { chessArr } = this.state;
chessArr = Array(20).fill("");
chessArr.map((item, index) => {
chessArr[index] = Array(20).fill("");
});
this.setState({
chessArr,
});
}
// 下棋
play = (row, col) => {
let { palyArr, chess, hasWinner } = this.state;
chess = chess === 1 ? 2 : 1;
this.setState(
{
row,
col,
chess,
palyArr: [...palyArr, { row, col, chess }],
},
() => {this.getWinner(row, col)}
);
};
//判断输赢的函数
getWinner = (row, col) => {
let { palyArr, chess, chessArr } = this.state;
palyArr.map((item) => {
chessArr[item.row][item.col] = { ...item };
});
// 分别对 上下,左右,左斜,右斜 方向进行判断是否产生winner
// 上下
let colCount = 0
for (let i = col + 1; i < 20; i++) {
if (chessArr[row][i].chess !== chess) break;
colCount++;
}
for (let i = col - 1; i >= 0; i--) {
if (chessArr[row][i].chess !== chess) break;
colCount++;
}
if (colCount >= 4) {
setTimeout(() => {
let r = window.confirm("Winner: " +`${chess == 1 ? "黑棋" : "白棋"}` +"\n" + "是否再来一把?");
if (r) window.location.reload();
}, 0);
colCount = 0;
this.setState({ hasWinner: chess });
return;
}
// 左右...
// 左斜...
// 右斜...
};
2、React-hook 函数组件
判断输赢的逻辑与函数组件没有太多区别,这里使用的是自定义Hook,只需要给函数组件 暴露用于渲染的 palyArr
变量,和用于更新渲染并判断输赢的 play
方法
2.1 创建函数组件
在函数组件中引入同级目录下的自定义hook :useHook.js
import React from "react";
import useHook from "./useHook";
const GobangHook = () => {
const border = Array(20).fill(null)
let { play, palyArr } = useHook()
render(...)
}
export default GobangHook
2.2 自定义Hook
使用react hook 的API去定义变量,一些用法可以参考文章React Hook Api
import { useState } from 'react';
export default () => {
const [palyArr, setpalyArr] = useState([])
const [chess, setChess] = useState(null)
const [hasWinner, setHasWinner] = useState(null)
const [chessArr, setChessArr] = useState(() => {
let arr = Array(20).fill("")
arr.map((item, index) => {
arr[index] = Array(20).fill("");
})
return arr
})
function play(row, col){
let newChess = chess === 1 ? 2 : 1;
let newPalyArr = [...palyArr, { row, col, chess:newChess }]
setChess(newChess)
setpalyArr(newPalyArr)
getWinner(newPalyArr, newChess, chessArr, row, col)
}
function getWinner(palyArr, chess, chessArr, row, col) {
palyArr.map((item) => {
chessArr[item.row][item.col] = { ...item };
});
// 分别对 上下,左右,左斜,右斜 方向进行判断是否产生winner
...
}
//暴露变量和方法
return { palyArr, play }
}
具体的代码实现请转到 Github 查看
Git仓库(觉得可的,进去点亮星星🌟)