欢迎关注得胜的git仓库

多种模式的五子棋

本次版本包含人机对战(机器先手、机器后手)、人人模式(默认)、提示功能等。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <style>
            *{
                padding: 0;margin: 0;
            }
            html,body{width:100%;height: 100%;}
            div{
                text-align: center;
            }
            div button{
                line-height: 16px;
                font-size: 16px;
                padding: 5px 10px;
                border-radius: 5px;
                background: #e73480;
                color: white;
                border: none;
            }
            .canvas{
                margin: 0 auto;
            }
        </style>
    </head>
    <body>
        <div class="canvas">
            <canvas id="gobang"></canvas>
        </div>
        
        <div>
            <button id="requestSupport">提示</button>
            <button id="offense">先手人机</button>
            <button id="defense">后手人机</button>
            <button id="regret">悔棋</button>
            <button id="giveup">认输</button>
            <button id="restart">再来一局</button>
            <button id="negotiate">求和</button>
        </div>
    </body>
    <script src="man-machine4.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        var gobang = new Gobang("gobang");
        // requestSupport
        document.getElementById("offense").addEventListener("click",()=>{
            if(0 && gobang.canContinue){
                alert("不可以中途开局,你可以先认输~~~");
            }else{
                gobang.machineFirst();
            }
        },false);
        document.getElementById("defense").addEventListener("click",()=>{
            if(0 && gobang.canContinue){
                alert("不可以中途开局,你可以先认输~~~");
            }else{
                gobang.manFirst();
            }
        },false);
        document.getElementById("requestSupport").addEventListener("click",()=>{
            gobang.requestSupport && gobang.requestSupport();
        },false);
        document.getElementById("regret").addEventListener("click",()=>{
            gobang.regret();
        },false);
        document.getElementById("giveup").addEventListener("click",()=>{
            if(confirm("你确定认输吗?")){
                gobang.giveUp();
            }
        },false);
        document.getElementById("restart").addEventListener("click",()=>{
            gobang.reStart();
        },false);
        document.getElementById("negotiate").addEventListener("click",()=>{
            if(confirm("你确定求和吗?")){
                gobang.negotiate();
            }
        },false);
    </script>
</html>
// 五子棋

class Gobang {
	constructor(canvasId, rowCount = 16) {
		this.canvasId = canvasId;
		this.rowCount = rowCount;

		this.resetData();
	}

	// 渲染页面
	renderUi() {
		//清除之前的画布
		this.ctx.clearRect(0, 0, this.width, this.height);

		// 重绘画布
		this.drawChessBoard();
		this.drawPieces();
	}

	// 重置数据,再来一局
	resetData() {
		var body = document.documentElement || document.body;
		var minWidth = Math.min(body.clientWidth,body.clientHeight-50);

		// 属性
		this.pieces = []; // 棋子数组 二位数组[[],[]] 0——空  1——白  2——黑
		this.colCount = this.rowCount; // 列数
		this.cellWidth = minWidth / (this.rowCount); //每个格子的宽
		this.width = this.rowCount * this.cellWidth; // 棋盘的宽
		this.height = this.width; // 棋盘的高
		this.R = this.cellWidth * 0.4; // 棋子半径
		this.hisStatus = []; // 历史记录 history status
		this.active = 2; // 默认黑棋先走
		
		this.manMachine = false; // true-人机模式	false-人人模式
		this.machine = 2; // 机器人执棋 2-黑棋	1-白棋
		
		this.canvas = document.getElementById(this.canvasId); // canvas DOM
		this.ctx = this.canvas.getContext("2d"); // canvas环境
		this.victor = 0; // 胜利方
		this.canContinue = true; // 是否可以继续下棋(产生赢家以后不可以)
		this.myPositions = []; // 我方的推荐位置数组  		格式:{x:5,y:6,weight:8}
		this.enemyPositions = []; // 敌方的推荐位置数组

		this.init();
	}

	// 初始化数据
	init() {
		this.initCanvas();
		this.initPiece();
		this.renderUi();
	}
	
	// 暂时给棋盘中间加一个黑棋
	first(){
		var center = Math.floor((this.rowCount+1)/2);
		this.pieces[center][center] = this.active;
		this.hisStatus[1] = this.deepClone(this.pieces);
		this.exchange();
	}

	// 设置棋盘的宽高
	initCanvas() {
		this.canvas.width = this.width;
		this.canvas.height = this.height;
		
		this.canvas.addEventListener("click",(e)=>{ // 小心this转移
			var offset = this.canvas.getBoundingClientRect();
			var x = Math.round((e.clientX - offset.left) / this.cellWidth);
			var y = Math.round((e.clientY - offset.top) / this.cellWidth);
			// console.log(x,y,"点击位置");
			
			// 走棋
			this.goStep(x,y);
		},false);
	}
	
	// 高亮最近走的棋子
	highLight(x,y,oneSide){
		var anotherSide = oneSide == 1 ? 2 : 1;
		var length = this.R*0.5;
		this.ctx.beginPath();
		this.ctx.moveTo(x * this.cellWidth - length, y * this.cellWidth);
		this.ctx.lineTo(x * this.cellWidth + length, y * this.cellWidth);
		this.ctx.moveTo(x * this.cellWidth, y * this.cellWidth - length);
		this.ctx.lineTo(x * this.cellWidth, y * this.cellWidth + length);
		this.ctx.strokeStyle = this.getColor(anotherSide);
		
		this.ctx.stroke();
	}

	// 初始化棋子
	initPiece() {
		var initPieces = [];
		for(let i = 0; i <= this.rowCount; i++) { // 行
			initPieces.push([]);
			for(let j = 0; j <= this.colCount; j++) { // 列
				if(i==0 || j==0 || i==this.rowCount || j==this.rowCount){
					initPieces[i].push(-1); // 不可以走的位置-1  空0 白1  黑2
				}else{
					initPieces[i].push(0); // 空0 白1  黑2
				}
			}
		}
		this.pieces = this.deepClone(initPieces);
		this.hisStatus[0] = this.deepClone(initPieces);
		//this.first();
	}
	
	// 获取某个棋子的颜色 	0——空  1——白  2——黑
	getColor (num){
		var res = "";
		console.trace();
		// console.log(num);
		switch(num){
			case 0:
				res = "";
				break;
			case 2:
				res = "black";
				break;
			case 1:
				res = "white";
				break;
			case -1:
				res = "yellow";
				break;
			default: 
				res="red"; // 错误了
		}
		return res;
	}

	// 画棋盘
	drawChessBoard() {
		// 背景
		this.ctx.beginPath();
		this.ctx.rect(0, 0, this.width, this.height);
		this.ctx.closePath();
		this.ctx.fillStyle = "#0099CC";
		this.ctx.fill();

		// 画横线
		this.ctx.beginPath();
		for(let i = 0; i < this.rowCount; i++) {
			this.ctx.moveTo(0, this.cellWidth * i);
			this.ctx.lineTo(this.width, this.cellWidth * i);
		}
		this.ctx.strokeStyle = "#333";
		this.ctx.stroke();

		// 画纵线
		this.ctx.beginPath();
		for(let i = 0; i < this.colCount; i++) {
			this.ctx.moveTo( this.cellWidth * i, 0);
			this.ctx.lineTo( this.cellWidth * i, this.height);
		}
		this.ctx.strokeStyle = "#333";
		this.ctx.stroke();
	}

	// 画一个棋子
	drawDot(x, y, r, color) {
		this.ctx.beginPath();
		this.ctx.arc(x, y, r, 0, 2 * Math.PI);
		this.ctx.closePath();

		this.ctx.fillStyle = color;
		this.ctx.fill();
	}

	// 画所有的棋子
	drawPieces(x, y) {
		//console.log(this.pieces)
		for(var i = 0; i < this.pieces.length; i++) { // 边界线不让走棋
			for(let j=0; j < this.pieces[i].length;j++){
//				if(this.pieces[i][j] == 1 || this.pieces[i][j] == 2){
				if(this.pieces[i][j] !== 0){
					var x = i * this.cellWidth;
					var y = j * this.cellWidth;
//					var y = j * this.cellWidth - this.cellWidth/2;
					this.drawDot(x,y,this.R,this.getColor(this.pieces[i][j]));
				}
			}
		}
	}
	
	// 
	drawOnePiece(i,j){
		var x = i * this.cellWidth;
		var y = j * this.cellWidth;
		this.drawDot(x,y,this.R,this.getColor(this.active));
	}
	
	// 判断是否可以走这一步
	canGo(x, y) {
		if(this.canContinue === false){
			alert("游戏已结束");
			return false;
		}
		if(x==0 || y==0 || x==this.rowCount || y==this.rowCount){
			alert("边界上不可以走棋哦");
			return false;
		}
		if(this.pieces[x][y]==0){
			return true;
		}else {
			return false;
		}
	}
	
	// 切换角色(换着走棋)
	exchange(){
		this.active = this.active == 1 ? 2 : 1;
	}

	manGoStep(x, y){
		if(this.canGo(x,y)){
			this.pieces[x][y] = this.active;//添加棋子
			this.renderUi();
			this.highLight(x,y,this.active);
			this.hisStatus.push(this.deepClone(this.pieces));//历史记录(悔棋复盘功能使用)
			this.getVictor();//这里有个坑,棋子还没有画上去,已经把输赢判断了????
			this.exchange();
			if(this.manMachine == true){
				this.requestSupport();
			}
		}else{
			// alert("这个位置已经被占领了,换个位置走吧");
		}
	}

	// 走一步棋
	goStep(x,y) {
		// 判断这一步是否可以走
		if(this.manMachine == true){
			// 人机模式
			if(this.machine == this.active){ // 轮到机器人走
				this.requestSupport();
			}else{ // 轮到人走
				this.manGoStep(x, y);
			}
		}else{
			// 人人模式
			this.manGoStep(x, y);
		}	
	}
	
	// 任何时候点击提示后,给出一个推荐位置
	requestSupport(){ // 请求支援
		this.helpRecommend(this.active);
		// console.log(this.myPositions,this.enemyPositions)
		var p = this.bestPosition();
		console.log(p);
		if(Object.keys(p).length != 0){
			
		}else{ // 第一次没有棋子,推荐的位置为空,默认推荐到中间
			var x = parseInt(this.rowCount / 2);
			var y = parseInt(this.rowCount / 2);
			if(this.canGo(x, y)){
				p.x = x;
				p.y = y;
			}else{
				alert("没有有效位置了,自己随便走吧");
			}
		}
		this.pieces[p.x][p.y] = this.active;
		this.renderUi();
		this.highLight(p.x,p.y,this.active);
		this.getVictor();
		this.exchange();
	}
	
	// 悔棋
	regret() {
		if(this.hisStatus.length<=1){
			console.log("当前不可以悔棋了");
			return;
		}
		this.canContinue = true;
		this.victor = 0;
		
		this.hisStatus.pop();
		this.hisStatus.pop();
		this.pieces = this.deepClone(this.hisStatus[this.hisStatus.length-1]);
		// this.exchange();
		this.renderUi();
	}
	
	// 重新开始
	reStart(){
		if(!this.victor){
			alert("还没有结束,不能重新开始");
		}else{
			this.resetData();
		}
	}
	
	// 求和
	negotiate(){
		alert("和棋");
		this.resetData();
	}
	
	// 认输
	giveUp(){
		this.victor = this.active == 1 ? 2 : 1;
		this.getWinner();
		setTimeout(()=>{
			this.resetData();
		},60);
	}
	
	// 机器人先走
	machineFirst(){
		this.resetData();
		this.manMachine = true;
		this.machine = 2;
		this.requestSupport();
	}
	
	// 机器人后走
	manFirst(){
		this.resetData();
		this.manMachine = true;
		this.machine = 1;
	}
	
	// 棋型判断 活三 死三等	  都有对称情况
	defineType (x,y){
		// 类型  权重 棋型
		// 活四  8 ?AAAA? 
		// 死四  7 BAAAA?——?AAAAB  AA?AA
		// 活三  6 ??AAA?——?AAA??  ?A?AA?——?AA?A?
		// 死三  5 BAAA??——??AAAB  BAA?A?——?A?AAB  BA?AA?——?AA?AB
		// 活二  4 ?AA???——???AA?  
		// 死二  3 BAA???  AA????
		// 活一  2 
		// 死一  1
	}
	
	
	helpRecommend(oneSide){
		var enemySide = oneSide == 1 ? 2 : 1;
		this.myPositions = [];
		this.enemyPositions = [];
		var aimArr,standpoint;
		
		for(let i=1;i<this.rowCount;i++){
			
			for(let j=1;j<this.rowCount;j++){
				
//				 var arr = ["r","rd","d","ld","l","lt","t","rt"];
				var arr = ["r","rd","d","ld"];
				// 权重相关变量 forward  backward   center  double  null
				
				var n2f1 = 0.2, // 两头空时 前面第一个空位置的权重
					n2f2 = 0.2, // 两头空时 前面第二个空位置的权重
					n2b1 = n2f1,
					n2b2 = n2f2,
					n1f1 = -0.8, // 一头空另一头是敌方或边界时  前面第一个空位置的权重
					n1f2 = -0.8,
					n1b1 = n1f1,
					n1b2 = n1f2,
					dn2c = 0.2, // 有两个片段时   两端都是空的时   中间位置的权重
					dn2b1 = 0.2,// 有两个片段时   两端都是空的时   后方第一个位置的权重
					dn2f1 = dn2b1,
					dn1c = -0.5,
					dn1b1 = -0.5,
					dn1f1 = dn1b1;
					
				
				if(this.pieces[i][j]==oneSide){ // 我方
					aimArr = this.myPositions;
					standpoint = oneSide;
				}else if(this.pieces[i][j]==enemySide){ // 敌方
					aimArr = this.enemyPositions;
					standpoint = enemySide;
				}else{
					continue;
				}
				
				console.table([{i:i,j:j,qizi:this.pieces[i][j],standpoint:standpoint}])
				
				
				
				for(var d =0;d<arr.length;d++){
					var count = 0;
					count = this.directionCount(arr[d],standpoint,i,j);
					var nd = this.nd(arr[d]);
					var h = nd.h;
					var v = nd.v;
					
					// 赢棋的单独写
					if(count == 4){
						if(this.pieces[i-1*h] && this.pieces[i-1*h][j-1*v] === 0){ // 前1空
							this.sumWeight(aimArr,i-1*h,j-1*v,10**5);
						}else{
							if(this.pieces[i+count*h] && this.pieces[i+count*h][j+count*v] === 0){ // 末1空
								this.sumWeight(aimArr,i+count*h,j+count*v,10**5);
							}
						}
						continue;
					}else{
						
					}
					
					// 某个方向的末端的推荐权重  (权重暂时认为后方第一个位置和第二位位置一样) 两头空的+0.2  一端空的+0  两端都死的考虑能否凑5个子
					if(this.pieces[i-1*h] && this.pieces[i-1*h][j-1*v] === 0){ // 前1空
						if(this.pieces[i+count*h] && this.pieces[i+count*h][j+count*v] === 0){ // 末1空
							if(this.pieces[i+(count+1)*h] && this.pieces[i+(count+1)*h][j+(count+1)*v] === 0){ //末2空
								if(count>=3){
									this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+n2b1+0.3));
									this.sumWeight(aimArr,i+(count+1)*h,j+(count+1)*v,10**(count+n2b2));
								}else{
									this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+n2b1));
									this.sumWeight(aimArr,i+(count+1)*h,j+(count+1)*v,10**(count+n2b2));
								}
							}else if(this.pieces[i+(count+1)*h] && this.pieces[i+(count+1)*h][j+(count+1)*v] === standpoint){ // 末2己
								let count2 = this.directionCount(arr[d],standpoint,i+(count+1)*h,j+(count+1)*v);
								if(count+count2 >= 4){ // 可以赢的特殊算
									this.sumWeight(aimArr,i+count*h,j+count*v,10**5);
								}else{
									if(this.pieces[i+(count+1+count2)*h] && this.pieces[i+(count+1+count2)*h][j+(count+1+count2)*v] === 0){
										this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+count2+dn2c));
										this.sumWeight(aimArr,i+(count+1+count2)*h,j+(count+1+count2)*v,10**(count+count2+dn2b1));
									}else {
										this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+count2+dn1c));
									}
								}
									
							}else { //末2敌或边界  
								this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+n1b1));
							}
						}else { // 末1敌或边界   末1不可能是己方的
							// 末端没有推荐的位置
						}
					}else if(this.pieces[i-1*h] && this.pieces[i-1*h][j-1*v] === standpoint){ // 前1己  这里已经计算过了,跳过逻辑
						continue;
					}else { // 前1 敌方或边界
						if(this.pieces[i+count*h] && this.pieces[i+count*h][j+count*v] === 0){ // 末1空
							if(this.pieces[i+(count+1)*h] && this.pieces[i+(count+1)*h][j+(count+1)*v] === 0){ //末2空
								this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+n1b1));
								this.sumWeight(aimArr,i+(count+1)*h,j+(count+1)*v,10**(count+n1b2));
							}else if(this.pieces[i+(count+1)*h] && this.pieces[i+(count+1)*h][j+(count+1)*v] === standpoint){ // 末2己
//									this.sumWeight(this.myPositions,i+count*h,j+count*v,10**(count+0.1));
								let count2 = this.directionCount(arr[d],standpoint,i+(count+1)*h,j+(count+1)*v);
								if(count+count2 >= 4){
									this.sumWeight(aimArr,i+count*h,j+count*v,10**5);
								}else{
									if(this.pieces[i+(count+1+count2)*h] && this.pieces[i+(count+1+count2)*h][j+(count+1+count2)*v] === 0){
										this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+count2+dn1c));
										this.sumWeight(aimArr,i+(count+1+count2)*h,j+(count+1+count2)*v,10**(count+count2+dn1b1));
									}else {// 两端是死的 中间要么是5要么就没意义
										if(count+1+count2 == 5){
											this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+count2+1));
										}else{
											this.sumWeight(aimArr,i+count*h,j+count*v,0);
											//console.log("中间凑不够5个,中间权重是0");
										}
									}
								}
									
							}else { //末2敌或边界
								if(count==4){ // 只有四颗子的时候这个位置才有意义
									this.sumWeight(aimArr,i+count*h,j+count*v,10**(count+1));
								}
							}
						}else { // 末1敌或边界   末1不可能是己方的
							// 走不了了
						}
					}
					
					// 某个方向的前端的推荐权重
					if(this.pieces[i+count*h] && this.pieces[i+count*h][j+count*v] === 0){ // 后1空
						if(this.pieces[i-1*h] && this.pieces[i-1*h][j-1*v] === 0){ // 前1空
							if(this.pieces[i-2*h] && this.pieces[i-2*h][j-2*v] === 0){ //前2空
								if(count>=3){
									this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+n2f1+0.3));
									this.sumWeight(aimArr,i-2*h,j-2*v,10**(count+n2f2));
								}else{
									this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+n2f1));
									this.sumWeight(aimArr,i-2*h,j-2*v,10**(count+n2f2));
								}
							}else if(this.pieces[i-2*h] && this.pieces[i-2*h][j-2*v] === standpoint){ // 前2己
//									this.sumWeight(this.myPositions,i-1*h,j-1*v,10**(count+0.3));
								let count2 = this.directionCount(this.reverseDirection(arr[d]),standpoint,i-2*h,j-2*v);
								if(count+count2 >= 4){
									this.sumWeight(aimArr,i-1*h,j-1*v,10**5);
								}else{
									if(this.pieces[i-(1+count2)*h] && this.pieces[i-(1+count2)*h][j-(1+count2)*v] === 0){
										this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+count2+dn2c));
										this.sumWeight(aimArr,i-(1+count2)*h,j-(1+count2)*v,10**(count+count2+dn2f1));
									}else {
										this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+count2+dn1c));
										this.sumWeight(aimArr,i-(1+count2)*h,j-(1+count2)*v,10**(count+count2+dn1f1));
									}
								}
									
							}else { //前2敌或边界
								this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+n1f1));
							}
						}else { // 前1敌或边界   前1不可能是己方的
							// 前端没有推荐的位置
						}
					}else if(this.pieces[i+count*h] && this.pieces[i+count*h][j+count*v] === standpoint){ // 后1己  这里已经计算过了,跳过逻辑
						continue;
					}else { // 后1 敌方或边界
						if(this.pieces[i-1*h] && this.pieces[i-1*h][j-1*v] === 0){ // 前1空
							if(this.pieces[i-2*h] && this.pieces[i-2*h][j-2*v] === 0){ //前2空
								this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+n1f1));
								this.sumWeight(aimArr,i-2*h,j-2*v,10**(count+n1f2));
							}else if(this.pieces[i-2*h] && this.pieces[i-2*h][j-2*v] === standpoint){ // 前2己
								// this.sumWeight(this.myPositions,i-1*h,j-1*v,10**(count+0.1));
								let count2 = this.directionCount(this.reverseDirection(arr[d]),standpoint,i-2*h,j-2*v);
								if(count+count2 >= 4){
									this.sumWeight(aimArr,i-1*h,j-1*v,10**5);
								}else{
									if(this.pieces[i-(1+count2)*h] && this.pieces[i-(1+count2)*h][j-(1+count2)*v] === 0){
										this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+count2+dn1c));
										this.sumWeight(aimArr,i-(1+count2)*h,j-(1+count2)*v,10**(count+count2+dn1f1));
									}else {
										if(count+1+count2 == 5){
											this.sumWeight(aimArr,i-1*h,j-1*v,10**(count+count2+1));
										}else{
											this.sumWeight(aimArr,i-1*h,j-1*v,0);
											//console.log("中间凑不够5个,中间权重是0");
										}
									}
								}
							}else { //前2敌或边界
								if(count==4){ // 只有四颗子的时候这个位置才有意义
									this.sumWeight(aimArr,i-2*h,j-2*v,10**(count+1));
								}
							}
						}else { // 前1敌或边界  前1不可能是己方的
							// 前后都是敌,推荐个锤子
						}
					}
				}
				
			}
		}
	}
	
	
	reverseDirection(direction){
		var rd = "";
		switch(direction){
			case "r":
				rd = "l";break;
			case "rd":
				rd = "lt";break;
			case "d":
				rd = "t";break;
			case "ld":
				rd = "rt";break;
			case "l":
				rd = "r";break;
			case "lt":
				rd = "rd";break;
			case "t":
				rd = "d";break;
			case "rt":
				rd = "ld";break;
			default: console.error("输入方向不对,无法反转"); 	
		}
		return rd;
	}
	
	// 方向数字化numberDirection r(1,0) rd(1,1) ld(-1,1)
	nd(direction){
		var res = {h:0,v:0}; // h horizontal v vertical
		switch(direction){
			case "r":
				res.h = 1;
				res.v = 0;
				break;
			case "rd":
				res.h = 1;
				res.v = 1;
				break;
			case "d":
				res.h = 0;
				res.v = 1;
				break;
			case "ld":
				res.h = -1;
				res.v = 1;
				break;
			case "l":
				res.h = -1;
				res.v = 0;
				break;
			case "lt":
				res.h = -1;
				res.v = -1;
				break;
			case "t":
				res.h = 0;
				res.v = -1;
				break;
			case "rt":
				res.h = 1;
				res.v = -1;
				break;
			default: console.error("方向输入有误");
		}
		return res;
	}
	
	// 合并同一个位置的权重
	sumWeight(arr,x,y,weight){
		weight = parseInt(weight); // 这里取一下整,小数看着不爽
		var index = -1;
		for(let i=0,len=arr.length;i<len;i++){
			if(arr[i].x==x && arr[i].y==y){
				index = i;
				break;
			}
		}
		if(index!=-1){ // 如果已存在则权重相加
			arr[index].weight += weight;
		}else{ // 如果不存在则添加一条
			arr.push({x,y,weight});
		}
	}
	
	// 从推荐位置中找出最佳位置  权重最大的位置
	bestPosition (){
		var myMax=0,myP={},myArr=[];
		for(let i=0,len=this.myPositions.length;i<len;i++){
			if(this.myPositions[i].weight>myMax){
				myMax = this.myPositions[i].weight;
				myP.x = this.myPositions[i].x;
				myP.y = this.myPositions[i].y;
			}
		}
		var enemyMax = 0, enemyP = {}, enemyArr = [];
		for(let i=0,len=this.enemyPositions.length;i<len;i++){
			if(this.enemyPositions[i].weight>enemyMax){
				enemyMax = this.enemyPositions[i].weight;
				enemyP.x = this.enemyPositions[i].x;
				enemyP.y = this.enemyPositions[i].y;
			}
		}
//		console.log(this.myPositions,this.ememyPositions);
		//console.log("敌方权重最大:"+enemyMax,"我方权重最大:"+myMax);
		
		for(let i=0,len=this.myPositions.length;i<len;i++){
			if(this.myPositions[i].weight==myMax){
				myArr.push(this.deepClone(this.myPositions[i]));
			}
		}
		for(let i=0,len=this.enemyPositions.length;i<len;i++){
			if(this.enemyPositions[i].weight==enemyMax){
				enemyArr.push(this.deepClone(this.enemyPositions[i]));
			}
		}
		console.log(myArr,enemyArr,"敌方权重最大:"+enemyMax,"我方权重最大:"+myMax)
		if(enemyMax>myMax){
			// 敌方权重最大的地方(有相同位置时,谋求自己的大权重位置)
			var myMaxW = 0; // 我方在敌方最有位置处的最佳权重
			var recommedP = enemyP;
			for(let i=0, len=enemyArr.length;i<len;i++){
				for(let j=0,len1=this.myPositions.length;j<len1;j++){
					if(this.myPositions[j].x==enemyArr[i].x && this.myPositions[j].y==enemyArr[i].y){
						if(this.myPositions[j].weight>myMaxW){
							myMaxW = this.myPositions[j].weight;
							recommedP.x = this.myPositions[j].x;
							recommedP.y = this.myPositions[j].y;
						}
					}
				}
			}
			return recommedP;
		}else {
			// 我方权重最大的地方(有相同位置时,占据敌方的相对大权重位置)
			var enemyMaxW = 0; // 我方在敌方最有位置处的最佳权重
			var recommedP = myP;
			for(let i=0, len=myArr.length;i<len;i++){
				for(let j=0,len1=this.enemyPositions.length;j<len1;j++){
					if(this.enemyPositions[j].x==myArr[i].x && this.enemyPositions[j].y==myArr[i].y){
						if(this.enemyPositions[j].weight>enemyMaxW){
							enemyMaxW = this.enemyPositions[j].weight;
							recommedP.x = this.enemyPositions[j].x;
							recommedP.y = this.enemyPositions[j].y;
						}
					}
				}
			}
			return recommedP;
		}
	}
	
	// 获取赢家
	getWinner(){
		switch(this.victor){
			case 0:
				// console.log("还没产生赢家");
				break;
			case 1: 
				setTimeout(()=>{
					alert("白棋赢");
					this.canContinue = false;
				},30);
				break;
			case 2:
				setTimeout(()=>{
					alert("黑棋赢");
					this.canContinue = false;
				},30);
				break;
			default:;
		}
	}

	// 判断输赢
	getVictor() { //1.找到一个当前棋子,2.判断它的右、右下、下、左下四个方向是否连成5个棋子
		var dArr = ["r","rd","d","ld"];
		for(var i=1;i<this.pieces.length;i++){
			for(var j=1;j<this.pieces[i].length;j++){
				if(this.pieces[i][j] == this.active){
					for(let k =0;k<dArr.length;k++){
						if(this.directionCount(dArr[k],this.active,i,j) == 5){// 右r 下d 左l 上t 
							this.victor = this.active;
							this.getWinner();
							return;
						}
					}
				}
			}
		}
	}
	
	// 各个方向连珠数量判断
	directionCount(direction,oneSide,i,j){
		var count = 0;
		var nd = this.nd(direction);
		if(this.pieces[i][j] == oneSide){
			count = 1;
			for(let k=1;k<5;k++){
				if(this.pieces[i+k*nd.h] && this.pieces[i+k*nd.h][j+k*nd.v] === oneSide){
					count++;
					continue;
				}else {
					break;
				}
			}
		}
		return count;
	}
	
	
	
	// 深拷贝
	deepClone(values) {
		var copy;

		// Handle the 3 simple types, and null or undefined
		if(null == values || "object" != typeof values) return values;

		// Handle Date
		if(values instanceof Date) {
			copy = new Date();
			copy.setTime(values.getTime());
			return copy;
		}

		// Handle Array
		if(values instanceof Array) {
			copy = [];
			for(var i = 0, len = values.length; i < len; i++) {
				copy[i] = this.deepClone(values[i]);
			}
			return copy;
		}

		// Handle Object
		if(values instanceof Object) {
			copy = {};
			for(var attr in values) {
				if(values.hasOwnProperty(attr)) copy[attr] = this.deepClone(values[attr]);
			}
			return copy;
		}

		throw new Error("Unable to copy values! Its type isn't supported.");
	}
}

  

posted on 2019-01-11 17:21  web得胜  阅读(739)  评论(2编辑  收藏  举报

导航

感谢观看web得胜的博客,如果您觉得对你有帮助,请点赞支持一下哦~。发现问题请留言指正,谢谢!