在这里阅读效果更佳

还记得当年和同桌在草稿纸上下三子棋的时光吗

今天我们就用代码来重温一下年少(假设你有react基础,没有也行,只要你会三大框架的任意一种,上手react不难)

游戏规则

  • 双方各执一子,在九宫格内一方三子连成线则游戏结束
  • 九宫格下满未有三子连线则视为平局

你可以点击这里来体验最终效果,样式有点丑,请见谅

准备阶段

建议先全局安装typescript 和 create-react-app(安装过请忽略

npm install typescript create-react-app -g

使用typescript初始化项目

create-react-app demo --typescript

初始化成功后ts环境已经配好了,不需要你手动加ts配置
此时就是tsx语法,我们就可以愉快的写ts了
src文件夹就是开发目录,所有代码都写在src文件夹下
我们使用sass来写样式,先安装sass

npm install node-sass --save

运行项目

npm run start

删掉初始化界面的一些代码

开发阶段

组件化

开发一个项目其实就是开发组件
把一个项目拆分一个个小组件,方便后期维护以及复用

  1. 棋子组件
  2. 棋盘组件
  3. 游戏规则组件
  4. 游戏状态组件

react中组件分为类组件和函数组件
需要管理状态的最好使用类组件
所以我们先把App改成类组件

import React from 'react';
import './App.css';
class App extends React.Component{render(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined {return (<div className="App"></div>);}
};export default App;

开发棋子组件

在src下新建component文件夹,在component文件夹下新建ChessComp.tsx,ChessComp.css
以后我们的组件都放在component文件夹下
棋子组件我们使用函数组件,思考需要传入组件的属性的类型:

  1. type(棋子的类型)
  2. onClick(点击棋子触发的回调函数)

棋子类型有三种(红子 ,黑子, 空),
为了约束棋子类型,我们使用一个枚举类型,
在src下新建types文件夹,专门放类型约束,
在types下新建enums.ts约束棋子类型

export enum ChessType {none,red,black
}

并在棋子tsx中导入
传入tsx的所有属性用一个IProps接口约束

interface IProps {type: ChessTypeonClick?: () => void
}

全部tsx代码:

import React from 'react';
import {ChessType} from "../types/enums";
import './ChessComp.css';interface IProps {type: ChessTypeonClick?: () => void
}
function ChessComp ({type, onClick}: IProps) {let chess = null;switch (type) {case ChessType.red:chess = <div className="red chess-item"></div>;break;case ChessType.black:chess = <div className="black chess-item"></div>;break;default:chess = null;}return (<div className="chess" onClick={() => {if (type === ChessType.none && onClick) {onClick();}}}>{chess}</div>)
};
export default ChessComp;

其中棋子只有为none类型时才能被点击
scss 代码:
棋子我们用背景颜色径向渐变来模拟

$borderColor: #dddddd;
$redChess: #ff4400;
$blackChess: #282c34;
.chess{display: flex;justify-content: center;align-items: center;width: 50px;height: 50px;border: 2px solid $borderColor;box-sizing: border-box;cursor: pointer;.chess-item{width: 30px;height: 30px;border-radius: 50%;}.red{background: radial-gradient(#fff, $redChess);}.black{background: radial-gradient(#fff, $blackChess);}
}

开发棋盘组件

同理在component文件夹下新建BoardComp.tsx,BoardComp.scss
棋盘组件我们需要传递三个参数:

  1. 棋子的数组
  2. 游戏是否结束
  3. 点击事件函数

循环数组渲染棋子, 并给游戏是否结束一个默认值
全部tsx代码:

import React from 'react';
import {ChessType} from "../types/enums";
import ChessComp from "./ChessComp";
import "./BoardComp.scss";
interface IProps {chesses: ChessType[];isGameOver?: booleanonClick?: (index: number) => void
}
const BoardComp: React.FC<IProps> = function(props) {// 类型断言const isGameOver = props.isGameOver as boolean;// 非空断言// const isGameOver = props.isGameOver!;const list = props.chesses.map((type, index) => {return (<ChessComptype={type}key={index}onClick={() => {if (props.onClick && !isGameOver) {props.onClick(index)}}}/>)});return (<div className="board">{list}</div>)
};
BoardComp.defaultProps = {isGameOver: false
};
export default BoardComp;

scss 代码:
使用flex布局

.board{display: flex;flex-wrap: wrap;width: 150px;height: 150px;
}

开发游戏规则组件

在component文件夹下新建Game.tsx,Game.scss
游戏规则组件不需要传参,我们使用类组件来管理状态
在types文件夹下的enums.ts里新增游戏状态的枚举类型

export enum ChessType {none,red,black
}
export enum GameStatus {/*** 游戏中*/gaming,/*** 红方胜利*/redWin,/*** 黑方胜利*/blackWin,/*** 平局*/equal,
}

核心的代码就是如何判断游戏的状态,我的方法有点死,你们可以自己重构,

import React from 'react';
import {ChessType, GameStatus} from "../types/enums";
import BoardComp from "./BoardComp";
import GameStatusComp from "./GameStatusComp";
import './Game.scss';/*** 棋子的数组* 游戏状态* 下一次下棋的类型*/
interface Istate {chesses: ChessType[],gameStatus: GameStatus,nextChess: ChessType.red | ChessType.black
}
class Game extends React.Component<{}, Istate> {state: Istate = {chesses: [],gameStatus: GameStatus.gaming,nextChess: ChessType.black};/*** 组件挂载完初始化*/componentDidMount(): void {this.init();}/*** 初始化9宫格*/init() {const arr: ChessType[] = [];for (let i = 0; i < 9; i ++) {arr.push(ChessType.none)}this.setState({chesses: arr,gameStatus: GameStatus.gaming,nextChess: ChessType.black})}/*** 处理点击事件,改变棋子状态和游戏状态*/handleChessClick(index: number) {const chesses: ChessType[] = [...this.state.chesses];chesses[index] = this.state.nextChess;this.setState(preState => ({chesses,nextChess: preState.nextChess === ChessType.black? ChessType.red : ChessType.black,gameStatus: this.getStatus(chesses, index)}))}/*** 获取游戏状态*/getStatus(chesses: ChessType[], index: number): GameStatus {// 判断是否有一方胜利const horMin = Math.floor(index/3) * 3;const verMin = index % 3;// 横向, 纵向, 斜向胜利if ((chesses[horMin] === chesses[horMin + 1] && chesses[horMin + 1] === chesses[horMin + 2]) ||(chesses[verMin] === chesses[verMin + 3] && chesses[verMin + 3] === chesses[verMin + 6]) ||(chesses[0] === chesses[4] && chesses[4] === chesses[8] && chesses[0] !== ChessType.none) ||((chesses[2] === chesses[4] && chesses[4] === chesses[6] && chesses[2] !== ChessType.none))) {return chesses[index] === ChessType.black ? GameStatus.blackWin : GameStatus.redWin;}// 平局if (!chesses.includes(ChessType.none)) {return GameStatus.equal;}// 游戏中return GameStatus.gaming;}render(): React.ReactNode {return <div className="game"><h1>三子棋游戏</h1><GameStatusComp next={this.state.nextChess} status={this.state.gameStatus}/><BoardCompchesses={this.state.chesses}isGameOver={this.state.gameStatus !== GameStatus.gaming}onClick={this.handleChessClick.bind(this)}/><button onClick={() => {this.init()}}>重新开始</button></div>;}
}export default Game;

样式

.game{position: absolute;display: flex;flex-direction: column;align-items: center;justify-content: space-around;top: 100px;width: 250px;height: 400px;left: 50%;transform: translateX(-50%);
}

开发显示游戏状态的组件

这个组件用来显示状态,在component文件夹下新建GameStatus.tsx,GameStatus.scss
没什么好说的,直接上代码

import React from 'react';
import {ChessType, GameStatus} from "../types/enums";
import './GameStatus.scss';
interface Iprops {status: GameStatusnext: ChessType.red | ChessType.black
}
function GameStatusComp(props: Iprops) {let content: JSX.Element;if (props.status === GameStatus.gaming) {if (props.next === ChessType.red) {content = <div className="next red">红方落子</div>} else {content = <div className="next black">黑方落子</div>}} else {if (props.status === GameStatus.redWin) {content = <div className="win red">红方胜利</div>} else if (props.status === GameStatus.blackWin) {content = <div className="win black">黑方胜利</div>} else {content = <div className="win equal">平局</div>}}return (<div className="status">{content}</div>)
}export default GameStatusComp;
.status {width: 150px;.next,.win{font-size: 18px;}.win{border: 2px solid;border-radius: 5px;width: 100%;padding: 10px 0;}.equal{background-color: antiquewhite;}.red{color: #ff4400;}.black{color: #282c34;}
}

收尾

最后在app.tsx里调用game组件

import React from 'react';
import './App.scss';
import Game from "./component/Game";class App extends React.Component{render(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined {return (<div className="App"><Game/></div>);}
};export default App;

转载于:https://www.cnblogs.com/LHLVS/p/11511673.html

React + Ts 实现三子棋小游戏相关推荐

  1. 三子棋小游戏(超详细)

    目录 一.实现三子棋游戏的基本逻辑 二.具体的函数实现 1. 菜单函数 2. 棋盘的实现 2.1 棋盘的初始化 2.2 棋盘的打印 3. 玩家下棋 4. 电脑下棋 5.判断棋盘状态 三. 三个文件 3 ...

  2. 【牛客刷题】上手用C语言写一个三子棋小游戏超详解哦(电脑优化)

    作者:[南航科院小张 南航科院小张的博客 专栏:从c语言的入门到进阶 学习知识不只是要懂,还要会用:想要找到好的工作,这里给大家介绍一件可以斩获诸多大厂offer的利器–牛客网 点击免费注册和我一起开 ...

  3. 使用C语言编写三子棋小游戏

    使用C语言编写三子棋小游戏: 首先进行分析: 1.需要将游戏实现分为三个部分:头文件,函数功能实现,游戏组合测试. 2.游戏可以循环进行,不必多次打开,可采用 do...while循环结构. 3.游戏 ...

  4. C语言实现三子棋小游戏(编程思路以及代码详解)

    目录 前言 一.三子棋游戏的实现逻辑 二.创建菜单并控制游戏开始或游戏结束 三.创建棋盘并且初始化棋盘 四.打印棋盘并验证打印棋盘和初始化棋盘模块的实现 五.玩家下棋 六.电脑下棋 六.输赢判断 七. ...

  5. 如何制作三子棋小游戏

    首先,一个游戏的制作,必须由大化小,分步完成. 当我们想要制作三子棋小游戏时,必须先搞清楚这个小游戏的逻辑和原理. 三子棋是黑白棋的一种.三子棋是一种民间传统游戏,又叫九宫棋.圈圈叉叉.一条龙.井字棋 ...

  6. C语言小项目--三子棋小游戏

    学了这么长时间的C语言,你是否觉得没有一个没写过稍微长点的代码显得很没有成就感!不怕,今天带你做一个小游戏,领略一下写C和小游戏的快乐.写完记得给自己一个鼓励哦! 一.三子棋小游戏 想必大家都玩过三子 ...

  7. vs2010c语言小游戏,用C语言写一个三子棋小游戏(用VS2010实现,加强版)

    前几天写了一个三子棋小游戏,但是比较简单,因为以前写的游戏棋盘只能是3x3那么大.今天对那个程序做了两点改进: 1.现在可以实现在任意大小的棋盘上下棋了. 2.因为棋盘可能变大,为了玩家方便确定坐标, ...

  8. 呆头呆脑的电脑----三子棋小游戏(C语言版)

    目录 1.需求分析 2.程序架构 3.代码实现(分函数呈现) (1)主函数代码实现 分析: 异常处理: (2)菜单函数的实现 分析: (3)游戏函数的实现 分析: (4)棋盘的初始化 分析: (5)棋 ...

  9. 趣讲用c语言实现三子棋小游戏

    目录 直接先看看最后运行效果吧 三子棋如何设计的,及其步骤 1,源文件已经头文件的创建 2.创建主函数 3.test函数的创建 4.game函数的创建和运行 5.五个函数的实现 a.init_boar ...

最新文章

  1. 15- 深度学习之神经网络核心原理与算法-多gpu实现CNN图片分类
  2. 企业网络推广专员浅析企业网络推广初期网站优化应重视的一些问题
  3. D(X)=E(X^2)-E^2(X)
  4. clickhouse原理解析与应用实践_Hybrid App (混合应用) 技术全解析 方案原理篇
  5. 液晶显示模块的分类和基本知识
  6. BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集
  7. IO流 (二) ----- 文件流
  8. Root cause be too many concurrent connections error could not open clinet transport with jdbc uri
  9. python中的turtle如何运行_python中turtle库的简单使用教程
  10. 应用编辑器保存的htnl代码怎么正常显示在页面上
  11. P1359 租用游艇 dfs/dp/floyd/dijk/spfa DAG(有向无环图)
  12. 关于Flume断点续传(防止重复消费)的解决方案
  13. 闲鱼SPU体系构建的背后
  14. Gerrit error:remote: ERROR: The following addresses are currently registered:XXX
  15. 用小鸟云服务器搭建网站常用的伪静态设置规则
  16. html仿微信评论输入框,简单仿微信朋友圈评论功能
  17. 用vba复制模板,并根据指定的列形成多个sheet重命名
  18. 电脑保护眼睛的背景颜色
  19. python输入数字并求和_Python如何输入数字并求和
  20. 从潞晨到世界名校,实习生火热招聘中

热门文章

  1. yandex浏览器新标签页按钮显示俄文的解决方案
  2. 全本软件白名单 Quanben Software Whitelist
  3. Css3动画—扭曲、旋转
  4. 【详细齐全】FIO使用方法 及参数解析(文章末尾)
  5. 数组切分【Java蓝桥杯】
  6. 印度用什么编程语言多_2020年印度8种最佳编程键盘
  7. 深度了解 JavaScript 中 三目运算符
  8. python遍历数组的方法
  9. 第二十三篇玩转【斗鱼直播APP】系列之直播总体概览
  10. 大杀器!苹果A10X处理器曝光:10nm工艺 全新GPU加成!