zoukankan      html  css  js  c++  java
  • react新手教程井字棋游戏

    react井字棋1.0

    js部分

    import React, { useState, useEffect } from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    
    // 单个格子
    function Square (props) {
        const lightLIst = props.winlist
        const num = props.num
        const [light, setLight] = useState(false)
        useEffect(() => {
            if (!lightLIst) return setLight(false)
            for (const key in lightLIst) {
                if (lightLIst[key] === num) return setLight(true)
            }
        }, [lightLIst, num])
        const cName = 'light'
        return (
            <button className={`square ${light ? cName : ''}`} onClick={props.onClick}>
                {props.value}
            </button>
        )
    }
    
    // 生成九宫格的组件
    class Board extends React.Component {
        renderSquare(i, y, x) {
            return <Square
                key={`${i}${y}`}
                winlist={this.props.winlist}
                num={i}
                value={this.props.squares[i]}
                onClick={() => this.props.onClick(i, y, x)}
            />
        }
        BoardList () {
            const row = []
            for (const arr of this.props.list) {
                row.push(<div key={`${arr[0][1]}${arr[0][2]}`}>
                    {arr.map(item => {
                        return this.renderSquare(item[0], item[1], item[2])
                    })}
                </div>)
            }
            return row
        }
        render() {
            return (
                <div>
                    {this.BoardList()}
                </div>
            )
        }
    }
    
    // 游戏组件
    class Game extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                list: [
                    [
                        [0, 3, 1],
                        [1, 3, 2],
                        [2, 3, 3]
                    ],
                    [
                        [3, 2, 1],
                        [4, 2, 2],
                        [5, 2, 3]
                    ],
                    [
                        [6, 1, 1],
                        [7, 1, 2],
                        [8, 1, 3]
                    ]
                ],
                history: [
                    {
                        squares: Array(9).fill(null),
                        xIndex: 0,
                        yIndex: 0,
                        boldNum: 0
                    }
                ],
                stepNumber:0,
                xIsNext: true,
            }
        }
        handleClick(i, y, x) {
            const history = this.state.history.slice(0, this.state.stepNumber + 1)
            const current = history[history.length - 1]
            const squares = current.squares.slice()
            if (calculateWinner(squares) || squares[i]) return
            squares[i] = this.state.xIsNext ? 'X' : 'O'
            this.setState({
                history: history.concat([{
                    squares: squares,
                    yIndex: y,
                    xIndex: x,
                    boldNum: history.length
                }]),
                stepNumber: history.length,
                xIsNext: !this.state.xIsNext,
            })
        }
        reverseHistory() {
            const history = this.state.history.slice()
            const newArr = []
            for (const key in history) {
                newArr.unshift(history[key])
            }
            this.setState({
                history: newArr
            })
        }
        jumpTo(move) {
            this.setState({
                stepNumber: move,
                xIsNext: (move % 2) === 0
            })
        }
        render() {
            const history = this.state.history
            const current = history[this.state.stepNumber]
            const winList = calculateWinner(current.squares)
            let winStatus
            winStatus = winList ? winList[0] : 0
            const winner = current.squares[winStatus]
            const lastStep = current.squares.filter((item) => {
                return item === null
            })
    
            const moves = history.map((step, move) => {
                const desc = step.boldNum ?
                    `Go to move #${step.boldNum}${winList}(x:${step.xIndex},y:${step.yIndex})`:
                    'Go to game start'
                return (
                    <li key={`${step.boldNum}`}
                        className={[step.boldNum === this.state.stepNumber ? 'bold' : '']}>
                        <button onClick={() => this.jumpTo(move)}>{desc}</button>
                    </li>
                )
            })
    
            let status
            if (winList) {
                status = 'Winner:' + winner
            } else {
                if (!winList && lastStep.length < 1) {
                    status = '平局'
                } else {
                    status = 'Next player:' + (this.state.xIsNext ? 'X' : "0")
                }
            }
            return (
                <div className="game">
                    <div className="game-board">
                        <Board
                            list={this.state.list}
                            winlist={winList}
                            squares={current.squares}
                            onClick={(i, x, y) => this.handleClick(i, x, y)}
                        />
                    </div>
                    <div className="game-info">
                        <div>{status}</div>
                        <ol>{moves}</ol>
                    </div>
                    <div>
                        <button onClick={() => this.reverseHistory()}>
                            改变排序
                        </button>
                    </div>
                </div>
            )
        }
    }
    
    // ========================================
    
    // 页面的根元素
    ReactDOM.render(
        <Game />,
        document.getElementById('root')
    );
    
    // 规定井字棋胜负的方法
    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 lines[i];
            }
        }
        return null;
    }
    

    css部分

    body {
        font: 14px "Century Gothic", Futura, sans-serif;
        margin: 20px;
    }
    
    ol, ul {
        padding-left: 30px;
    }
    
    .board-row:after {
        clear: both;
        content: "";
        display: table;
    }
    
    .status {
        margin-bottom: 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;
         34px;
    }
    
    .square:focus {
        outline: none;
    }
    
    .kbd-navigation .square:focus {
        background: #ddd;
    }
    
    .game {
        display: flex;
        flex-direction: row;
    }
    
    .game-info {
        margin-left: 20px;
    }
    
    .bold{
        font-weight: bold;
    }
    
    .light{
        background: chartreuse!important;
    }
    
    


    react井字棋2.0

    js部分

    主页面
    import React, { useState, useEffect } from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import { CanvasBox } from './canvas'
    
    // 单个格子
    function Square (props) {
        const lightList = props.winlist
    
        const num = props.num
        const [light, setLight] = useState(false)
    
        // 做判断是否处在胜利的三颗棋子中,是则高亮
        useEffect(() => {
            if (!lightList) return setLight(false)
            for (const key in lightList) {
                if (lightList[key] === num) return setLight(true)
            }
        }, [lightList, num])
    
        const str = props.value
        const winKey = props.winKey
        const canvasSquare = React.createRef()
        // 设置画布数据
        const setCanvasFn = (canvasSquare, str, lightList, winKey) => {
            const cbr = canvasSquare.current
            if (cbr.getContext){
                const cb = cbr.getContext('2d')
                // 清空画布
                cbr.height = cbr.height
                // 显示字体
                if (str) {
                    cb.beginPath()
                    cb.fillStyle = 'black'
                    cb.font = '48px sans-serif'
                    if (str === 'O') cb.fillText(str, 16,52, 60)
                    if (str === 'X') cb.fillText(str, 20,52, 60)
                    cb.closePath()
                }
                //  产生竖线
                const h = () => {
                    cb.moveTo(0, 34)
                    cb.lineTo(68,34)
                    cb.lineWidth = 8
                    cb.stroke()
                }
                //  产生横线
                const w = () => {
                    cb.moveTo(34, 0)
                    cb.lineTo(34,68)
                    cb.lineWidth = 8
                    cb.stroke()
                }
                //  产生左斜线
                const l = () => {
                    cb.moveTo(0, 0)
                    cb.lineTo(68,68)
                    cb.lineWidth = 8
                    cb.stroke()
                }
                //  产生右斜线
                const r = () => {
                    cb.moveTo(68, 0)
                    cb.lineTo(0,68)
                    cb.lineWidth = 8
                    cb.stroke()
                }
                // 游戏出现胜利结果后,使用条件判断哪个格子该产生什么线
                if (lightList) {
                    for (const key in lightList) {
                        if (lightList[key] === num) {
                            switch (winKey) {
                                case  0:
                                case  1:
                                case  2:
                                    h()
                                    break
                                case  3:
                                case  4:
                                case  5:
                                    w()
                                    break
                                case  6:
                                    l()
                                    break
                                case  7:
                                    r()
                                    break
                                default:
                                    return ''
                            }
                        }
                    }
                }
            }
        }
        useEffect(() => {
            setCanvasFn(canvasSquare, str, lightList, winKey)
        }, [str, lightList, canvasSquare, winKey])
    
        const cName = 'light'
        return (
            <canvas ref={canvasSquare} className={`square ${light ? cName : ''}`} width="68px" height="68px" onClick={props.onClick}>
                {props.value}
            </canvas>
        )
    }
    
    // 生成九宫格的组件
    class Board extends React.Component {
        renderSquare(i, y, x) {
            return <Square
                key={`${i}${y}`}
                winKey={this.props.winKey}
                winlist={this.props.winlist}
                num={i}
                value={this.props.squares[i]}
                onClick={() => this.props.onClick(i, y, x)}
            />
        }
        BoardList () {
            const row = []
            for (const arr of this.props.list) {
                row.push(<div key={`${arr[0][1]}${arr[0][2]}`}>
                    {arr.map(item => {
                        return this.renderSquare(item[0], item[1], item[2])
                    })}
                </div>)
            }
            return row
        }
        render() {
            return (
                <div>
                    {this.BoardList()}
                </div>
            )
        }
    }
    
    // 游戏组件
    class Game extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                list: [
                    [
                        [0, 3, 1],
                        [1, 3, 2],
                        [2, 3, 3]
                    ],
                    [
                        [3, 2, 1],
                        [4, 2, 2],
                        [5, 2, 3]
                    ],
                    [
                        [6, 1, 1],
                        [7, 1, 2],
                        [8, 1, 3]
                    ]
                ],
                history: [
                    {
                        squares: Array(9).fill(null),
                        xIndex: 0,
                        yIndex: 0,
                        boldNum: 0
                    }
                ],
                stepNumber:0,
                xIsNext: true,
            }
        }
        handleClick(i, y, x) {
            const history = this.state.history.slice(0, this.state.stepNumber + 1)
            const current = history[history.length - 1]
            const squares = current.squares.slice()
            if ((calculateWinner(squares) && calculateWinner(squares).arr) || squares[i]) return
            squares[i] = this.state.xIsNext ? 'X' : 'O'
            this.setState({
                history: history.concat([{
                    squares: squares,
                    yIndex: y,
                    xIndex: x,
                    boldNum: history.length
                }]),
                stepNumber: history.length,
                xIsNext: !this.state.xIsNext,
            })
        }
        reverseHistory() {
            const history = this.state.history.slice()
            const newArr = []
            for (const key in history) {
                newArr.unshift(history[key])
            }
            this.setState({
                history: newArr
            })
        }
        jumpTo(move) {
            this.setState({
                stepNumber: move,
                xIsNext: (move % 2) === 0
            })
        }
        render() {
            const history = this.state.history
            const current = history[this.state.stepNumber]
            const winKey = calculateWinner(current.squares) && calculateWinner(current.squares).key
            const winList = calculateWinner(current.squares) && calculateWinner(current.squares).arr
            let winStatus
            winStatus = winList ? winList[0] : 0
            const winner = current.squares[winStatus]
            const lastStep = current.squares.filter((item) => {
                return item === null
            })
    
            const moves = history.map((step, move) => {
                const desc = step.boldNum ?
                    `Go to move #${step.boldNum}${winList}(x:${step.xIndex},y:${step.yIndex})`:
                    'Go to game start'
                return (
                    <li key={`${step.boldNum}`}
                        className={[step.boldNum === this.state.stepNumber ? 'bold' : '']}>
                        <button onClick={() => this.jumpTo(move)}>{desc}</button>
                    </li>
                )
            })
    
            let status
            if (winList) {
                status = 'Winner:' + winner
            } else {
                if (!winList && lastStep.length < 1) {
                    status = '平局'
                } else {
                    status = 'Next player:' + (this.state.xIsNext ? 'X' : "0")
                }
            }
            return (
                <div className="game">
                    <div className="game-board">
                        <Board
                            list={this.state.list}
                            winKey={winKey}
                            winlist={winList}
                            squares={current.squares}
                            onClick={(i, x, y) => this.handleClick(i, x, y)}
                        />
                    </div>
                    <div className="game-info">
                        <div>{status}</div>
                        <ol>{moves}</ol>
                    </div>
                    <div className="game-info">
                        <button onClick={() => this.reverseHistory()}>
                            改变排序
                        </button>
                    </div>
                    <div className="game-info">
                        <CanvasBox/>
                    </div>
                </div>
            )
        }
    }
    
    // ========================================
    
    // 页面的根元素
    ReactDOM.render(
        <Game />,
        document.getElementById('root')
    );
    
    // 规定井字棋胜负的方法
    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]) {
                const data = {
                    arr: lines[i],
                    key: i
                }
                return data
            }
        }
        return null;
    }
    
    
    次要组件(可删除)
    import React, {useEffect} from 'react'
    
    export function CanvasBox() {
        const canvasBox = React.createRef()
        useEffect(() => {
            const canvas = canvasBox.current
            if (canvas.getContext) {
                const ctx = canvas.getContext('2d')
                ctx.fillStyle = '#ff0000'
                ctx.fillRect(33,0,66,33)
                ctx.moveTo(33,0)
                ctx.lineTo(33,99)
                ctx.stroke()
                ctx.moveTo(66,0)
                ctx.lineTo(66,99)
                ctx.stroke()
                ctx.moveTo(0,33)
                ctx.lineTo(99,33)
                ctx.stroke()
                ctx.moveTo(0,66)
                ctx.lineTo(99,66)
                ctx.stroke()
                ctx.fillStyle='#ff0000'
                ctx.beginPath()
                ctx.arc(49.5,49.5,14,0,Math.PI*2,true)
                ctx.closePath()
                ctx.fill()
                ctx.beginPath()
                ctx.fillStyle='white'
                ctx.font='24px'
                ctx.fillText('⚪',42.5,52.5)
                ctx.closePath()
            }
        })
        return(
            <div>
                <canvas ref={canvasBox} id='canvas-box' width='99px' height='99px' style={{ border: '1px solid #c3c3c3' }}>
                    您的浏览器不支持canvas元素
                </canvas>
                <canvas className='square' width='33px' height='33px' >
                    您的浏览器不支持canvas元素
                </canvas>
            </div>
        )
    }
    
    

    css部分

    body {
        font: 14px "Century Gothic", Futura, sans-serif;
        margin: 20px;
    }
    
    ol, ul {
        padding-left: 30px;
    }
    
    .board-row:after {
        clear: both;
        content: "";
        display: table;
    }
    
    .status {
        margin-bottom: 10px;
    }
    
    .square {
        background: #fff;
        border: 1px solid #999;
        float: left;
        height: 34px;
        box-sizing: border-box;
        padding: 0;
         34px;
    }
    
    .square:focus {
        outline: none;
    }
    
    .kbd-navigation .square:focus {
        background: #ddd;
    }
    
    .game {
        display: flex;
        flex-direction: row;
    }
    
    .game-info {
        margin-left: 20px;
    }
    
    .bold{
        font-weight: bold;
    }
    
    .light{
        background: chartreuse!important;
    }
    
    
  • 相关阅读:
    Handler详细说明系列(六)——View的post()详解
    2013年6月17日星期一
    2013年6月16日星期日
    线程管理四种方法
    java 线程 ProducerAndConsumer
    POJ 2948 DP
    Java的递归算法
    开机黑屏 仅仅显示鼠标 电脑黑屏 仅仅有鼠标 移动 [已成功解决]
    网络安全审查制度即将推出 手机App安全加密成必定趋势
    递归算法浅谈
  • 原文地址:https://www.cnblogs.com/ww-523-99/p/14004026.html
Copyright © 2011-2022 走看看