游戏斗兽棋,童年的回忆

游戏斗兽棋,童年的回忆

最近在某游戏平台上面玩了一款经典的游戏,《斗兽棋》,就是象、狮、虎、豹、狼、狗、猫、鼠八种棋子组成,分为红方和蓝方,童年时代经常玩的游戏,俗称“洋火皮”,哈哈。现在用 react-native 进行实现一下。下面是代码,代码里面有详细的注释。

import React, { Component } from 'react'
import { View, Text, TouchableOpacity, Button } from 'react-native';
import { navigationOptions } from './../../utils/navigationOptions';
import { createStackNavigator, createAppContainer } from "react-navigation";
import Utils from './../../utils/Utils';


class Game extends Component {
	constructor(props){
		super(props)
		this.state = {
			/**
			 *  二维数组
			 *  0 代表空白(没有棋子), 9 代表未翻开的棋子,
             *  1 ~ 8 分别代表 红色 { 象,狮,虎,豹,狼,狗,猫,鼠 } 
             *  9 ~ 16 分别代表 蓝色 { 象,狮,虎,豹,狼,狗,猫,鼠 } 
			 */
			walls: [
				// [ 1, 1, 1, 1 ],
				// [ 1, 1, 1, 1 ],
				// [ 1, 1, 1, 1 ],
				// [ 1, 1, 1, 1 ]
			],
			chesses: [
				1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
			],
			map: {
				1: '象',
				2: '狮',
				3: '虎',
				4: '豹',
				5: '狼',
				6: '狗',
				7: '猫',
				8: '鼠'
			},
			colorMap: {}, //0 代表未翻开的棋子, 1 代表翻开的棋子
			selectChess: 0, // 棋子被翻开后,再次点击被选中的棋子,0 代表都未选中,1-16 代表被选中的序号
			index: -1, // 上一次选中的棋子的一维下标,-1 代表未选中,
			index2: -1, // 上一次选中的棋子的二维下标,-1 代表未选中,
			// currentChess: 0, // 当前可走的棋子  0 代表红色方, 1 代表蓝色方 暂时没用
			// surplusChessMap: { // 剩余的棋子,双方开始各有八颗
			// 	red: 8,
			// 	blue: 8
			// }
		}
	}
	static navigationOptions = navigationOptions({ headerTitle: 'Game' })

	componentDidMount() {
		this.initWalls()
	}
	
	render() {
		const { walls } = this.state
		return (
			<View style={{flex:1, backgroundColor: '#000'}}>
				<View style={{height: '20%', justifyContent: 'space-around', alignItems: 'center'}}>
					<Text style={{color: '#fff', textAlign: 'center'}}>斗兽棋</Text>
					<Button title='重新开始' onPress={e => this.initWalls()}></Button>
				</View>
				<View style={{ flex: 1, justifyContent: 'space-around', alignItems: 'center' }}>
					{ this.init(walls) }
				</View>
			</View>
		)
	}
	/**
	 * 初始化
	 */
	init() {
		const { chesses, walls, map, colorMap, selectChess } = this.state

		return walls.map((item, index) => (
			<View style={{ width: '100%', height: 100, display: 'flex', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', backgroundColor: 'pink' }} key={'item'+index}>
				{
					item.map((item2,index2) => (
						<View style={{width: 80, height: 80, backgroundColor: 'yellow', justifyContent: 'space-around', alignItems: 'center', ...Utils.setPadding(5)}} key={'item2'+index2}>
							<TouchableOpacity onPress={e => this.touchHandle(item2,index,index2)} activeOpacity={0.7} style={{ width: selectChess == item2 ? '109%' : '90%', height: selectChess == item2 ? '108%' : '90%', backgroundColor: item2 === 0 ? 'yellow' : (colorMap[item2] ? '#adc' : '#ccc'), justifyContent: 'space-around', alignItems: 'center' }}>
								<View>
									<Text style={{ color: item2 <= 8 ? 'red' : 'blue', fontSize: selectChess == item2 ? 40 : 20 }}>{ colorMap[item2] ? (map[item2 <= 8 ? item2 : item2 - 8]) : '' }</Text>
								</View>
							</TouchableOpacity>
						</View>
					))
				}
			</View>
		))
	}
	/**
	 * 初始化棋子,初始化背景颜色
	 */
	initWalls(){
		const { chesses, walls, colorMap } = this.state
		let arr = []
		chesses.sort(this.randomSort)
		for(let i = 0, len = chesses.length; i < len; i+=4){
			arr.push(chesses.slice(i, i + 4))
		}
		chesses.map(item=>{
			colorMap[item] = 0
		})
		this.setState({
			walls: arr,
			colorMap
		})
	}
	/**
	 * 随机排序
	 */
	randomSort(){
		return Math.random() > 0.5 ? 1 : -1
	}
	/**
	 * 点击每一项触发的函数
	 * @param {*} item 当前项的值
	 * @param {*} i1 当前项的一维下标
	 * @param {*} i2 当前项的二维下表
	 */
	touchHandle(item, i1, i2) {
		const { colorMap, selectChess, walls, index, index2 } = this.state
		// 如果当前未选中任何棋子,纯粹的点击空白处,直接返回
		if(item === 0 && index === -1) return;
		if(colorMap[item] == 1 || item === 0){ // 判断是否是已经被翻开的棋子或者空白格
			if(selectChess == item){
				this.setState({
					selectChess: 0,
					index: -1,
					index2: -1
				})
			}else if(selectChess == 0){
				this.setState({
					selectChess: item,
					index: i1,
					index2: i2
				})
			}else{
				let pre1 = walls[index][index2]
				let now1 = walls[i1][i2]
				// 判断是否是同类型棋子
				let isSameType = ((pre1 > 8 && now1 > 8) || (pre1 <= 8 && now1 <= 8)) && !(pre1 === 0 || now1 === 0)
				if(isSameType){
					this.setState({
						selectChess: item
					})
					return
				}
				// 判断两次点击是否是在同一行或者同一列
				if(i1 === index || i2 === index2){
					const diff = i1 === index ? i2 - index2 : i1 - index
					// 判断两次点击是否相邻
					if(Math.abs(diff) === 1){
						let arr = JSON.parse(JSON.stringify(walls))
						let pre = walls[index][index2] > 8 ? walls[index][index2] - 8 : walls[index][index2]
						let now = walls[i1][i2] > 8 ? walls[i1][i2] - 8 : walls[i1][i2]
						if(now === 0){ // 如果当前值为0,那么上一个值直接与当前值交换位置
							arr[index][index2] = walls[i1][i2]
							arr[i1][i2] = walls[index][index2]
							this.setState({
								walls: arr,
								selectChess: 0
							})
						}else{
							// 如果上一个值大于当前值,那么保留当前值,当前值位置不变,上一个值变为0
							if(pre > now){
								if(pre1 === 8 && now1 === 9 || (pre1 === 16 && now1 === 1)){ // 如果第一次点击的是老鼠,第二次点击的是大象,那么保留老鼠pre1,并将第二次位置设置为0
									arr[i1][i2] = walls[index][index2]
									arr[index][index2] = 0
								}else{
									arr[index][index2] = 0
								}
							}else if(pre === now){ // 如果两者相等,那么两者都设置为0
								arr[index][index2] = 0
								arr[i1][i2] = 0
							}else{ // 如果当前值大于上一个值,那么保留上一个值,将当前值的位置设置为上一个值,并将上一个值的位置设置为0
								if(pre1 === 1 && now1 === 16 || (pre1 === 9 && now1 === 8)){ // 如果第一次点击的是大象,第二次点击的是老鼠,那么保留老鼠now1,并将第一次位置设置为0
									arr[index][index2] = 0
								}else{
									arr[index][index2] = 0
									arr[i1][i2] = walls[index][index2]
								}
							}
							this.setState({
								walls: arr,
								selectChess: 0
							})
						}
					}
				}
			}
		}else{
			this.setState({
				colorMap: { ...colorMap, [item]: 1 },
				selectChess: 0
			})
		}
	}
}
const AppNavigator = createStackNavigator(
	{ 
		Game:{screen:Game}
	},
	{
		initialRouteName:"Game"
	}
);
export default createAppContainer(AppNavigator)

样式就不在此贴了,因为没有美化,比较难看,只是实现了功能,而且没有进行输赢判定。后期有时间再补充吧。使用的方法可能比较绕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值