效果展示
需要的插件准备
此实战项目需要用到两个插件。
-
react-native-snackbar
底部信息提示组件。
-
react-native-vector-icons
图标组件。
安装组件:
npm i react-native-snackbar
npm i react-native-vector-icons
npm i @types/react-native-vector-icons // 使用 TS 时需要安装
使用react-native-vector-icons
插件时,需要在 IOS 和安卓的配置文件中加入对应的参数配置,而这里我是使用安卓,所以只是展示安卓的配置,IOS 的配置方法可以查看这里。
// 路径是在 android/app/build.gradle 文件中添加如下配置
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
游戏逻辑
我们棋盘采用数组的方式来维护棋盘下子情况。具体的棋盘布局图如下:
在井字游戏规则中,主要在横着连续三个、竖着连续三个、斜着连续三个棋子都算是获胜,所以通过棋盘布局图,我们可以知道有如下几种情况就可以获取:
- 数组下标[0,1,2]、[3,4,5]和[6,7,8]中的所有值相同的时候我们就可以判断为获胜
- 数组下标[0,3,6]、[1,4,7]和[2,5,8]中的所有值相同的时候我们就可以判断为获胜
- 数组下标[0,4,8]和[2,4,6]中的所有值相同的时候我们就可以判断为获胜
通过上述梳理的规则,我们就可以编写对应判断输赢的逻辑函数。这里就不做代码展示,可以下载完整代码查看。
注意: 数组下标的值必须非初始化的值(本实战中初始值是 empty),所以编写游戏逻辑时需要加上此判断。
实现核心步骤
- 编写棋子组件
// 这里的Icon组件是react-native-vector-icons组件里面的
type IconParsms = PropsWithChildren<{ name: string }>;
const Icons = (props: IconParsms) => {switch (props.name) {case "circle":return <Icon name="circle-thin" size={38} color="#F7CD2E" />;break;case "cross":return <Icon name="times" size={38} color="#38CC77" />;break;default:return <Icon name="pencil" size={38} color="#0D0D0D" />;break;}
};
- 编写下棋动作事件
下棋动作主要是监听棋盘中每个
// 点击事件,修改对应的图标
const onChangeItem = (itemNumber: number) => {// 已经有一方赢得比赛时,在点击棋盘时就会使用Snackbar组件给用户信息提示if (gameWinner) {return Snackbar.show({text: gameWinner,backgroundColor: "#000000",textColor: "#FFFFFF",});}// 判断棋盘每个位置上的棋子情况if (gameState[itemNumber] === "empty") {gameState[itemNumber] = isCross ? "cross" : "circle";setIsCross(!isCross); // 通过修改 isCross 的值判断是 ○ 还是 × 下棋} else {// 非empty的值都是已经下过子,所以就不能在下return Snackbar.show({text: "这里已有棋子",backgroundColor: "red",textColor: "#FFF",});}checkIsWinner(); // 调用判断输赢的逻辑函数
};
- 编写页面结构(样式代码在完整代码中)
<SafeAreaView><StatusBar />{/* 操作/比赛提示 */}{gameWinner ? (<View style={[styles.playerInfo, styles.winnerInfo]}><Text style={styles.winnerTxt}>{gameWinner}</Text></View>) : (<Viewstyle={[styles.playerInfo, isCross ? styles.playerX : styles.playerO]}><Text style={styles.gameTurnTxt}>轮到 {isCross ? "X" : "O"} 下</Text></View>)}{/* 棋盘 */}<FlatListnumColumns={3}data={gameState}style={styles.grid}renderItem={({ item, index }) => (<Pressablekey={index}style={styles.card}onPress={() => onChangeItem(index)}><Icons name={item} /></Pressable>)}/>{/* 游戏操作 */}<Pressable style={styles.gameBtn} onPress={reloadGame}><Text style={styles.gameBtnText}>{gameWinner ? "开始新游戏" : "重置游戏"}</Text></Pressable>
</SafeAreaView>
完整代码下载
完整代码