让我们用 React 创建一个井字游戏。
欢迎大家,
在本文中,我们将使用 react 和 react hooks 创建一个井字游戏应用程序。
在我们开始创建应用程序之前,您应该熟悉
Javscript、React 和 React-hooks。
所以,不要浪费时间,让我们开始项目设置。
项目设置
在终端中转到您想要创建 react-app 的目录,
然后运行以下命令。
npx create-react-app tic-tac-toe
为了创建我们的应用程序,我使用了create-react-app
框架。
如果您想手动创建,也可以这样做。
您可以删除App.test.js
、setupTests.js
和logo.svg
。
然后App.js
按如下方式清理:
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
Hello I am react app.
</div>
);
}
export default App;
运行yarn start
或npm start
在本地主机上运行开发服务器。
项目设置到此就完成了。让我们继续下一步。
让我们构建我们的应用程序。
将我们的应用程序分解成功能。
- 首先
src/App.js
,创建一个名为的函数,calculateWinner
从数组中获取获胜者。
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
]
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i]
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a]
}
}
return null
}
我们在线阵列中存储了获胜者的线条模式,如果我们在游戏的任何时候看到这些模式中的任何一个,我们就会宣布获胜者。
- 为了计算下一回合,创建一个名为的函数
calculateNextValue
。
function calculateNextValue(squares) {
return squares.filter(Boolean).length % 2 === 0 ? 'X' : 'O'
}
- 然后,我们可以通过创建下一个函数来检查游戏的当前状态。
function calculateStatus(winner, squares, nextValue) {
return winner
? `Winner: ${winner}`
: squares.every(Boolean)
? `Scratch: Cat's game`
: `Next player: ${nextValue}`
}
现在App.css
让我们为我们的游戏板写一些样式
.game {
font: 14px 'Century Gothic', Futura, sans-serif;
margin: 20px;
min-height: 260px;
}
.game ol,
.game ul {
padding-left: 30px;
}
.board-row:after {
clear: both;
content: '';
display: table;
}
.status {
margin-bottom: 10px;
}
.restart {
margin-top: 10px;
}
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}
.square:focus {
outline: none;
background: #ddd;
}
.game {
display: flex;
flex-direction: row;
}
.game-info {
margin-left: 20px;
min-width: 190px;
}
现在让我们在 App.js 中创建游戏板
function Board() {
const [squares, setSquares] = React.useState(Array(9).fill(null))
const nextValue = calculateNextValue(squares)
const winner = calculateWinner(squares)
const status = calculateStatus(winner, squares, nextValue)
function selectSquare(square) {
if (winner || squares[square]) {
return
}
const squaresCopy = [...squares]
squaresCopy[square] = nextValue
setSquares(squaresCopy)
}
function restart() {
setSquares(Array(9).fill(null))
}
function renderSquare(i) {
return (
<button className="square" onClick={() => selectSquare(i)}>
{squares[i]}
</button>
)
}
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div className="board-row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div className="board-row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
<button className="restart" onClick={restart}>
restart
</button>
</div>
)
}
现在创建一个Game()
函数并将我们的Board()
组件放入
其中。
function Game() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
</div>
)
}
然后Game()
在里面渲染函数App()
。
function App() {
return <Game />
}
最后我们的App.js
看起来应该是这样的。
import React from 'react';
import "./App.css";
function Board() {
const [squares, setSquares] = React.useState(Array(9).fill(null))
const nextValue = calculateNextValue(squares)
const winner = calculateWinner(squares)
const status = calculateStatus(winner, squares, nextValue)
function selectSquare(square) {
if (winner || squares[square]) {
return
}
const squaresCopy = [...squares]
squaresCopy[square] = nextValue
setSquares(squaresCopy)
}
function restart() {
setSquares(Array(9).fill(null))
}
function renderSquare(i) {
return (
<button className="square" onClick={() => selectSquare(i)}>
{squares[i]}
</button>
)
}
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div className="board-row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div className="board-row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
<button className="restart" onClick={restart}>
restart
</button>
</div>
)
}
function Game() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
</div>
)
}
function calculateStatus(winner, squares, nextValue) {
return winner
? `Winner: ${winner}`
: squares.every(Boolean)
? `Scratch: Cat's game`
: `Next player: ${nextValue}`
}
function calculateNextValue(squares) {
return squares.filter(Boolean).length % 2 === 0 ? 'X' : 'O'
}
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
]
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i]
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a]
}
}
return null
}
function App() {
return <Game />
}
export default App
就这样。我们完成了。
💡 附加功能
您可以使用以下钩子将游戏的方块保存到浏览器本地主机:
function useLocalStorageState(
key,
defaultValue = '',
{serialize = JSON.stringify, deserialize = JSON.parse} = {},
) {
const [state, setState] = React.useState(() => {
const valueInLocalStorage = window.localStorage.getItem(key)
if (valueInLocalStorage) {
return deserialize(valueInLocalStorage)
}
return typeof defaultValue === 'function' ? defaultValue() : defaultValue
})
const prevKeyRef = React.useRef(key)
React.useEffect(() => {
const prevKey = prevKeyRef.current
if (prevKey !== key) {
window.localStorage.removeItem(prevKey)
}
prevKeyRef.current = key
window.localStorage.setItem(key, serialize(state))
}, [key, state, serialize])
return [state, setState]
}
export {useLocalStorageState}
谢谢阅读。
编码愉快😍。
文章来源:https://dev.to/asyncnavi/let-s-create-a-tic-tac-toe-with-react-440g