效果展示
需要的插件准备
此实战项目需要用到两个插件。
-
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>
) : (
<View
style={[styles.playerInfo, isCross ? styles.playerX : styles.playerO]}
>
<Text style={styles.gameTurnTxt}>轮到 {isCross ? "X" : "O"} 下</Text>
</View>
)}
{/* 棋盘 */}
<FlatList
numColumns={3}
data={gameState}
style={styles.grid}
renderItem={({ item, index }) => (
<Pressable
key={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>
完整代码下载
完整代码