0
点赞
收藏
分享

微信扫一扫

React 实现五子棋

Java架构领域 2024-07-24 阅读 30

简介

         本文将会基于React 实现五子棋小游戏,游戏规则为先让5颗棋子连成1线的一方获胜。

实现效果

技术实现

页面布局

<div>
    <table style={{border: '1px solid #000', borderCollapse: 'collapse', backgroundColor: 'lightgray'}}>
      <tbody>
      {
        squares.map((row, rowIndex) => {
          return <tr key={rowIndex}>
            {
              row.map((col, colIndex) => {
                return <td key={colIndex}
                           style={{border: '1px solid #000', width: '30px', height: '30px'}}

                           onClick={(event) => {
                             const clickedElement = event.target as HTMLTableCellElement;

                             const rect = clickedElement.getBoundingClientRect();
                             const x = event.clientX - rect.left;
                             const y = event.clientY - rect.top;
                             const width = clickedElement.getBoundingClientRect().width;
                             const height = clickedElement.getBoundingClientRect().height;

                             const left = x / width;
                             const top = y / height;
                             if (left < 0.5 && top < 0.5){ // 左上
                               if (rowIndex > 0){
                                 rowIndex--;
                               }
                               if (colIndex > 0){
                                 colIndex--;
                               }
                             }
                             if (left < 0.5 && top > 0.5){ // 左下

                               if (colIndex > 0){
                                 colIndex--;
                               }
                             }
                             if (left > 0.5 && top < 0.5){ // 右上
                               if (rowIndex > 0){
                                 rowIndex--;
                               }

                             }

                             let item = squares[rowIndex][colIndex];
                             if (item !== '') {
                               return;
                             }
                             if (times % 2 === 0) {
                               item = 'black';
                             } else {
                               item = 'white';
                             }
                             const newSquares = [...squares];
                             newSquares[rowIndex][colIndex] = item;

                             setTimes(times + 1);
                             setSquares(newSquares);
                           }
                           }
                >
                  {col === 'white' ?
                    <div
                      style={{
                        width: '100%',
                        height: '100%',
                        backgroundColor: 'white',
                        borderRadius: '50%',
                        position: "relative",
                        right: "-50%",
                        bottom: "-50%"
                      }}></div>
                    : (col === 'black' ?
                      <div
                        style={{
                          width: '100%',
                          height: '100%',
                          backgroundColor: 'black',
                          borderRadius: '50%',
                          position: "relative",
                          right: "-50%",
                          bottom: "-50%"
                        }}></div> : col)}
                </td>
              })
            }
          </tr>
        })
      }
      </tbody>
    </table>

  </div>

        本文用table实现游戏布局,棋盘大小为15 * 15,背景色为浅灰,棋子为白色或黑色。

        由于棋子是位于交叉点上,需要将table cell 定位到右下角, right - 50%, bottom -50%,

下棋逻辑

onClick={(event) => {
 const clickedElement = event.target as HTMLTableCellElement;

 const rect = clickedElement.getBoundingClientRect();
 const x = event.clientX - rect.left;
 const y = event.clientY - rect.top;
 const width = clickedElement.getBoundingClientRect().width;
 const height = clickedElement.getBoundingClientRect().height;

 const left = x / width;
 const top = y / height;
 if (left < 0.5 && top < 0.5) { // 左上
   if (rowIndex > 0) {
     rowIndex--;
   }
   if (colIndex > 0) {
     colIndex--;
   }
 }
 if (left < 0.5 && top > 0.5) { // 左下

   if (colIndex > 0) {
     colIndex--;
   }
 }
 if (left > 0.5 && top < 0.5) { // 右上
   if (rowIndex > 0) {
     rowIndex--;
   }

 }

 let item = squares[rowIndex][colIndex];
 if (item !== '') {
   return;
 }
 if (times % 2 === 0) {
   item = 'black';
 } else {
   item = 'white';
 }
 const newSquares = [...squares];
 newSquares[rowIndex][colIndex] = item;

 setTimes(times + 1);
 setSquares(newSquares);
}
}

        基于times控制是白方还是黑方,然后更新squares状态,棋盘会根据squares状态进行显示。

        对于每个交叉点,棋子是以交叉点为右下角的table cell。

        计算点击位置位于table cell的哪个区域,然后计算交叉点对应的table cell。

        左上 -> r-- c--

        右上 -> r-- c

        左下 -> r c--

        右下 -> r ,c

获胜逻辑判断

    useEffect(()=>{

        // 计算dp的值
        for (let i = 0; i < 15; i++) {
            for (let j = 0; j < 15; j++) {
                if (squares[i][j] === '') {
                    continue;
                }
                // 判断左边
                if (j >= 5){
                    let num = 1;
                    for (let k = 1; k < 5; k++) {
                        if (squares[i][j - k] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断上边
                if (i >= 5){
                    let num = 1;
                    for (let k = 1; k < 5; k++) {
                        if (squares[i - k][j] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断右边
                if (j <= 10){
                    let num = 1;
                    for (let k = 1; k < 5; k++) {
                        if (squares[i][j + k] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断下边
                if (i <= 10){
                    let num = 1;
                    for (let k = 1; k < 5; k++){
                        if (squares[i + k][j] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    console.log(i + ',' + j + ':'+ num)
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断左上
                if (i >= 5 && j >= 5){
                    let num = 1;
                    for (let k = 1; k < 5; k++) {
                        if (squares[i - k][j - k] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断右上
                if (i <= 10 && j >= 5){
                    let num = 1;
                    for (let k = 1; k < 5; k++) {
                        if (squares[i + k][j - k] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断左下
                if (i >= 5 && j <= 10){
                    let num = 1;
                    for (let k = 1; k < 5; k++) {
                        if (squares[i - k][j + k] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
                // 判断右下
                if (i <= 10 && j <= 10){
                    let num = 1;
                    for (let k = 1; k < 5; k++){
                        if (squares[i + k][j + k] === squares[i][j]) {
                            num++;
                        } else {
                            break;
                        }
                    }
                    if (num >= 5) {
                        alert(squares[i][j] +'win');
                        setSquares(initSquares)
                        setTimes(0);
                        return;
                    }
                }
            }
        }

    }, [squares])

         判断每个棋子上下左右,左上,右上,左下,右下是否有连续5个棋子。

整体代码

const Board = () => {
  /**
   * 创建一个 15 * 15  的棋盘
   */
  const initSquares = Array.from({length: 15},
    () => new Array(15).fill(''));
  const [squares, setSquares] = useState(initSquares);
  const [times, setTimes] = useState(0);
  useEffect(() => {

    // 计算dp的值
    for (let i = 0; i < 15; i++) {
      for (let j = 0; j < 15; j++) {
        if (squares[i][j] === '') {
          continue;
        }
        // 判断左边
        if (j >= 5) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i][j - k] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断上边
        if (i >= 5) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i - k][j] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断右边
        if (j <= 10) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i][j + k] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断下边
        if (i <= 10) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i + k][j] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断左上
        if (i >= 5 && j >= 5) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i - k][j - k] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断右上
        if (i <= 10 && j >= 5) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i + k][j - k] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断左下
        if (i >= 5 && j <= 10) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i - k][j + k] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
        // 判断右下
        if (i <= 10 && j <= 10) {
          let num = 1;
          for (let k = 1; k < 5; k++) {
            if (squares[i + k][j + k] === squares[i][j]) {
              num++;
            } else {
              break;
            }
          }
          if (num >= 5) {
            alert(squares[i][j] + '----' + 'win');
            setSquares(initSquares)
            setTimes(0);
            return;
          }
        }
      }
    }

  }, [squares])

  return <div>
    <table style={{border: '1px solid #000', borderCollapse: 'collapse', backgroundColor: 'lightgray'}}>
      <tbody>
      {
        squares.map((row, rowIndex) => {
          return <tr key={rowIndex}>
            {
              row.map((col, colIndex) => {
                return <td key={colIndex}
                           style={{border: '1px solid #000', width: '30px', height: '30px'}}

                           onClick={(event) => {
                             const clickedElement = event.target as HTMLTableCellElement;

                             const rect = clickedElement.getBoundingClientRect();
                             const x = event.clientX - rect.left;
                             const y = event.clientY - rect.top;
                             const width = clickedElement.getBoundingClientRect().width;
                             const height = clickedElement.getBoundingClientRect().height;

                             const left = x / width;
                             const top = y / height;
                             if (left < 0.5 && top < 0.5) { // 左上
                               if (rowIndex > 0) {
                                 rowIndex--;
                               }
                               if (colIndex > 0) {
                                 colIndex--;
                               }
                             }
                             if (left < 0.5 && top > 0.5) { // 左下

                               if (colIndex > 0) {
                                 colIndex--;
                               }
                             }
                             if (left > 0.5 && top < 0.5) { // 右上
                               if (rowIndex > 0) {
                                 rowIndex--;
                               }

                             }

                             let item = squares[rowIndex][colIndex];
                             if (item !== '') {
                               return;
                             }
                             if (times % 2 === 0) {
                               item = 'black';
                             } else {
                               item = 'white';
                             }
                             const newSquares = [...squares];
                             newSquares[rowIndex][colIndex] = item;

                             setTimes(times + 1);
                             setSquares(newSquares);
                           }
                           }
                >
                  {col === 'white' ?
                    <div
                      style={{
                        width: '100%',
                        height: '100%',
                        backgroundColor: 'white',
                        borderRadius: '50%',
                        position: "relative",
                        right: "-50%",
                        bottom: "-50%"
                      }}></div>
                    : (col === 'black' ?
                      <div
                        style={{
                          width: '100%',
                          height: '100%',
                          backgroundColor: 'black',
                          borderRadius: '50%',
                          position: "relative",
                          right: "-50%",
                          bottom: "-50%"
                        }}></div> : col)}
                </td>
              })
            }
          </tr>
        })
      }
      </tbody>
    </table>

  </div>
}
举报

相关推荐

0 条评论