惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 里沃特

XR806开发板环境搭建记录 谈谈把网站迁移到阿里云的一些感想和其中遇到的一些问题 HTML5+JS 《五子飞》游戏实现(七)游戏试玩 - 里沃特 HTML5+JS 《五子飞》游戏实现(六)鼠标响应与多重选择 HTML5+JS 《五子飞》游戏实现(五)移动棋子 HTML5+JS 《五子飞》游戏实现(四)夹一个和挑一对 - 里沃特 HTML5+JS 《五子飞》游戏实现(三)页面和棋盘棋子 HTML5+JS 《五子飞》游戏实现(二)路线分析和资源准备 - 里沃特 HTML5+JS 《五子飞》游戏实现(一)规则 cocos2dx-2.2.1 免 Cygwin 环境搭建(Win8+VS2013+ADT Bundle+android-ndk-r9c) - 里沃特 深入理解 cocos2d-x 坐标系 - 里沃特 在VS2010 下编译 cocos2d-x-2.1.4 - 里沃特 FFmpeg 1.2 for Android 生成一个动态库 FFmpeg 1.2 for Android 编译动态库 - 里沃特 Linq 批量更新数据 C# 统一对 try...catch 的调用,方便保存错误日志。 手机:由全触摸屏失效所想到的 愚人节奉献给大家的礼物,敬请收下 C# 让控件全屏显示(WinForm) - 里沃特
HTML5+JS 《五子飞》游戏实现(八)人机对战
里沃特 · 2015-01-19 · via 博客园 - 里沃特

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

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

完整《五子飞》游戏人机对战: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 《五子飞》游戏实现(七)游戏试玩