要想实现人机对战,就必须让电脑自动下棋,而且要知道自动去查找对方的棋子,看看有没有可以挑一对的,有没有可以夹一个的,这样下起来才有意思。

当电脑用户下完棋后,电脑应立即搜索用户的棋子,然后如果没有被吃的,就再随机走一个棋子(要想让电脑成为下棋高手就不能随机下棋,要考虑下棋后会不会再被对方吃掉等等,这里只简单做随机下子了)。

完整《五子飞》游戏人机对战:http://www.lyout.com/projects/fiveflychess/FiveflyChess8.htm

// 查找是否有可挑的棋子
for (i = 0; i < this.lines.length; i++) {
for (j = 0; j < this.lines[i].length; j++) {
if (this.chesses[this.lines[i][j]].player == p1 && j < this.lines[i].length - 2) {
if ((j + 2) < this.lines[i].length && this.chesses[this.lines[i][j + 1]].player == Player.None) {
if (this.chesses[this.lines[i][j + 2]].player == p1) {

找到可以挑的两个棋子后,还要判断这条线上不能有其他的棋子:

isfind = true;
for (k = j + 3; k < this.lines[i].length; k++) {
if (this.chesses[this.lines[i][k]].player != Player.None) {
isfind = false;
break;
}
}

确定这条线上只有对方两个棋子并且能被挑之后,再查找电脑方有没有可以去挑这两个棋子的棋子:

var result;
for (k = 0; k < this.lines.length; k++) {
pos = $.inArray(this.lines[i][j + 1], this.lines[k]);
if (pos != -1) {
for (n = pos - 1; n >= 0; n--) {
p2 = this.chesses[this.lines[k][n]].player;
if (p2 == Player.None) continue;
if (p2 == p1) break;
// 被挑的棋子1,被挑的棋子2,挑棋子的位置,用来挑的棋子
result = [this.lines[i][j], this.lines[i][j + 2], this.lines[i][j + 1], this.lines[k][n]];
break;
}
for (n = pos + 1; n < this.lines[k].length; n++) {
p2 = this.chesses[this.lines[k][n]].player;
if (p2 == Player.None) continue;
if (p2 == p1) break;
// 被挑的棋子1,被挑的棋子2,挑棋子的位置,用来挑的棋子
result = [this.lines[i][j], this.lines[i][j + 2], this.lines[i][j + 1], this.lines[k][n]];
break;
}
}
}

如果没有找到可挑的棋子,再查找可夹的棋子(夹棋子的时候有左右两方可能用来夹,这里只分析左方):

// 查找是否有可夹的棋子
for (i = 0; i < this.lines.length; i++) {
for (j = 0; j < this.lines[i].length; j++) {
if (this.chesses[this.lines[i][j]].player == p1 && j > 0 && j < (this.lines[i].length - 1)) {// 找到了
if (this.chesses[this.lines[i][j - 1]].player == player) {// 左边是否有对方棋子

找到被夹的后,要判断一下这条线上只能有已方的一个棋子和对方的一个棋子并且挨着:

isfind = true;
// 其他的位置只能是空
for (k = 0; k < j - 1; k++) {
if (this.chesses[this.lines[i][k]].player != Player.None) { isfind = false; break; }
}
if (isfind) {
for (k = j + 1; k < this.lines[i].length; k++) {
if (this.chesses[this.lines[i][k]].player != Player.None) { isfind = false; break; }
}
}

最后再找已方可以用来执行“夹”的棋子:

var result;
for (k = 0; k < this.lines.length; k++) {
pos = $.inArray(this.lines[i][j + 1], this.lines[k]);
if (pos != -1) {
for (n = pos - 1; n >= 0; n--) {
p2 = this.chesses[this.lines[k][n]].player;
if (p2 == Player.None) continue;
if (p2 == p1) break;
// 被夹的棋子,可用来夹的位置,夹棋子的棋子
result = [this.lines[i][j], this.lines[i][j + 1], this.lines[k][n]];
break;
}
for (n = pos + 1; n < this.lines[k].length; n++) {
p2 = this.chesses[this.lines[k][n]].player;
if (p2 == Player.None) continue;
if (p2 == p1) break;
// 被夹的棋子,可用来夹的位置,夹棋子的棋子
result = [this.lines[i][j], this.lines[i][j + 1], this.lines[k][n]];
break;
}
}
}

找了可以被挑或被夹的棋子后,就直接执行 moveChess 函数,然后再判断一下执行完后游戏是否结束就可以了。

如果没有找到合适的棋子,就需要自动下棋。我们暂时做最初级别的,随机下一个棋子:

var i, j, k, index, moved, mover;
var items = [];
// 可以下棋的棋子
for(i=0; i<this.chesses.length; i++){
if(this.chesses[i].player==this.currentPlayer) items.push(i);
}
if(items.length==0) return; k = 0;
moved = 0;
while(k<20){
// 随机得到一个棋子用于移动
var movec = items.length==1?0:Math.floor(Math.random() * ( items.length-1 + 1)); var dirs = [];
for(i=0; i<this.lines.length; i++){
index = $.inArray(items[movec], this.lines[i]);
if(index!=-1) dirs.push(i);
}
// 随机得到一条可移动的路线
var linec = Math.floor(Math.random() * ( dirs.length-1 + 1));
// 移动棋子
index = $.inArray(items[movec], this.lines[dirs[linec]]); mover = 0;
if(index==0||index==(this.lines[dirs[linec]].length-1)){
if(index==0) mover = 1;
}else{// 随机下棋方向
var dirc = Math.floor(Math.random() * ( 1 + 1));
if(dirc==0) mover = 1;
}
if(mover){
if(this.moveChess(this.lines[dirs[linec]][index+1], items[movec])){
this.currentIndex = this.lines[dirs[linec]][index+1];
console.log(this.currentIndex);
moved = 1;
break;
}
}else{
if(this.moveChess(this.lines[dirs[linec]][index-1], items[movec])){
this.currentIndex = this.lines[dirs[linec]][index-1];
console.log(this.currentIndex);
moved = 1;
break;
}
}
k++;
}
if(moved){
if (!this.chessarray) {
var player = this.currentPlayer;
this.currentPlayer = this.getAnotherPlayer(player);
this.changePlayer();
if (this.isGameOver(this.currentPlayer)) { this.winner = player; this.isover = true; }
}
}else{
this.winner = player; this.isover = true;
}

好的,《五子飞》游戏就到此结束了。

代码中都有相关注释了,里沃特就简单跟小伙伴们说下,不清楚的可以留言。要源码的可以直接查看网页源代码。

还有一点点小BUG,游戏结束时也没有提示,要想重新开始游戏,需要刷新页面。

里沃特旨在跟大家分享怎么从写个小游戏入手,代码考虑得不周全,伙伴们互相交流。高手们也请指教下:)

HTML5+JS 《五子飞》游戏实现(一)规则

HTML5+JS 《五子飞》游戏实现(二)路线分析和资源准备

HTML5+JS 《五子飞》游戏实现(三)页面和棋盘棋子

HTML5+JS 《五子飞》游戏实现(四)夹一个和挑一对

HTML5+JS 《五子飞》游戏实现(五)移动棋子

HTML5+JS 《五子飞》游戏实现(六)鼠标响应与多重选择

HTML5+JS 《五子飞》游戏实现(七)游戏试玩

HTML5+JS 《五子飞》游戏实现(八)人机对战的更多相关文章

  1. HTML5+JS 《五子飞》游戏实现(一)规则

    很久没写文章了,这个游戏其实已经写了有段时间了,一直没有完善,赶在新年之际,分享给大家. 该<五子飞>游戏,不是平常大家所说的<五子棋>,这个玩法简单,是我们老家儿时常玩的一种 ...

  2. HTML5+JS 《五子飞》游戏实现(七)游戏试玩

    前面第一至第六章我们已经把<五子飞>游戏的基本工作都已经讲得差不多了,这一章主要是把所有的代码分享给大家,然后小伙伴们也可以玩一玩. 至于人机对战的我们放到后面讲进行分析. 试玩地址:ht ...

  3. HTML5+JS 《五子飞》游戏实现(六)鼠标响应与多重选择

    上一章我们提到了如果有多条线上的棋子可以被吃掉,那么游戏需要提示用户,让用户选择吃哪条线上的.另外因为是网页游戏,所以一定要实现鼠标单击棋子可以进行操作. 当鼠标移动棋子上面后,切换鼠标指针为手形,移 ...

  4. HTML5+JS 《五子飞》游戏实现(五)移动棋子

    上一章 我们知道了怎么处理两个重要的吃棋动作,想要吃对方的棋子,首先得移动自己的棋子.现在里沃特跟大家分享分享,怎么移动棋子. 想要移动棋子,在页面上,首先要点击一下要移动的棋子,然后再点击一下目标位 ...

  5. HTML5+JS 《五子飞》游戏实现(四)夹一个和挑一对

    在第一章我们已经说了怎么才能“夹一个”以及怎样才能挑一对,但那毕竟只是书面上的,对码农来讲,我们还是用代码讲解起来会更容易了解. 为了更容易对照分析,我们先把路线再次贴出来: // 可走的路线 thi ...

  6. HTML5+JS 《五子飞》游戏实现(三)页面和棋盘棋子

    前面两节,我们已经对<五子飞>有个初步的认识,对走棋路线也有了基本的了解,现在里沃特继续跟大家分享HTML页面,另外把棋盘棋子也画出来. 演示地址:http://www.lyout.com ...

  7. HTML5+JS 《五子飞》游戏实现(二)路线分析和资源准备

    上一节 里沃特与我们分享了<五子飞>的下棋规则,可能有些伙伴看得不清楚,像我们码农还是看到代码比较靠谱.下面就把可以走棋的路线跟大家说一下. 假设从左上角开始,以0开始编号,往右数(没看第 ...

  8. 用html5+js实现掌机游戏赛车demo

    最近无聊,用html5+js做了一个以前玩过的掌机赛车游戏,顺便学习一下画布的api以及巩固一下js基础. 游戏界面,没做什么美化. 游戏规则:游戏界面分为三列,黑色方块随机落下,红色方块可以在三列自 ...

  9. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

随机推荐

  1. IO系统性能之一:衡量性能的几个指标

    作为一个数据库管理员,关注系统的性能是日常最重要的工作之一,而在所关注的各方面的性能只能IO性能却是最令人头痛的一块,面对着各种生涩的参数和令人眼花缭乱的新奇的术语,再加上存储厂商的忽悠,总是让我们有 ...

  2. Android Paint类方法说明

    * Paint类介绍 * * Paint即画笔,在绘图过程中起到了极其重要的作用,画笔主要保存了颜色, * 样式等绘制信息,指定了如何绘制文本和图形,画笔对象有很多设置方法, * 大体上可以分为两类, ...

  3. subversion 1.8.5好像不是很成熟

    加:--enable-all-static1. 没找到libneon库支持,不得不用libserf。2. libserf编译要用到scons.py,所有要有python工具支持。3. 当遇到链接少ss ...

  4. (一)半小时开发一个APP

    [前言] HPP是什么? HybirdApp的简称,详细介绍参见:HPP--让所有中小企业拥有自己的APP 说白了就是用html+css+js开发app,包括ios和android版本. HBuild ...

  5. POJ 1584 A Round Peg in a Ground Hole --判定点在形内形外形上

    题意: 给一个圆和一个多边形,多边形点可能按顺时针给出,也可能按逆时针给出,先判断多边形是否为凸包,再判断圆是否在凸包内. 解法: 先判是否为凸包,沿着i=0~n,先得出初始方向dir,dir=1为逆 ...

  6. unity3d 的Quaternion.identity和transform.rotation区别是什么

    Quaternion.identity就是指Quaternion(0,0,0,0),就是每旋转前的初始角度,是一个确切的值,而transform.rotation是指本物体的角度,值是不确定的,比如可 ...

  7. 【Unity】Update()和FixedUpdate()

    Update()每帧调用,FixedUpdate()以指定频率被调用. 可以在 Edit -> project settings -> Time -> Fixed Timestep ...

  8. java自带线程池和队列详细讲解

    Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后 ...

  9. 利用MySQL存储过程分割字符串

    (转)http://tec.5lulu.com/detail/104krn1e6p2w78d77.html 现有一段字符串,如apple,banana,orange,pears,grape,要把它按照 ...

  10. C#手工注入辅助工具

    看了某牛出版的MySql手注天书一神书,基本上解决了SQL注入上的知识点,于是打完(酱油)省赛回来通宵了一晚上写了个工具 方便语句构造SQL 联合查询 报错注入 盲注 读写 命令执行 基本都有整合 遇 ...