基础规则
https://blog.csdn.net/zslngu/article/details/115743943
效果
录屏2026-03-14 21.36.50-狼吃羊-reac
代码
ts
import { Role } from "@/base/MyEnums.ts"
import WolfGoatRole from "@/components/WolfGoatRole.tsx"
import { useState } from "react"
export default function WolfGoatPage() {
const row = 5
const col = 5
const [matrix, setMatrix] = useState([
["0", Role.WOLF, Role.WOLF, Role.WOLF, "0"],
["0", "0", "0", "0", "0"],
[Role.GOAT, Role.GOAT, Role.GOAT, Role.GOAT, Role.GOAT],
[Role.GOAT, Role.GOAT, Role.GOAT, Role.GOAT, Role.GOAT],
[Role.GOAT, Role.GOAT, Role.GOAT, Role.GOAT, Role.GOAT],
])
const eq = (a, b) => {
return a[0] == b[0] && a[1] == b[1]
}
const hasPieceSelect = () => {
return !eq(currClick, [-1, -1])
}
enum Status {
WAIT_SELECT_PIECE,
HAS_SELECT_PIECE,
}
const calStatus = () => {
if (hasPieceSelect()) {
return Status.HAS_SELECT_PIECE
} else {
return Status.WAIT_SELECT_PIECE
}
}
// 选中的棋子
const [currClick, setCurrClick] = useState([-1, -1])
const fetchRole = ([a, b]: number[]) : Role | string => {
return matrix[a][b]
}
const bgColor = (i, j) => {
if (fetchRole([i, j]) == Role.WOLF) {
return "bg-red-300"
} else if (fetchRole([i, j]) == Role.GOAT) {
return "bg-green-300"
}
}
interface HistoryVO {
targetPos: number[]
role: Role | string,
currentPos: number[]
msg: string
}
const [history, setHistory] = useState<Array<HistoryVO>>([])
const canNormalStep = ([i, j]: number[], [a, b]: number[]) => {
const res =
Math.abs(i - a) + Math.abs(j - b) == 1 && fetchRole([a, b]) == "0"
console.log(`judge can normal return ${res} ${[i, j]} ${[a, b]} ${fetchRole([a, b])}`)
return res
}
const copyMatrix = (param: Array<Array<number | Role | string>>) => {
return matrix.map((arr, i) => {
return arr.map((value, j) => {
let idx = 0
for (idx = 0; idx < param.length; idx++) {
const p = param[idx]
if (eq([i, j], [p[0], p[1]])) {
return p[2].toString()
}
}
return value
})
})
}
const canEat = ([i, j]: number[], [a, b]: number[]) => {
const roleCan =
fetchRole([i, j]) == Role.WOLF && fetchRole([a, b]) == Role.GOAT
const postCan =
(i == a && Math.abs(j - b) == 2) || (Math.abs(i - a) == 2 && j == b)
return roleCan && postCan
}
//
// 状态: 待选棋子 选棋子操作
// 状体;已选棋子
// 选一样的 取消选中
// 走棋 同时判断规则
const onClickCell = (i, j, e) => {
// 待选棋子
const status = calStatus()
if (status == Status.WAIT_SELECT_PIECE) {
if (fetchRole([i, j]) == '0') {
return
}
setCurrClick([i, j])
return
}
// 已选了棋子
// 取消
// 重选
// 走路
// 吃子
else if (status == Status.HAS_SELECT_PIECE) {
if (eq(currClick, [i, j])) {
setCurrClick([-1, -1])
return
} else if (fetchRole(currClick) == fetchRole([i, j])) {
setCurrClick([i, j])
return
}
else if (canNormalStep(currClick, [i, j])) {
setHistory([{
targetPos: [i, j],
currentPos: currClick,
role: fetchRole(currClick),
msg: `${fetchRole(currClick)} 从 (${currClick[0]}, ${currClick[1]}) 移动到 (${i}, ${j})`
}, ...history])
const a = Array<Array<number | Role | string>>([])
a.push([i, j, fetchRole(currClick)])
a.push([currClick[0], currClick[1], "0"])
setMatrix(copyMatrix(a))
setCurrClick([-1, -1])
return
} else if (canEat(currClick, [i, j])) {
setHistory([
{
targetPos: [i, j],
currentPos: currClick,
role: fetchRole(currClick),
msg: `${fetchRole(currClick)} 从 (${currClick[0]}, ${currClick[1]}) 吃掉了 (${i}, ${j}) 的 ${fetchRole([i, j])}`,
},
...history,
])
const a = Array<Array<number | Role | string>>([])
a.push([i, j, fetchRole(currClick)])
a.push([currClick[0], currClick[1], "0"])
setMatrix(copyMatrix(a))
setCurrClick([-1, -1])
}
}
}
return (
<div className="flex-col items-center" style={{ paddingTop: "40px" }}>
<div>当前选中棋子 {currClick}</div>
<div>
{
history
.map((value, idx, arr) => {
if (idx < 3) {
return (<p>
第{arr.length - idx}手 {value.msg}
</p>)
} else {
return (<></>)
}
})
}
</div>
<table className="w-full table-auto border-collapse">
<tbody>
{Array.from({ length: row }, (_, i) => (
<tr key={i}>
{Array.from({ length: col }, (_, j) => (
<td
key={j}
className={
"border px-10 py-15" +
(i == currClick[0] && j == currClick[1]
? " " + bgColor(i, j)
: "")
}
onClick={(e) => onClickCell(i, j, onClickCell)}
>
{matrix[i][j] === Role.WOLF ? (
<WolfGoatRole role={Role.WOLF} />
) : (
<></>
)}
{matrix[i][j] === Role.GOAT ? (
<WolfGoatRole role={Role.GOAT} />
) : (
<></>
)}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
}