课程/JavaScript/前端开发
JS实现人机大战之五子棋(AI篇)
-
-
慕移动9910096
2018-01-25
- }
}
}
this.chessBoard[u][v] = 2;
this.type = !this.type;
},
// 落子函数 i--X轴交叉点下标 j--Y轴交叉点下标 type--true为黑子,false为白子 backGauge--棋盘边框线宽度
oneStep: function (i, j, type, backGauge) {
this.context.beginPath();
this.context.arc(backGauge + i * this.residue, backGauge + j * this.residue, Math.floor(this.residue / 2) - 3, 0, 2 * Math.PI);
this.context.closePath();
var gradient = this.context.createRadialGradient(backGauge + i * this.residue + 2, backGauge + j * this.residue - 2, Math.floor(this.residue / 2) - 3, backGauge + i * this.residue + 2, backGauge + j * this.residue - 2, 0);
if (type) {
gradient.addColorStop(0, '#0A0A0A');
gradient.addColorStop(1, '#636766');
} else {
gradient.addColorStop(0, '#D1D1D1');
gradient.addColorStop(1, '#F9F9F9');
}
this.context.fillStyle = gradient;
this.context.fill();
}
};
chess.init();
};
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- for (var x = 0; x <= this.num; x++) {
for (var y = 0; y <= this.num; y++) {
if (this.wins[x][y][k] && this.chessBoard[x][y] === 0) {
if ((x-q)*(x-q) === 1 ||(y-w)*(y-w) === 1 ) {
u = x;
v = y;
}
}
}
}
}
}
}
}
}
}
}
}
}
this.chessList.push([u, v, this.type]);
this.oneStep(u, v, this.type, this.backGauge);
for (var k = 0; k < this.count; k++) {
if (!this.type && this.wins[u][v][k]) {
this.myWin[k] += 999;
if (this.otherWin[k] < 999) {
this.otherWin[k]++;
if (this.otherWin[k] >= 5) {
alert('电脑赢了');
this.over = true;
this.admit = false;
this.admitted.classList.add('admit_btn');
this.admitted.classList.remove('start_btn');
this.back.classList.add('admit_btn');
this.back.classList.remove('start_btn');
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- for (var x = 0; x <= this.num; x++) {
for (var y = 0; y <= this.num; y++) {
if (this.wins[x][y][k] && this.chessBoard[x][y] === 0) {
if ((x-q)*(x-q) === 1 ||(y-w)*(y-w) === 1 ) {
u = x;
v = y;
}
}
}
}
}
}
}
}
}
if (aIScore[i][j][l] === max) {
for (var m = 1; m < 5; m++) {
if (myScore[i][j][m] > maxScore) {
maxScore = myScore[i][j][m];
u = i;
v = j;
} else if (myScore[i][j][m] === maxScore) {
for (var k = 0; k < this.count; k++) {
if (this.otherWin[k] === l) {
for (var x = 0; x <= this.num; x++) {
for (var y = 0; y <= this.num; y++) {
if (this.wins[x][y][k] && this.chessBoard[x][y] === 2) {
q = x;
w = y;
}
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- if (aIScore[i][j][l] > max) {
max = aIScore[i][j][l];
u = i;
v = j;
}
}
}
}
}
}
for (var i = 0; i <= this.num; i++) {
for (var j = 0; j <= this.num; j++) {
if (this.chessBoard[i][j] === 0) {
for (var l = 1; l < 5; l++) {
if (myScore[i][j][l] === max) {
for (var m = 1; m < 5; m++) {
if (aIScore[i][j][m] > maxScore) {
maxScore = aIScore[i][j][m]
u = i;
v = j;
} else if (myScore[i][j][m] === maxScore) {
for (var k = 0; k < this.count; k++) {
if (this.myWin[k] === l) {
for (var x = 0; x <= this.num; x++) {
for (var y = 0; y <= this.num; y++) {
if (this.wins[x][y][k] && this.chessBoard[x][y] === 1) {
q = x;
w = y;
}
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- for (var i = 0; i <= this.num; i++) {
for (var j = 0; j <= this.num; j++) {
if (this.chessBoard[i][j] === 0) {
for (var k = 0; k < this.count; k++) {
if (this.wins[i][j][k]) {
if (this.myWin[k] === 1) {
myScore[i][j][1] += 200;
} else if (this.myWin[k] === 2) {
myScore[i][j][2] += 600;
} else if (this.myWin[k] === 3) {
myScore[i][j][3] += 4000;
} else if (this.myWin[k] === 4) {
myScore[i][j][4] += 20000;
}
if (this.otherWin[k] === 1) {
aIScore[i][j][1] += 220;
} else if (this.otherWin[k] === 2) {
aIScore[i][j][2] += 620;
} else if (this.otherWin[k] === 3) {
aIScore[i][j][3] += 5500;
} else if (this.otherWin[k] === 4) {
aIScore[i][j][4] += 50000;
}
}
for (var l = 1; l < 5; l++) {
if (myScore[i][j][l] > max) {
max = myScore[i][j][l];
u = i;
v = j;
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- if (!that.over) {
console.log(that.type)
that.type = !that.type;
console.log(that.type)
if (that.isAI) {
that.isComput();
}
}
};
},
// 电脑走棋
isComput: function () {
var aIScore = []; // 电脑分数统计 人机对战时使用
var myScore = []; // 玩家1分数统计 人机对战时使用
var max = 0; // 统计最高分数
var maxScore = 0; // 统计最高分数
var u = 0, v = 0, q = 0, w = 0;
for (var i = 0; i <= this.num; i++) {
aIScore[i] = [];
myScore[i] = [];
for (var j = 0; j <= this.num; j++) {
aIScore[i][j] = [];
myScore[i][j] = [];
for (var k = 1; k < 5; k++) {
aIScore[i][j][k] = 0;
myScore[i][j][k] = 0;
}
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- for (var k = 0; k < that.count; k++) {
if (that.type && that.wins[i][j][k]) {
that.otherWin[k] += 999;
if (that.myWin[k] < 999) {
that.myWin[k]++;
if (that.myWin[k] >= 5) {
alert('你赢了!');
that.over = true;
that.admit = false;
that.admitted.classList.add('admit_btn');
that.admitted.classList.remove('start_btn');
that.back.classList.add('admit_btn');
that.back.classList.remove('start_btn');
}
}
} else if (!that.type && that.wins[i][j][k] && !that.isAI) {
that.myWin[k] += 999;
if (that.otherWin[k] < 999) {
that.otherWin[k]++;
if (that.otherWin[k] >= 5) {
alert('你输了!');
that.over = true;
that.admit = false;
that.admitted.classList.add('admit_btn');
that.admitted.classList.remove('start_btn');
that.back.classList.add('admit_btn');
that.back.classList.remove('start_btn');
}
}
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- for (var i = 0; i < this.count; i++) {
this.myWin[i] = 0;
this.otherWin[i] = 0;
}
}
// 判断是否悔棋
if (this.takeBack) {
for (var i = 0; i < this.chessList.length; i++) {
this.oneStep(this.chessList[i][0], this.chessList[i][1], this.chessList[i][2], this.backGauge);
}
}
// 绑定canvas点击事件
this.chessDom.onclick = function (e) {
if (that.over) {
return;
}
var x = e.offsetX;
var y = e.offsetY;
var i = Math.round((x - backGauge) / residue);
var j = Math.round((y - backGauge) / residue);
if (i > that.num || j > that.num || that.chessBoard[i][j] !== 0) {
return;
} else {
that.takeBack = false;
if (that.type) {
that.chessBoard[i][j] = 1;
} else {
that.chessBoard[i][j] = 2;
}
}
that.chessList.push([i, j, that.type]);
that.oneStep(i, j, that.type, backGauge);
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- // 第一种赢法---所有5子竖线
for (var i = 0; i <= this.num; i++) {
for (var j = 0; j <= this.num - 4; j++) {
for (var k = 0; k <= 4; k++) {
this.wins[i][j + k][this.count] = true;
}
this.count++;
}
}
// 第二种赢法---所有5子横线
for (var i = 0; i <= this.num; i++) {
for (var j = 0; j <= this.num - 4; j++) {
for (var k = 0; k <= 4; k++) {
this.wins[j + k][i][this.count] = true;
}
this.count++;
}
}
// 第三种赢法---所有5子斜线
for (var i = 0; i <= this.num - 4; i++) {
for (var j = 0; j <= this.num - 4; j++) {
for (var k = 0; k <= 4; k++) {
this.wins[i + k][j + k][this.count] = true;
}
this.count++;
}
}
// 第四种赢法---所有5子反斜线
for (var i = 0; i <= this.num - 4; i++) {
for (var j = this.num; j >= 4; j--) {
for (var k = 0; k <= 4; k++) {
this.wins[i + k][j - k][this.count] = true;
}
this.count++;
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- // 画棋盘
darwChessboard: function () {
var residue = Math.floor((this.windowWidth - 50) / (this.num + 1));
this.residue = residue;
var that = this;
var backGauge = (this.windowWidth - 50 - residue * this.num) / 2;
this.backGauge = backGauge;
for (var k = 0; k <= this.num; k++) {
this.context.moveTo(backGauge,backGauge + residue * k);
this.context.lineTo(backGauge + residue * this.num,backGauge + residue * k);
this.context.stroke();
this.context.moveTo(backGauge + residue * k,backGauge);
this.context.lineTo(backGauge + residue * k,backGauge + residue * this.num);
this.context.stroke();
};
if (!this.takeBack) {
for (var f = 0; f <= this.num; f++) {
this.chessBoard[f] = [];
this.wins[f] = [];
for (var s = 0; s <= this.num; s++) {
this.chessBoard[f][s] = 0;
this.wins[f][s] = [];
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- if (this.chessList.length > 0) {
deleteItem = this.chessList.pop();
for (var i = 0; i < this.count; i++) {
if (deleteItem[2]) {
if (this.myWin[i] && this.wins[deleteItem[0]][deleteItem[1]][i]) {
if (this.myWin[i] < 999) {
this.myWin[i]--;
}
this.otherWin[i] -= 999;
}
} else {
if (this.otherWin[i] && this.wins[deleteItem[0]][deleteItem[1]][i]) {
if (this.otherWin[i] < 999) {
this.otherWin[i]--;
}
this.myWin[i] -= 999;
}
}
}
this.chessBoard[deleteItem[0]][deleteItem[1]] = 0;
} else {
this.type = !this.type;
}
this.resetFn();
},
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- // 为canvas添加背景图片
var logo = document.getElementById('img');
this.context.drawImage(logo, 0, 0, this.windowWidth - 50, this.windowWidth - 50)
// 画棋盘
this.darwChessboard();
},
// 悔棋
takeBackFn: function () {
if (this.takeBack && this.chessList.length > 0) {
return;
}
this.takeBack = true;
var deleteItem = this.chessList.pop();
this.chessBoard[deleteItem[0]][deleteItem[1]] = 0;
for (var i = 0; i < this.count; i++) {
if (deleteItem[2]) {
if (this.myWin[i] && this.wins[deleteItem[0]][deleteItem[1]][i]) {
if (this.myWin[i] < 999) {
this.myWin[i]--;
}
this.otherWin[i] -= 999;
}
} else {
if (this.otherWin[i] && this.wins[deleteItem[0]][deleteItem[1]][i]) {
if (this.otherWin[i] < 999) {
this.otherWin[i]--;
}
this.myWin[i] -= 999;
}
}
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- // 开始
startFn: function () {
if (this.start) {
return;
}
var isComputAI = document.getElementsByClassName('active')[0].getAttribute('data-type');
if (isComputAI === '1') {
this.isAI = true;
}
this.over = false;
this.start = true;
this.startBtn.classList.add('admit_btn');
this.startBtn.classList.remove('start_btn');
this.admitted.classList.remove('admit_btn');
this.admitted.classList.add('start_btn');
this.back.classList.remove('admit_btn');
this.back.classList.add('start_btn');
this.resetting.classList.add('reset_btn');
this.resetting.classList.remove('admit_btn');
this.admit = true;
this.reset = true;
},
// 重置
resetFn: function () {
// 获取canvas实例并自适应
var chessDom = document.getElementById('chess');
this.chessDom = chessDom;
this.context = chessDom.getContext('2d');
this.context.strokeStyle = '#BFBFBF';
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- // 点击重置按钮
this.resetting.onclick = function () {
if (!that.reset) {
if (that.over && !that.start) {
that.tip = '游戏未开始';
}
alert(that.tip);
return;
}
that.initData();
that.startBtn.classList.remove('admit_btn');
that.startBtn.classList.add('start_btn');
that.admitted.classList.add('admit_btn');
that.admitted.classList.remove('start_btn');
that.back.classList.add('admit_btn');
that.back.classList.remove('start_btn');
that.resetting.classList.remove('reset_btn');
that.resetting.classList.add('admit_btn');
that.resetFn();
}
// 对战模式选择
document.getElementsByClassName('text_ct')[0].onclick = function (e) {
if (that.start) {
return;
}
var index = Number(e.target.getAttribute('data-type'));
if (index === that.index) {
return;
}
var children = this.children;
children[that.index].classList.remove('active');
children[index].classList.add('active');
that.index = index;
}
},
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- // 初始化方法
init: function () {
this.initData();
this.initCanvasData(); // 初始化canvas数据
},
initCanvasData: function () {
var that = this;
this.resetFn();
// 点击开始按钮
this.startBtn.onclick = function () {
that.startFn();
}
// 点击认输按钮
this.admitted.onclick = function () {
if (!that.admit) {
if (that.over && that.start) {
that.tip = '游戏已结束';
} else if (that.over && !that.start) {
that.tip = '游戏未开始';
}
alert(that.tip);
return;
}
if (that.type) {
alert('你输了')
that.over = true;
that.admit = false;
that.admitted.classList.add('admit_btn');
that.admitted.classList.remove('start_btn');
}
}
// 点击悔棋按钮
this.back.onclick = function () {
if (!that.admit) {
if (that.over && that.start) {
that.tip = '游戏已结束';
alert(that.tip);
return;
} else if (that.over && !that.start) {
that.tip = '游戏未开始';
alert(that.tip);
return;
}
}
that.takeBackFn();
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- window.onload = function () {
var chess = {
tip: '', // 提示消息
windowWidth: document.documentElement.clientWidth, // 当前窗口可见宽度
windowHeight: document.documentElement.clientHeight, // 当前窗口可见高度
startBtn: document.getElementById('startBtn'), // 开始按钮
admitted: document.getElementById('admitted'), // 认输按钮
back: document.getElementById('back'), // 悔棋按钮
resetting: document.getElementById('resetting'), // 重置按钮
initData: function () {
this.start = false; // true--游戏开始(点击开始按钮) false--游戏结束
this.reset = false; // 重置 true--重置按钮可点 false--重置按钮不可点
this.over = true; // true--游戏结束 false--游戏开始中
this.admit = false; // true--认输按钮可点 false--认输按钮不可点
this.type = true; // true--黑子 false--白子
this.isAI = false; // true--人机 false--非人机
// 初始化落子二维数组
this.chessBoard = [];
this.wins = []; // 赢法数组
this.count = 0;
// 初始化棋盘变量
this.num = 15;
// 赢法的统计数组
this.myWin = [];
this.otherWin = [];
this.index = 0;
this.takeBack = false;
this.chessList = [];
},
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- body {
background: #495C65;
}
canvas {
display: block;
margin: auto auto;
box-shadow: -3px -3px 3px #EFEFEF, 5px 5px 5px #B9B9B9;
/*background: url('../images/chess.jpg') no-repeat;
background-size: cover;*/
}
.chessTitle {
margin: 10px 0px;
line-height: 40px;
text-align: center;
font-family: '微软雅黑';
font-size: 36px;
}
.chessTitle[data-text]::after {
content: attr(data-text);
color: #FFFFFF;
-webkit-mask-image: -webkit-gradient(linear, 0 0, 0 bottom, from(#FBD1CE), to(rgba(204, 126, 11, 0)));
}
.btn_box {
margin-top: 20px;
}
.btn_box .btn {
margin: 10px auto;
width: 3rem;
height: 2rem;
line-height: 2rem;
text-align: center;
border-radius: 50%;
}
.btn_box .start_btn {
background-color: darkorange;
}
.btn_box .reset_btn {
background-color: aqua;
}
.btn_box .admit_btn {
background-color: gainsboro;
}
.text_ct {
height: 2rem;
line-height: 2rem;
text-align: center;
color: #FFFFFF;
}
.active {
background: #F99707;
}
-
1赞 · 1采集
-
-
慕移动9910096
2018-01-25
- <!DOCTYPE HTML>
<html>
<head>
<title>五子棋</title>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
<link rel="stylesheet" href="./css/chess.css"/>
</head>
<body>
<div id="chessTitle" class="chessTitle" data-text="五子棋"></div>
<canvas id="chess"></canvas>
<div class="btn_box">
<div class="text_ct">
<span class="active" data-type="0">双人对战</span>
<span data-type="1">人机对战</span>
</div>
</div>
<div class="btn_box">
<div id="startBtn" class="btn start_btn">开始</div>
<div id="admitted" class="btn admit_btn">认输</div>
<div id="back" class="btn admit_btn">悔棋</div>
<div id="resetting" class="btn admit_btn">重置</div>
</div>
<img id="img" src="images/chess.jpg" style="display: none;"></img>
<script src="./js/chess.js" type="text/javascript"></script>
</body>
</html>
-
2赞 · 1采集
-
-
quwei
2016-04-13
- 更新赢法数组
-
截图
0赞 · 1采集
-
-
quwei
2016-04-13
- 分数最高的点
-
截图
0赞 · 0采集