对于一些复杂或不规则的UI,我们可能无法通过组合其它组件的方式来实现,比如我们需要一个
- 正六边形
- 一个渐变的圆形进度条
- 一个棋盘等。
当然,有时候我们可以使用图片来实现,但在一些需要动态交互的场景静态图片也是实现不了的,比如要实现一个手写输入面板,这时,我们就需要来自己绘制UI外观
几乎所有的UI系统都会提供一个自绘UI的接口,这个接口通常会提供一块2D画布Canvas,Canvas内部封装了一些基本绘制的API,开发者可以通过Canvas绘制各种自定义图形。在Flutter中,提供了一个CustomPaint 组件,它可以结合画笔CustomPainter来实现自定义图形绘制。
CustomPaint
我们看看CustomPaint构造函数:
CustomPaint({Key key,this.painter,this.foregroundPainter,this.size = Size.zero,this.isComplex = false,this.willChange = false,Widget child, //子节点,可以为空})
- painter: 背景画笔,会显示在子节点后面;
- foregroundPainter: 前景画笔,会显示在子节点前面
- size:
- 当child为null时,代表默认绘制区域大小
- 如果有child则忽略此参数,画布尺寸则为child尺寸
- 如果有child但是想指定画布为特定大小,可以使用SizeBox包裹CustomPaint实现。
- isComplex:是否复杂的绘制,如果是,Flutter会应用一些缓存策略来减少重复渲染的开销。
- willChange:和isComplex配合使用,当启用缓存时,该属性代表在下一帧中绘制是否会改变。
可以看到,绘制时我们需要提供前景或背景画笔,两者也可以同时提供。我们的画笔需要继承CustomPainter类,我们在画笔类中实现真正的绘制逻辑
注意
如果CustomPaint有子节点,为了避免子节点不必要的重绘并提高性能,通常情况下都会将子节点包裹在RepaintBoundary组件中,这样会在绘制时就会创建一个新的绘制层(Layer),其子组件将在新的绘制层(Layer)上绘制,而父组件将在原来Layer上绘制,也就是说RepaintBoundary 子组件的绘制将独立于父组件的绘制,RepaintBoundary会隔离其子节点和CustomPaint本身的绘制边界。示例如下:
CustomPaint(size: Size(300, 300), //指定画布大小painter: MyPainter(),child: RepaintBoundary(child:...)),)
CustomPainter
CustomPainter中提定义了一个虚函数paint:
void paint(Canvas canvas, Size size);
paint有两个参数:
- Canvas:一个画布,包括各种绘制方法,我们列出一下常用的方法:
- drawLine 画线
- drawPoint 画点
- drawPath 画路径
- drawImage 画图像
- drawRect 画矩形
- drawCircle 画圆
- drawOval 画椭圆
- drawArc 画圆弧
- Size:当前绘制区域大小
画笔Paint
现在画布有了,我们最后还缺一个画笔,Flutter提供了Paint类来实现画笔。在Paint中,我们可以配置画笔的各种属性如粗细、颜色、样式等。如:
var paint = Paint() //创建一个画笔并配置其属性..isAntiAlias = true //是否抗锯齿..style = PaintingStyle.fill //画笔样式:填充..color=Color(0x77cdb175);//画笔颜色
更多的配置属性读者可以参考Paint类定义。
示例:五子棋/盘
下面我们通过一个五子棋游戏中棋盘和棋子的绘制来演示自绘UI的过程,首先我们看一下我们的目标效果,如图所示:
代码:
import 'package:flutter/material.dart';import 'dart:math';void main() => runApp(new MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: true,title: 'CustomPaintRoute',theme: ThemeData(primarySwatch: Colors.blue,),home: Scaffold(appBar: AppBar(title: Text("CustomPaintRoute")),body: CustomPaintRoute(),));}}class CustomPaintRoute extends StatelessWidget {@overrideWidget build(BuildContext context) {return Center(child: CustomPaint(size: Size(300, 300), //指定画布大小painter: MyPainter(),),);}}class MyPainter extends CustomPainter {@overridevoid paint(Canvas canvas, Size size) {double eWidth = size.width / 15;double eHeight = size.height / 15;//画棋盘背景var paint = Paint()..isAntiAlias = true..style = PaintingStyle.fill //填充..color = Color(0x77cdb175); //背景为纸黄色canvas.drawRect(Offset.zero & size, paint);//画棋盘网格paint..style = PaintingStyle.stroke //线..color = Colors.black87..strokeWidth = 1.0;for (int i = 0; i <= 15; ++i) {double dy = eHeight * i;canvas.drawLine(Offset(0, dy), Offset(size.width, dy), paint);}for (int i = 0; i <= 15; ++i) {double dx = eWidth * i;canvas.drawLine(Offset(dx, 0), Offset(dx, size.height), paint);}//画一个黑子paint..style = PaintingStyle.fill..color = Colors.black;canvas.drawCircle(Offset(size.width / 2 - eWidth / 2, size.height / 2 - eHeight / 2),min(eWidth / 2, eHeight / 2) - 2,paint,);//画一个白子paint.color = Colors.white;canvas.drawCircle(Offset(size.width / 2 + eWidth / 2, size.height / 2 - eHeight / 2),min(eWidth / 2, eHeight / 2) - 2,paint,);}//在实际场景中正确利用此回调可以避免重绘开销,本示例我们简单的返回true@overridebool shouldRepaint(CustomPainter oldDelegate) => true;}
性能
绘制是比较昂贵的操作,所以我们在实现自绘控件时应该考虑到性能开销,下面是两条关于性能优化的建议:
- 尽可能的利用好shouldRepaint返回值:在UI树重新build时,控件在绘制前都会先调用该方法以确定是否有必要重绘;
- 假如我们绘制的UI不依赖外部状态,那么就应该始终返回false,因为外部状态改变导致重新build时不会影响我们的UI外观;
- 如果绘制依赖外部状态,那么我们就应该在shouldRepaint中判断依赖的状态是否改变,如果已改变则应返回true来重绘,反之则应返回false不需要重绘。
绘制尽可能多的分层:在上面五子棋的示例中,我们将棋盘和棋子的绘制放在了一起,这样会有一个问题:由于棋盘始终是不变的,用户每次落子时变的只是棋子,但是如果按照上面的代码来实现,每次绘制棋子时都要重新绘制一次棋盘,这是没必要的。优化的方法就是将棋盘单独抽为一个组件,并设置其shouldRepaint回调值为false,然后将棋盘组件作为背景。然后将棋子的绘制放到另一个组件中,这样每次落子时只需要绘制棋子。
总结
自绘控件非常强大,理论上可以实现任何2D图形外观,实际上Flutter提供的所有组件最终都是通过调用Canvas绘制出来的,只不过绘制的逻辑被封装起来了,读者有兴趣可以查看具有外观样式的组件源码,找到其对应的RenderObject对象,
如Text对应的RenderParagraph对象最终会通过Canvas实现文本绘制逻辑
对比HTML+JS中的canvas
<style>canvas { background:rgba(222, 222, 222, 0.3) }div { background: gray;float: left;}</style><div></div><canvas id="myCanvas" width="400px" height="400px"></canvas></div><div><canvas id="mycanvas2" width="600px" height="600px"></canvas></div><div><canvas id="mycanvas3" width="800px" height="500px" style="background: red;"></canvas></div><div> <canvas id="mycanvas4" width="500px" height="500px"></canvas></div><script>var c = document.querySelector("#myCanvas");var ctx = c.getContext("2d");var cX = 200; //y轴坐标var cY = 200; //x轴坐标var r = 200; //半径var deg = 0; //角度var angle = deg * Math.PI / 180; //弧度var start = Math.PI / 2;var end = start + Math.PI;var ang = Math.PI / 180; //弧度function drawCirle(ctx, x, y, r, start, end, color = "#000", anti = false) {ctx.beginPath();ctx.fillStyle = color;ctx.arc(x, y, r, start, end, anti);ctx.fill();}setInterval(function () {ctx.clearRect(0, 0, c.width, c.height);drawCirle(ctx, cX, cY, r, start + deg * ang, end + deg * ang, "#000", false);drawCirle(ctx, cX, cY, r, start + deg * ang, end + deg * ang, "#fff", true);drawCirle(ctx, cX + (r / 2) * Math.sin(deg * ang), cY - (r / 2) * Math.cos(deg * ang), r / 2, 0, Math.PI * 2, "#000", true);drawCirle(ctx, cX - (r / 2) * Math.sin(deg * ang), cY + (r / 2) * Math.cos(deg * ang), r / 2, 0, Math.PI * 2, "#fff", false);drawCirle(ctx, cX + (r / 2) * Math.sin(deg * ang), cY - (r / 2) * Math.cos(deg * ang), 20, 0, Math.PI * 2, "#fff", true);drawCirle(ctx, cX - (r / 2) * Math.sin(deg * ang), cY + (r / 2) * Math.cos(deg * ang), 20, 0, Math.PI * 2, "#000", true);deg++;c.style.transform = "rotate(" + deg + "deg)";}, 100);</script><script>var mycanvas = document.querySelector("#mycanvas2");var ctx2 = mycanvas.getContext("2d");setInterval(function () {ctx2.beginPath();ctx2.strokeStyle = "rgb(" + rand(0, 255) + "," + rand(0, 255) + "," + rand(0, 255) + ")";ctx2.lineWidth = 3;ctx2.moveTo(rand(0, 500), rand(0, 500));ctx2.lineTo(rand(0, 600), rand(0, 600));ctx2.stroke();}, 1000);function rand(min, max) {return Math.round(Math.random() * (max - min)) + min;}setInterval(function () {ctx2.beginPath();//填充坐标ctx2.fillRect(rand(0, 300), rand(0, 300), rand(0, 300), rand(0, 300));//边框颜色ctx2.strokeStyle = "rgb(" + rand(0, 200) + "," + rand(0, 200) + "," + rand(0, 200) + ")";ctx2.lineWidth = 2;//边框坐标ctx2.strokeRect(rand(1, 300), rand(1, 300), rand(1, 300), rand(1, 300));//填充颜色ctx2.fillStyle = "rgb(" + rand(0, 255) + "," + rand(0, 255) + "," + rand(0, 255) + ")";}, 3000)</script><script type="text/javascript">var mycanvas=document.querySelector("#mycanvas3");var cx=mycanvas.getContext("2d");function drawstar(cxt,x,y,R,r,fillStyle,rot){cxt.beginPath();for (var i=0;i<5;i++) {cxt.lineTo(Math.cos((18+72*i)/180*Math.PI+rot)*R+x,-Math.sin((18+72*i)/180*Math.PI+rot)*R+y);cxt.lineTo(Math.cos((54+72*i)/180*Math.PI+rot)*r+x,-Math.sin((54+72*i)/180*Math.PI+rot)*r+y);}cxt.fillStyle=fillStyle;cxt.closePath();cxt.fill()}drawstar(cx,120,130,80,35,"yellow",0)drawstar(cx,250,50,30,12,"yellow",12)drawstar(cx,300,110,30,12,"yellow",-12)drawstar(cx,290,200,30,12,"yellow",-12)drawstar(cx,220,250,30,12,"yellow",12)</script><script type="text/javascript">var mycanvas = document.querySelector("#mycanvas4");var cx = mycanvas.getContext("2d");function drawCircle({fillStyle,x,y,r,start,end,color}) {cx.beginPath();cx.fillStyle = color||"#fff";cx.arc(x||250, y||250, r||200, start||0, end||Math.PI*2)cx.fill();}function drawLine({strokeColor,lineWidth,y,r,start,end,color,x1,y1,x2,y2}) {cx.beginPath();cx.strokeStyle=strokeColor||"red";cx.lineWidth=lineWidth||"8"cx.moveTo(x1||240,y1||140);cx.lineTo(x2||160,y2||220);cx.stroke();}drawCircle({color:'red',x:250,y:250,r:200})drawCircle({color:'#fff',x:250,y:250,r:194})drawCircle({color:'red',x:250,y:250,r:190})drawCircle({color:'#fff',x:250,y:250,r:145})drawCircle({color:'red',x:250,y:250,r:139})drawCircle({color:'#fff',x:250,y:250,r:133})drawLine({x1:240,y1:140,x2:160,y2:220})drawLine({x1:160,y1:216,x2:228,y2:300})drawLine({x1:228,y1:300,x2:280,y2:300})</script>
JS画板绘图
<style type="text/css">body{background-color:#8fbc8f;}#bj{margin:0 400px;width:530px;height:700px;border-radius:20px;background-color:#000;}canvas{margin:15px;border-radius:20px;background-color:#fff;}#to{margin:0 100px;color:#FFF;}input{margin:0 8px;}</style><div id="bj"><canvas id="mycanvas" width="500px" height="600px"></canvas><div id="to">画笔颜色:<input id="color" type="color" /> 画笔大小:<input type="number" id="number" min="1" max="20" value="1" /></div></div><script>var mycanvas = document.querySelector("#mycanvas");var cxt = mycanvas.getContext("2d");var color = "#000";var lineWith = 2;//接触鼠标时候,然后在移动鼠标时候mycanvas.onmousedown = function (e) {start_draw();cxt.moveTo(e.clientX - mycanvas.offsetLeft, e.clientY - mycanvas.offsetTop);mycanvas.addEventListener("mousemove", draw);}//松开鼠标mycanvas.onmouseup = function () {mycanvas.removeEventListener("mousemove", draw);}//选择画笔document.querySelector("#color").oninput = function () {color = this.value;}//选择画笔大小document.querySelector("#number").oninput = function () {lineWith = this.value;}//开始画function start_draw() {cxt.beginPath();cxt.strokeStyle = color;cxt.lineWidth = lineWith;}function draw(e) {e.preventDefault();cxt.lineTo(e.clientX - mycanvas.offsetLeft, e.clientY - mycanvas.offsetTop);cxt.stroke();}</script>
JS canvas绘制象棋
<!DOCTYPE html><html><head><meta charset="utf-8"><title></title><!--<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>--><!--<link rel="stylesheet" type="text/css" href="css/chess.css"/>--><script src="js/jquery.js" type="text/javascript" charset="utf-8"></script></head><style type="text/css">* {margin: 0;padding: 0}#Wrap {width: 700px;height: 640px;margin: 0 auto}#currActive {font-size: 30px;font-weight: 700;margin-left: 260px;margin: 8px 250px}#canvas {float: left;background: #EAC591;display: block}#take_notes {width: 80px;height: 645px;padding: 10px;float: right;overflow: hidden;display: flex;flex-direction: column-reverse;}#ul {list-style: none;margin: 0;padding: 0}#ul li {padding: 2px;overflow: hidden}#shuying {float: left}#shuying p {margin: 10px;font-size: 30px}#main {width: 600px;height: 150px;-webkit-justify-content: space-around;display: flex; //分横栏justify-content: space-around}#main div {width: 100px;height: 50px;line-height: 50px;text-align: center;margin-top: 10px;border-radius: 20%;font-weight: 700}#main div a {text-decoration: none;color: #000}#main div a:hover {color: #00f}#main div ul {list-style: none;position: relative}#main div ul {position: absolute}.daohang {position: absolute;display: none;margin-left: 18px;margin-top: -190px;background: pink;border-radius: 10%}.daohang a {font: "微软雅黑";font-size: 15px;margin-top: -6px}#dianji:hover .daohang {display: block}#red_zi {color: red}</style><body><div id="Wrap"><div id="currActive"></div><canvas id="canvas" width="600" height="660"></canvas><div id="take_notes"><div id="shuying"></div><ul id="ul"></ul></div><div id="main"><div style="background-color:coral;"><a href="canvas绘制象棋.html">重新开始</a></div><div style="background-color:lightblue;"><a href="#">提示</a></div><div style="background-color:khaki;"><a href="#">悔棋</a></div><div style="background-color:pink;" id="dianji"><a href="#">设置</a><ul class="daohang"><li class="daohang_1"><a href="#">棋盘大小</a></li><li class="daohang_2"><a href="#">棋子大小</a></li><li class="daohang_3"><a href="#">棋子颜色</a></li></ul></div></div></body><script>var obj = {};// 棋盘初始化obj.init = function (lqfs) {var canvas = document.querySelector("canvas");this.ctx = canvas.getContext("2d");// 棋盘初始化obj.init_back = function () {this.drawRowLine();this.drawColLine();this.ctx.clearRect(this.chunk + 1, this.chunk * 5 + 1, this.chunk * 8 - 2, this.chunk - 2);this.drawsharpS();this.drawX();this.drawText();}// this.chunk =lqfs&&lqfs.chunk?lqfs.chunk:50;// this.radius =lqfs&&lqfs.radius?lqfs.radius:23;// this.CandidateCircleR =lqfs&&lqfs.ccr?lqfs.ccr:5;/*---------------------------可以修改棋盘、棋子大小,颜色,谁先手 ------------------------------------------------------------*/obj.chunk = 60; //棋盘线格大小this.radius = this.chunk / 2 - 3; // 棋子半径this.CandidateCircleR = this.chunk / 10; //候选棋子的半径大小this.drawCandidateCircle_fillStyle = "#fff"; //候选的内圆颜色this.drawCandidateCircle_strokeStyle = "red"; //候选的内圆边框原色this.drawCandidateCircle_lineWidth = 2; //候选内圆的边框大小this.init_back();this.init_chess();$(canvas).unbind();this.addEvent();this.Notations = []; // 记录步骤this.currActive = "red"; // 先下$("#currActive").text("红方先下").css({ "color": "red", })/*---------------------------------------------------------------------------------------------------------------------------------*/}/*---------------------------------------------------------------------------------------------------------------------------------*/// 棋子初始化obj.init_chess = function () {//上方(红)var Car_b1 = { x: 1, y: 1, text: "車" }var Horse_b1 = { x: 2, y: 1, text: "馬" }var Elephant_b1 = { x: 3, y: 1, text: "象" }var Scholar_b1 = { x: 4, y: 1, text: "士" }var Boss_b = { x: 5, y: 1, text: "将" }var Scholar_b2 = { x: 6, y: 1, text: "士" }var Elephant_b2 = { x: 7, y: 1, text: "象" }var Horse_b2 = { x: 8, y: 1, text: "馬" }var Car_b2 = { x: 9, y: 1, text: "車" }var Cannon_b1 = { x: 2, y: 3, text: "炮" }var Cannon_b2 = { x: 8, y: 3, text: "炮" }var Soldier_b1 = { x: 1, y: 4, text: "卒" }var Soldier_b2 = { x: 3, y: 4, text: "卒" }var Soldier_b3 = { x: 5, y: 4, text: "卒" }var Soldier_b4 = { x: 7, y: 4, text: "卒" }var Soldier_b5 = { x: 9, y: 4, text: "卒" }//下方(黑)var Car_r1 = { x: 1, y: 10, text: "車" }var Horse_r1 = { x: 2, y: 10, text: "馬" }var Elephant_r1 = { x: 3, y: 10, text: "相" }var Scholar_r1 = { x: 4, y: 10, text: "仕" }var Boss_r = { x: 5, y: 10, text: "帅" }var Scholar_r2 = { x: 6, y: 10, text: "仕" }var Elephant_r2 = { x: 7, y: 10, text: "相" }var Horse_r2 = { x: 8, y: 10, text: "馬" }var Car_r2 = { x: 9, y: 10, text: "車" }var Cannon_r1 = { x: 2, y: 8, text: "炮" }var Cannon_r2 = { x: 8, y: 8, text: "炮" }var Soldier_r1 = { x: 1, y: 7, text: "兵" }var Soldier_r2 = { x: 3, y: 7, text: "兵" }var Soldier_r3 = { x: 5, y: 7, text: "兵" }var Soldier_r4 = { x: 7, y: 7, text: "兵" }var Soldier_r5 = { x: 9, y: 7, text: "兵" }this.cheer_arr_B = [Car_b1, Horse_b1, Elephant_b1, Scholar_b1, Boss_b, Scholar_b2, Elephant_b2, Horse_b2, Car_b2,Cannon_b1, Cannon_b2, Soldier_b1, Soldier_b2, Soldier_b3, Soldier_b4, Soldier_b5];this.cheer_arr_R = [Car_r1, Horse_r1, Elephant_r1, Scholar_r1, Boss_r, Scholar_r2, Elephant_r2, Horse_r2, Car_r2,Cannon_r1, Cannon_r2, Soldier_r1, Soldier_r2, Soldier_r3, Soldier_r4, Soldier_r5];var that = this;$.each(this.cheer_arr_B, function (i, e) {e.color = "#000"; //圆的文字颜色e.bgcolor = "#fff"; //圆的背景颜色e.bgColor_b = "#000"; //外边的框颜色e.type = "black";that.drawPiece(e);that.drawChessText(e);});$.each(this.cheer_arr_R, function (i, e) {e.color = "#f00"; //圆的文字颜色e.bgcolor = "#fff"; //圆的背景颜色e.bgColor_b = "#f00"; //外边的框颜色e.type = "red";that.drawPiece(e);that.drawChessText(e);});this.cheer_arr_ALL = this.cheer_arr_B.concat(this.cheer_arr_R);}/*--------------------------------------------------------------------------------------------------------------------------------------*/// 画棋子形状obj.drawPiece = function (e) {this.ctx.beginPath();this.ctx.fillStyle = e.bgcolor;this.ctx.strokeStyle = e.bgColor_b;this.ctx.lineWidth = 2;this.ctx.arc(e.x * this.chunk, e.y * this.chunk, this.radius, 0, Math.PI * 2, true); //this.radius棋子大小this.ctx.closePath();this.ctx.fill();this.ctx.stroke();}/*--------------------------------------------------------------------------------------------------------------------------------------*/// 画棋子文字obj.drawChessText = function (e) {var font = "" + this.chunk / 1.5 + "px "this.ctx.font = "bold " + font + " Courier New";this.ctx.fillStyle = e.color;var offset = this.ctx.measureText(e.text).width / 2;this.ctx.fillText(e.text, e.x * this.chunk - offset, e.y * this.chunk + this.chunk / 4.5);}/*---------------------------------------------------------------------------------------------------------------------------------*/// 画直线obj.drawLine = function (x0, y0, x1, y1, lw) {this.ctx.beginPath();var x0 = x0 * this.chunk;var y0 = y0 * this.chunk;var x1 = x1 * this.chunk;var y1 = y1 * this.chunk;this.ctx.strokeStyle = "#000";this.ctx.lineWidth = lw ? lw : 1;this.ctx.moveTo(x0, y0);this.ctx.lineTo(x1, y1);this.ctx.closePath();this.ctx.stroke();}/*---------------------------------------------------------------------------------------------------------------------------------*/// 画横线obj.drawRowLine = function () {for (var i = 1; i <= 10; i++) {this.drawLine(1, i, 9, i);}}// 画竖线obj.drawColLine = function () {for (var i = 1; i <= 9; i++) {this.drawLine(i, 1, i, 10);}}// 画Xobj.drawX = function () {this.drawLine(4, 1, 6, 3, 0.5);this.drawLine(4, 3, 6, 1, 0.5);this.drawLine(4, 8, 6, 10, 0.5);this.drawLine(4, 10, 6, 8, 0.5);}/*---------------------------------------------------------------------------------------------------------------------------------*/// 画单个#obj.drawsharp = function (x, y) {var x = x * this.chunk;var y = y * this.chunk;var range_y = this.chunk / 4.3; /*#的竖的距离*/var range_x = this.chunk / 4.3; /*#的横的距离*/var range_close = this.chunk / 12; /*间隔距离*//*var range_y=10;var range_x=10;var range_close=5; */this.ctx.beginPath();this.ctx.strokeStyle = "#000";this.ctx.lineWidth = 1;if (x != 1) {// 左上this.ctx.moveTo(x - range_close, y - range_y);this.ctx.lineTo(x - range_close, y - range_close);this.ctx.lineTo(x - range_x, y - range_close);// 左下this.ctx.moveTo(x - range_close, y + range_y);this.ctx.lineTo(x - range_close, y + range_close);this.ctx.lineTo(x - range_x, y + range_close);}if (x != 9) {// 右上this.ctx.moveTo(x + range_close, y - range_y);this.ctx.lineTo(x + range_close, y - range_close);this.ctx.lineTo(x + range_x, y - range_close);// 右下this.ctx.moveTo(x + range_close, y + range_y);this.ctx.lineTo(x + range_close, y + range_close);this.ctx.lineTo(x + range_x, y + range_close);}this.ctx.stroke();this.ctx.closePath();}// 画#/*obj.drawsharpS = function(){this.drawsharp(2,3);this.drawsharp(8,3);this.drawsharp(1,4);this.drawsharp(3,4);this.drawsharp(5,4);this.drawsharp(7,4);this.drawsharp(9,4);this.drawsharp(2,8);this.drawsharp(8,8);this.drawsharp(1,7);this.drawsharp(3,7);this.drawsharp(5,7);this.drawsharp(7,7);this.drawsharp(9,7);}*///用循环函数的并和画#obj.drawsharpS = function () {this.drawsharp(2, 3);this.drawsharp(8, 3);for (var i = 1; i <= 5; i++) {this.drawsharp(2 * i - 1, 4)}for (var i = 1; i <= 5; i++) {this.drawsharp(2 * i - 1, 7)}this.drawsharp(2, 8);this.drawsharp(8, 8);}/*--------------------------------------------------------------------------------------------------------------------------------------*/// 画楚河/漢界obj.drawText = function () {var font = "" + this.chunk / 1.5 + "px ";this.ctx.font = "bold " + font + " KaiTi_GB2312";this.ctx.fillStyle = "#000";this.ctx.fillText("楚 河", this.chunk * 2, this.chunk * 5 + this.chunk / 1.3);this.ctx.fillText("漢 界", this.chunk * 6 + this.chunk / 3, this.chunk * 5 + this.chunk / 1.3);var font1 = "" + this.chunk / 6 + "px"this.ctx.font = "" + font1 + " Courier New";this.text_arr = ["九", "八", "七", "六", "五", "四", "三", "二", "一"];for (var i = 0; i < 9; i++) {this.ctx.fillText((i + 1).toString(), this.chunk * (i + 1) - 5, 20);this.ctx.fillText(this.text_arr[i], this.chunk * (i + 1) - 5, this.chunk * 11 - this.chunk / 6);}}/*---------------------------------------------------------------------------------------------------------------------------------*/// 画候选形状obj.drawCandidateCircle = function (x, y) {this.ctx.beginPath();this.ctx.fillStyle = this.drawCandidateCircle_fillStyle; //候选内圆的颜色this.ctx.strokeStyle = this.drawCandidateCircle_strokeStyle; //候选内圆的边框颜色this.ctx.lineWidth = this.drawCandidateCircle_lineWidth; //候选内圆的边框大小this.ctx.arc(x * this.chunk, y * this.chunk, this.CandidateCircleR, 0, Math.PI * 2, true);this.ctx.closePath();this.ctx.fill();this.ctx.stroke();}// 画选中棋子状态obj.drawChecked = function (p) {//画候选的形状var temp_x = p.x * this.chunk;var temp_y = p.y * this.chunk;this.ctx.beginPath();this.ctx.strokeStyle = "#00f";this.ctx.lineWidth = 1;this.ctx.moveTo(temp_x - this.radius, temp_y - this.radius + 10); //this.radius棋子大小this.ctx.lineTo(temp_x - this.radius, temp_y - this.radius);this.ctx.lineTo(temp_x - this.radius + 10, temp_y - this.radius);this.ctx.moveTo(temp_x - this.radius, temp_y + this.radius - 10);this.ctx.lineTo(temp_x - this.radius, temp_y + this.radius);this.ctx.lineTo(temp_x - this.radius + 10, temp_y + this.radius);this.ctx.moveTo(temp_x + this.radius, temp_y - this.radius + 10);this.ctx.lineTo(temp_x + this.radius, temp_y - this.radius);this.ctx.lineTo(temp_x + this.radius - 10, temp_y - this.radius);this.ctx.moveTo(temp_x + this.radius, temp_y + this.radius - 10);this.ctx.lineTo(temp_x + this.radius, temp_y + this.radius);this.ctx.lineTo(temp_x + this.radius - 10, temp_y + this.radius);this.ctx.stroke();this.ctx.closePath();}// 画候选位置obj.drawCandidate = function () {switch (this.action.text) {case "車":var temp_y = this.action.y;while (!this.inArray(this.action.x, ++temp_y) && temp_y <= 10) {this.drawCandidateCircle(this.action.x, temp_y);}var temp_y = this.action.y;while (!this.inArray(this.action.x, --temp_y) && temp_y > 0) {this.drawCandidateCircle(this.action.x, temp_y);}var temp_x = this.action.x;while (!this.inArray(++temp_x, this.action.y) && temp_x < 10) {this.drawCandidateCircle(temp_x, this.action.y);}var temp_x = this.action.x;while (!this.inArray(--temp_x, this.action.y) && temp_x > 0) {this.drawCandidateCircle(temp_x, this.action.y);}break;case "馬":if (!this.inArray(this.action.x - 2, this.action.y - 1)&& this.action.x - 2 >= 1 && this.action.y - 1 >= 1&& !this.inArray(this.action.x - 1, this.action.y)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 1);}if (!this.inArray(this.action.x - 1, this.action.y - 2)&& this.action.x - 1 >= 1 && this.action.y - 2 >= 1&& !this.inArray(this.action.x, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 1, this.action.y - 2);}if (!this.inArray(this.action.x + 1, this.action.y - 2)&& this.action.x + 1 <= 9 && this.action.y - 2 >= 1&& !this.inArray(this.action.x, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 1, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y - 1)&& this.action.x + 2 <= 9 && this.action.y - 1 >= 1&& !this.inArray(this.action.x + 1, this.action.y)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 1);}if (!this.inArray(this.action.x + 2, this.action.y + 1)&& this.action.x + 2 <= 9 && this.action.y + 1 <= 10&& !this.inArray(this.action.x + 1, this.action.y)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 1);}if (!this.inArray(this.action.x + 1, this.action.y + 2)&& this.action.x + 1 <= 9 && this.action.y + 2 <= 10&& !this.inArray(this.action.x, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 1, this.action.y + 2);}if (!this.inArray(this.action.x - 1, this.action.y + 2)&& this.action.x - 1 >= 1 && this.action.y + 2 <= 10&& !this.inArray(this.action.x, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 1, this.action.y + 2);}if (!this.inArray(this.action.x - 2, this.action.y + 1)&& this.action.x - 2 >= 1 && this.action.y + 1 <= 10&& !this.inArray(this.action.x - 1, this.action.y)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 1);}break;case "相":if (this.action.y == 10) {if (!this.inArray(this.action.x - 2, this.action.y - 2)&& !this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y - 2)&& !this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 2);}} else if (this.action.y == 6) {if (!this.inArray(this.action.x - 2, this.action.y + 2)&& !this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 2);}if (!this.inArray(this.action.x + 2, this.action.y + 2)&& !this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 2);}} else if (this.action.x == 1) {if (!this.inArray(this.action.x + 2, this.action.y - 2)&& !this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y + 2)&& !this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 2);}} else if (this.action.x == 9) {if (!this.inArray(this.action.x - 2, this.action.y - 2)&& !this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 2);}if (!this.inArray(this.action.x - 2, this.action.y + 2)&& !this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 2);}} else {if (!this.inArray(this.action.x + 2, this.action.y - 2)&& !this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y + 2)&& !this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 2);}if (!this.inArray(this.action.x - 2, this.action.y - 2)&& !this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 2);}if (!this.inArray(this.action.x - 2, this.action.y + 2)&& !this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 2);}}break;case "象":if (this.action.y == 1) {if (!this.inArray(this.action.x - 2, this.action.y + 2)&& !this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 2);}if (!this.inArray(this.action.x + 2, this.action.y + 2)&& !this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 2);}} else if (this.action.y == 5) {if (!this.inArray(this.action.x - 2, this.action.y - 2)&& !this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y - 2)&& !this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 2);}} else if (this.action.x == 1) {if (!this.inArray(this.action.x + 2, this.action.y - 2)&& !this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y + 2)&& !this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 2);}} else if (this.action.x == 9) {if (!this.inArray(this.action.x - 2, this.action.y - 2)&& !this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 2);}if (!this.inArray(this.action.x - 2, this.action.y + 2)&& !this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 2);}} else {if (!this.inArray(this.action.x + 2, this.action.y - 2)&& !this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y - 2);}if (!this.inArray(this.action.x + 2, this.action.y + 2)&& !this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 2, this.action.y + 2);}if (!this.inArray(this.action.x - 2, this.action.y - 2)&& !this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y - 2);}if (!this.inArray(this.action.x - 2, this.action.y + 2)&& !this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 2, this.action.y + 2);}}break;case "仕":if (this.action.x == 5 && this.action.y == 9) {if (!this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 1, this.action.y - 1);}if (!this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 1, this.action.y + 1);}if (!this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 1, this.action.y - 1);}if (!this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 1, this.action.y + 1);}} else {this.drawCandidateCircle(5, 9);}break;case "士":if (this.action.x == 5 && this.action.y == 2) {if (!this.inArray(this.action.x - 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x - 1, this.action.y - 1);}if (!this.inArray(this.action.x - 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x - 1, this.action.y + 1);}if (!this.inArray(this.action.x + 1, this.action.y - 1)) {this.drawCandidateCircle(this.action.x + 1, this.action.y - 1);}if (!this.inArray(this.action.x + 1, this.action.y + 1)) {this.drawCandidateCircle(this.action.x + 1, this.action.y + 1);}} else {this.drawCandidateCircle(5, 2);}break;case "帅":if (!this.inArray(this.action.x, this.action.y - 1) && this.action.y > 8) {this.drawCandidateCircle(this.action.x, this.action.y - 1);}if (!this.inArray(this.action.x, this.action.y + 1) && this.action.y < 10) {this.drawCandidateCircle(this.action.x, this.action.y + 1);}if (!this.inArray(this.action.x - 1, this.action.y) && this.action.x > 4) {this.drawCandidateCircle(this.action.x - 1, this.action.y);}if (!this.inArray(this.action.x + 1, this.action.y) && this.action.x < 6) {this.drawCandidateCircle(this.action.x + 1, this.action.y);}break;case "将":if (!this.inArray(this.action.x, this.action.y - 1) && this.action.y > 1) {this.drawCandidateCircle(this.action.x, this.action.y - 1);}if (!this.inArray(this.action.x, this.action.y + 1) && this.action.y < 3) {this.drawCandidateCircle(this.action.x, this.action.y + 1);}if (!this.inArray(this.action.x - 1, this.action.y) && this.action.x > 4) {this.drawCandidateCircle(this.action.x - 1, this.action.y);}if (!this.inArray(this.action.x + 1, this.action.y) && this.action.x < 6) {this.drawCandidateCircle(this.action.x + 1, this.action.y);}break;case "兵":if (this.action.y > 5 && !this.inArray(this.action.x, this.action.y - 1)) {this.drawCandidateCircle(this.action.x, this.action.y - 1);} else if (this.action.y <= 5) {if (!this.inArray(this.action.x, this.action.y - 1) && this.action.y > 1) {this.drawCandidateCircle(this.action.x, this.action.y - 1);}if (!this.inArray(this.action.x - 1, this.action.y) && this.action.x > 1) {this.drawCandidateCircle(this.action.x - 1, this.action.y);}if (!this.inArray(this.action.x + 1, this.action.y) && this.action.x < 9) {this.drawCandidateCircle(this.action.x + 1, this.action.y);}}break;case "卒":if (this.action.y <= 5 && !this.inArray(this.action.x, this.action.y + 1)) {this.drawCandidateCircle(this.action.x, this.action.y + 1);} else if (this.action.y > 5) {if (!this.inArray(this.action.x, this.action.y + 1) && this.action.y < 10) {this.drawCandidateCircle(this.action.x, this.action.y + 1);}if (!this.inArray(this.action.x - 1, this.action.y) && this.action.x > 1) {this.drawCandidateCircle(this.action.x - 1, this.action.y);}if (!this.inArray(this.action.x + 1, this.action.y) && this.action.x < 9) {this.drawCandidateCircle(this.action.x + 1, this.action.y);}}break;case "炮":var temp_y = this.action.y;while (!this.inArray(this.action.x, ++temp_y) && temp_y <= 10) {this.drawCandidateCircle(this.action.x, temp_y);}var temp_y = this.action.y;while (!this.inArray(this.action.x, --temp_y) && temp_y > 0) {this.drawCandidateCircle(this.action.x, temp_y);}var temp_x = this.action.x;while (!this.inArray(++temp_x, this.action.y) && temp_x < 10) {this.drawCandidateCircle(temp_x, this.action.y);}var temp_x = this.action.x;while (!this.inArray(--temp_x, this.action.y) && temp_x > 0) {this.drawCandidateCircle(temp_x, this.action.y);}break;}}/*---------------------------------------------------------------------------------------------------------------------------------*/// 更新棋局obj.updateChess = function (e) {var lqf =this.ctx.clearRect(0, 0, canvas.width, canvas.height);this.init_back();var that = this;$.each(this.cheer_arr_ALL, function (i, e) {that.drawPiece(e);that.drawChessText(e);});$("#ul").empty(); //清空$.each(this.Notations, function (iii, lqfs) {var cars = ["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"]for (var i = 1; i < 2; i++) {var html_2 = '<li data-id="' + cars[i] + '" class="lqf' + i * 6 + '" style="color: red" >' + lqfs + '</li>';var html_1 = '<li data-id="' + cars[3] + '" class="lqf' + i * 7 + '" style="color: black">' + lqfs + '</li>';var tas = true;if (tas) { $("#ul").append(html_1); tas = false; }else { $("#ul").append(html_2); tas = true; }}});}/*---------------------------------------------------------------------------------------------------------------------------------*/// 增加点击事件obj.addEvent = function () {var that = this;//保存当前对象this.checked = false;//保存选中当前棋子的索引$(canvas).on("mousedown", function (ev) { //鼠标按下for (var j = 1; j <= 10; j++) {for (var i = 1; i <= 9; i++) {//计算当前棋子的位置坐标var temp_i = i * obj.chunk;var temp_j = j * obj.chunk;//计算当前位置和鼠标位置之间的距离var distanct = Math.sqrt(Math.pow(temp_i - ev.offsetX, 2) + Math.pow(temp_j - ev.offsetY, 2));if (distanct <= that.radius) {var overChess = false;$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == i && ee.y == j) {overChess = true;var p = { x: ee.x, y: ee.y };// console.log(that.checked);if (that.currActive != ee.type && !that.checked) {return false;}if (!that.checked) {console.log("选中一个棋子");that.drawChecked(p);that.action = ee;that.drawCandidate();that.checked = true;} else if (that.action.x == ee.x && that.action.y == ee.y) {console.log("点在原棋子上");that.updateChess();that.checked = false;} else if (that.action.type == ee.type) {console.log("切换棋子");that.updateChess();that.drawChecked(p);that.action = ee;that.drawCandidate();} else {// 是否能吃子if (that.Eating_ruless(i, j)) {that.eat(ii, ee, i, j);} else if (that.action.text == "帅") { // 对将if (that.action.x == i) {var canEat = true;$.each(that.cheer_arr_ALL, function (iii, lqfs) {if (lqfs.x == that.action.x && lqfs.y == j) {if (lqfs.text == "将") {for (var t = that.action.y - 1; t > j; t--) {if (that.inArray(that.action.x, t)) {canEat = false;break;}}} else {canEat = false;}return false;}});if (canEat) {that.eat(ii, ee, i, j);}}} else if (that.action.text == "将") {if (that.action.x == i) {var canEat = true;$.each(that.cheer_arr_ALL, function (iii, lqfs) {if (lqfs.x == that.action.x && lqfs.y == j) {if (lqfs.text == "帅") {for (var t = that.action.y + 1; t < j; t++) {if (that.inArray(that.action.x, t)) {canEat = false;break;}}} else {canEat = false;}return false;}});if (canEat) {that.eat(ii, ee, i, j);}}}}return false;}});if (overChess) {console.log("点在棋子上");} else {// 是否能移动if (that.checked && that.Move_rules(i, j)) {console.log("移动棋子");that.move(i, j);}}}}}});}// 记谱obj.book = function (ee, i, j) {var distance = Math.abs(ee.y - j);var Notation;if (ee.type == "red") {$("#currActive").text("轮到黑方").css({ "color": "black", })var oldP = this.text_arr[ee.x - 1];var newP = this.text_arr[i - 1];var num = this.text_arr[9 - distance];if (j < ee.y) {if (ee.x == i) {var tag_1 = '<span style="color: red">进<span>';var tag_2 = '<span style="color: red">' + ee.text + '<span>';console.log(ee.text + oldP + "进" + num);Notation = tag_2 + oldP + tag_1 + num;} else {var tag_1 = '<span style="color: red">进<span>';var tag_2 = '<span style="color: red">' + ee.text + '<span>';console.log(ee.text + oldP + "进" + newP);Notation = tag_2 + oldP + tag_1 + newP;}} else if (j > ee.y) {if (ee.x == i) {var tag_1 = '<span style="color: red">退<span>';var tag_2 = '<span style="color: red">' + ee.text + '<span>';console.log(ee.text + oldP + "退" + num);Notation = tag_2 + oldP + tag_1 + num;} else {var tag_1 = '<span style="color: red">退<span>';var tag_2 = '<span style="color: red">' + ee.text + '<span>';console.log(ee.text + oldP + "退" + newP);Notation = tag_2 + oldP + tag_1 + newP;}} else {var tag_1 = '<span style="color: red">平<span>';var tag_2 = '<span style="color: red">' + ee.text + '<span>';console.log(ee.text + oldP + "平" + newP);Notation = tag_2 + oldP + tag_1 + newP;}} else {$("#currActive").text("轮到红方").css({ "color": "red", })if (j > ee.y) {if (ee.x == i) {console.log(ee.text + ee.x + "进" + distance);Notation = ee.text + ee.x + "进" + distance} else {console.log(ee.text + ee.x + "进" + i);Notation = ee.text + ee.x + "进" + i;}} else if (j < ee.y) {if (ee.x == i) {console.log(ee.text + ee.x + "退" + distance);Notation = ee.text + ee.x + "退" + distance;} else {console.log(ee.text + ee.x + "退" + i);Notation = ee.text + ee.x + "退" + i;}} else {console.log(ee.text + ee.x + "平" + i);Notation = ee.text + ee.x + "平" + i;}}this.Notations.push(Notation);}// 是否结束obj.isOver = function (ee) {if (ee.text == "将") {$("#shuying").html('<p>' + "结束红方赢" + '</p>').css({ "background": "yellow", "color": "red" });$("#ul").empty();return true;} else if (ee.text == "帅") {$("#shuying").html('<p>' + "结束黑方赢" + '</p>').css({ "background": "yellow", "color": "black" });$("#ul").empty();return true;} else {return false;}}/*--------------------------------------------------------------------------------------------------------------------------------------*/// 移动obj.move = function (i, j) {var that = this;$.each(that.cheer_arr_ALL, function (iii, lqfs) {if (lqfs.x == that.action.x && lqfs.y == that.action.y) {that.book(lqfs, i, j);lqfs.x = i;lqfs.y = j;that.currActive = lqfs.type == "red" ? "black" : "red";return false;}});that.updateChess();that.checked = false;}// 吃子obj.eat = function (ii, ee, i, j) {this.cheer_arr_ALL.splice(ii, 1);this.move(i, j);if (this.isOver(ee)) {this.ctx.clearRect(0, 0, canvas.width, canvas.height);this.init();return false;};}/*---------------------------------------------------------------------------------------------------------------------------------*/// 棋子移动规则obj.Move_rules = function (i, j) {switch (this.action.text) {case "車":return this.rules_Car(i, j);case "馬":return this.rules_Horse(i, j);case "相":return this.rules_Elephant_r(i, j);case "象":return this.rules_Elephant_b(i, j);case "仕":return this.rules_Scholar_r(i, j);case "士":return this.rules_Scholar_b(i, j);case "帅":return this.rules_Boss_r(i, j);case "将":return this.rules_Boss_b(i, j);case "兵":return this.rules_Soldier_r(i, j);case "卒":return this.rules_Soldier_b(i, j);case "炮":if (this.rules_Cannon(i, j) == 0) {return true;}return false;}}/*---------------------------------------------------------------------------------------------------------------------------------*/// 棋子吃子规则obj.Eating_ruless = function (i, j) {switch (this.action.text) {case "車":return this.rules_Car(i, j);case "馬":return this.rules_Horse(i, j);case "相":return this.rules_Elephant_r(i, j);case "象":return this.rules_Elephant_b(i, j);case "仕":return this.rules_Scholar_r(i, j);case "士":return this.rules_Scholar_b(i, j);case "帅":return this.rules_Boss_r(i, j);case "将":return this.rules_Boss_b(i, j);case "兵":return this.rules_Soldier_r(i, j);case "卒":return this.rules_Soldier_b(i, j);case "炮":if (this.rules_Cannon(i, j) == 1) {return true;}return false;}}/*---------------------------------------------------------------------------------------------------------------------------------*///各个棋子的规则// 車的规则obj.rules_Car = function (i, j) {if (this.action.x == i || this.action.y == j) {if (this.action.x == i) {if (this.action.y < j) {console.log("车下");var hasObstacle = false;for (var p = this.action.y + 1; p < j; p++) {if (this.inArray(i, p)) {hasObstacle = true;break;}}if (hasObstacle) {return false;}}if (this.action.y > j) {console.log("车上");var hasObstacle = false;for (var p = this.action.y - 1; p > j; p--) {if (this.inArray(i, p)) {hasObstacle = true;break;}}if (hasObstacle) {return false;}}}if (this.action.y == j) {if (this.action.x < i) {console.log("车右");var hasObstacle = false;for (var p = this.action.x + 1; p < i; p++) {if (this.inArray(p, j)) {hasObstacle = true;break;}}if (hasObstacle) {return false;}}if (this.action.x > i) {console.log("车左");var hasObstacle = false;for (var p = this.action.x - 1; p > i; p--) {if (this.inArray(p, j)) {hasObstacle = true;break;}}if (hasObstacle) {return false;}}}return true;}return false;}// 馬的规则obj.rules_Horse = function (i, j) {var hasObstacle = false;var that = this;if ((Math.abs(this.action.x - i) == 1 && Math.abs(this.action.y - j) == 2)|| (Math.abs(this.action.x - i) == 2 && Math.abs(this.action.y - j) == 1)) {if (this.action.x - i == 2) { // 左$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == that.action.x - 1 && ee.y == that.action.y) {hasObstacle = true;return false;}});if (hasObstacle) {return false;}} else if (i - that.action.x == 2) { // 右$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == that.action.x + 1 && ee.y == that.action.y) {hasObstacle = true;return false;}});if (hasObstacle) {return false;}} else if (that.action.y - j == 2) { // 上$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == that.action.x && ee.y == that.action.y - 1) {hasObstacle = true;return false;}});if (hasObstacle) {return false;}} else if (j - that.action.y == 2) { // 下$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == that.action.x && ee.y == that.action.y + 1) {hasObstacle = true;return false;}});if (hasObstacle) {return false;}}return true;}return false;}// 红相的规则obj.rules_Elephant_r = function (i, j) {var hasObstacle = false;var that = this;if ((Math.abs(that.action.x - i) == 2 && Math.abs(that.action.y - j) == 2) && j >= 6) {var vgaX = (that.action.x + i) / 2;var vgaY = (that.action.y + j) / 2;console.log(vgaX);$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == vgaX && ee.y == vgaY) {hasObstacle = true;return false;}});if (hasObstacle) {return false;}return true;}return false;}// 黑象的规则obj.rules_Elephant_b = function (i, j) {var hasObstacle = false;var that = this;if ((Math.abs(that.action.x - i) == 2 && Math.abs(that.action.y - j) == 2) && j < 6) {var vgaX = (that.action.x + i) / 2;var vgaY = (that.action.y + j) / 2;// console.log(vgaX);$.each(that.cheer_arr_ALL, function (ii, ee) {if (ee.x == vgaX && ee.y == vgaY) {hasObstacle = true;return false;}});if (hasObstacle) {return false;}return true;}return false;}// 红仕的规则obj.rules_Scholar_r = function (i, j) {if (this.action.x == 5 && this.action.y == 9) {if (Math.abs(this.action.x - i) == 1 && Math.abs(this.action.y - j) == 1) {return true;}}else if (i == 5 && j == 9) {return true;}return false;}// 黑仕的规则obj.rules_Scholar_b = function (i, j) {if (this.action.x == 5 && this.action.y == 2) {if (Math.abs(this.action.x - i) == 1 && Math.abs(this.action.y - j) == 1) {return true;}} else if (i == 5 && j == 2) {return true;}return false;}// 帅的规则obj.rules_Boss_r = function (i, j) {if ((Math.abs(this.action.x - i) == 1 && this.action.y == j)|| (this.action.x == i && Math.abs(this.action.y - j) == 1)) {if (i >= 4 && i <= 6 && j >= 8 && j <= 10) {return true;} else {return false;}}return false;}// 将的规则obj.rules_Boss_b = function (i, j) {if ((Math.abs(this.action.x - i) == 1 && this.action.y == j)|| (this.action.x == i && Math.abs(this.action.y - j) == 1)) {if (i >= 4 && i <= 6 && j >= 1 && j <= 3) {return true;} else {return false;}}return false;}// 兵的规则obj.rules_Soldier_r = function (i, j) {if (this.action.y <= 5) {if ((this.action.x == i && this.action.y - 1 == j) || (this.action.x - 1 == i && this.action.y == j) || (this.action.x + 1 == i && this.action.y == j)) {return true;}} else {if (this.action.x == i && this.action.y - 1 == j) {return true;}}return false;}// 卒的规则obj.rules_Soldier_b = function (i, j) {if (this.action.y > 5) {if ((this.action.x == i && this.action.y + 1 == j) || (this.action.x - 1 == i && this.action.y == j) || (this.action.x + 1 == i && this.action.y == j)) {return true;}} else {if (this.action.x == i && this.action.y + 1 == j) {return true;}}return false;}// 炮的规则obj.rules_Cannon = function (i, j) {var that = this;if (this.action.x == i || this.action.y == j) {var t = 0;if (this.action.x == i) {var temp = this.action.y;if (temp < j) {while (++temp != j) {$.each(this.cheer_arr_ALL, function (ii, ee) {if (ee.x == that.action.x && ee.y == temp) {t++;return false;}});}return t;} else {while (--temp != j) {$.each(this.cheer_arr_ALL, function (ii, ee) {if (ee.x == that.action.x && ee.y == temp) {t++;return false;}});}return t;}} else {var temp = this.action.x;if (temp < i) {while (++temp != i) {$.each(this.cheer_arr_ALL, function (ii, ee) {if (ee.x == temp && ee.y == that.action.y) {t++;return false;}});}return t;} else {while (--temp != i) {$.each(this.cheer_arr_ALL, function (ii, ee) {if (ee.x == temp && ee.y == that.action.y) {t++;return false;}});}return t;}}}return 2;}obj.inArray = function (x, y) {var hasObstacle = false;$.each(this.cheer_arr_ALL, function (ii, ee) {if (ee.x == x && ee.y == y) {hasObstacle = true;return false;}});return hasObstacle;}obj.init();</script></html>
