基于React + Antd 实现的斗兽棋web应用
- 项目简介
- 功能规划
- 项目源码
- 棋盘渲染
- mapitem
- gamemap(部分)
- map.json
- 棋子移动 && 规则特性 && 地形规则 && 游戏结束
- gamemap(部分)
项目简介
很高兴能以这种方式认识你,这个项目源自于学习了React官方的井字棋入门,想换一种方式,实战一下。
功能规划
-
已实现
-
未实现
-
- 棋盘渲染
-
- 棋子移动
-
- 根据棋子特性的特别移动规则
-
- 地形限制
-
- 陷阱
-
- 进入洞穴结束
-
- 更改选棋
-
- 贴图渲染
-
- 界面优化
项目源码
具体源码前往:https://gitee.com/lin-liangyou/react-beast-fighting-chess
棋盘渲染
和React官方教学案例一样思路,将棋盘的棋格单独成组件,设立属性如mapitem
,然后使用gamemap
包裹起来处理。
mapitem
import React from 'react';
import './item.css';
const Item = (props)=>{
return(
<button
id={`type${props.typeId}`}
onClick={props.onClick}
className={`itemParent ${props.classType} ${props.isChoose}`}
data-index={props.index}>
{props.name}
</button>
)
}
export default Item;
gamemap(部分)
const Map = ()=>{
//...
const listRush = () =>{
const mapAll = [];
let mapLine = [];
list.forEach(function(item,index) {
const { listName, type } = mapInit(index);
mapLine.push(
<Item
key={index}
typeId={item}
classType={(type === 'B')?'typeB':((type === 'A')?'typeA':'')}
isChoose={ (choose[0] === index || choose[1] === index) ? (nextPlayer==='Red'?'typeACHO':'typeBCHO') : ''}
name={listName||''}
onClick={ (event) => itemTouch(event) }
index={index}/>);
if( (index + 1) % 7 === 0 ){
mapLine.push(<br/>);
let parentLine = <div className="parentLine">{mapLine}</div>
mapAll.push(parentLine);
mapLine = [];
}
})
return mapAll;
}
return (
<div className='gameParent'>
<div className='title'>{`next player:${nextPlayer}`}</div>
{
listRush()
}
</div>
)
}
export default Map;
map.json
为了代码长度缩减,将用到的静态数据封装到map.json
里面,list
是地形布局,mapPOS
则是每个棋盘对应的ID,其他的如此类推,ALsit
与BList
则是存储棋子的数组,顺序按照listName
{
"list": [
0,0,2,3,2,0,0,
0,0,0,2,0,0,0,
0,0,0,0,0,0,0,
0,1,1,0,1,1,0,
0,1,1,0,1,1,0,
0,1,1,0,1,1,0,
0,0,0,0,0,0,0,
0,0,0,2,0,0,0,
0,0,2,3,2,0,0
],
"mapPOS": [
0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55,
56, 57, 58, 59, 60, 61, 62
],
"mapRiver":[
22, 23, 25, 26,
29, 30, 32, 33,
36, 37, 39, 40
],
"mapRiverBank":[
15, 16, 18, 19,
21, 24, 27,
28, 31, 34,
35, 38, 41,
43, 44, 46, 47
],
"mapTrap":[
2, 4, 10, 52, 58 ,60
],
"gameOver":[
3, 59
],
"listName":[
"鼠","猫","狗","狼","豹","虎","狮","象"
],
"AList":[
20, 12, 8, 18, 16, 6, 0, 14
],
"BList":[
42, 50, 54, 44, 46, 56, 62, 48
]
}
棋子移动 && 规则特性 && 地形规则 && 游戏结束
gamemap(部分)
const itemTouch = (e)=>{
let point = Number(e.target.dataset.index);
//判断是否为首次选子
if(choose[0] === 99){//选子状态
//合理判断
if(nextPlayer === 'Red'){
if(AList.indexOf(point) === -1){
message.warn('选子错误!');
return;
}else{//合理 -> 记录棋子类型
setChessType( AList.indexOf(point) );
}
}else{
if(BList.indexOf(point) === -1){
message.warn('选子错误!');
return;
}else{//合理 -> 记录棋子类型
setChessType( BList.indexOf(point) );
}
}
//合理 -> 选子
setChoose([point,99]);
}else{//落子状态
//落子逻辑 -> 落子点判断
const fristPoint = mapPOS.indexOf(choose[0]);
const comparePoint = mapPOS.indexOf(point);
const number = comparePoint - fristPoint;
if( Math.abs(number) === 7 || Math.abs(number) === 1){//距离计算 value:1
//下水判断
if( mapRiver.indexOf(point) !== -1 ){// 落子点 是否为水
if(chessType === 0){
}else{
message.warn('落子错误,只有鼠才能入水!');
return
}
}
}else if(chessType === 6 || chessType === 5){
console.log(`当前位置:${choose[0]}`);
if(mapRiverBank.indexOf(choose[0]) !== -1){//河岸判断
if( Math.abs(number) === 28 || Math.abs(number) === 3){//距离计算 value:3 || 2
}else{
message.warn('落子错误,你怎么跃的?!');
return;
}
}else{
message.warn('落子错误,前往河岸才可跳跃!');
return;
}
}else{
message.warn('落子错误,行动格错误!');
return;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// 吃子 && 行动 逻辑过程
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
if(nextPlayer === 'Red'){//玩家判断 -> Red行动
if( AList.indexOf(point) === -1){//踩子判断
//吃子判断
const enemy = BList.indexOf(point);
if(enemy !== -1){// 落子点 踩敌判断
// 踩敌 -> 大小比拼
if( chessType >= enemy ){
//列表移除
BList[enemy] = 99;
}else if( chessType === 0 && enemy === 7){//特殊点 1 鼠象关系
//列表移除
BList[enemy] = 99;
}else if( mapTrap.indexOf(point) !== -1 ){//陷阱判断
//列表移除
BList[enemy] = 99;
}else{
message.warn(`落子错误,打不过!它比你大${enemy-chessType}级`);
return;
}
}
//棋格行动
const obj = AList.indexOf(choose[0]);
AList[obj] = point;
}else{
message.warn('落子错误,落子点有同伴!');
return;
}
}else{//Blue行动
if( BList.indexOf(point) === -1){//踩子判断
//吃子判断
const enemy = AList.indexOf(point);
if(enemy !== -1){// 落子点 踩敌判断
// 踩敌 -> 大小比拼
if( chessType >= enemy ){
//列表移除
AList[enemy] = 99;
}else if( chessType === 0 && enemy === 7){
//列表移除
AList[enemy] = 99;
}else if( mapTrap.indexOf(point) !== -1 ){//陷阱判断
//列表移除
AList[enemy] = 99;
}else{
message.warn(`落子错误,打不过!它比你大${enemy-chessType}级`);
return;
}
}
//棋格行动
const obj = BList.indexOf(choose[0]);
BList[obj] = point;
}else{
message.warn('落子错误,落子点有同伴!');
return;
}
}
//游戏结束状态判断
if(gameOver.indexOf(point) !== -1){
alert(`游戏结束,恭喜${nextPlayer}胜利\n点击确认重新开始!!`);
window.location.reload();
}
//落子还原 -=-=- 结束动作
setChoose([99,99]);
setChessType(null);
if( nextPlayer === 'Red' )setNextPlayer('Blue');
else setNextPlayer('Red');
}
}
新人第一次发帖,欢迎大家指正批评。