【Cocos Creator 实战教程(1)】——人机对战五子棋

整体思路

在15*15的棋盘上每一个可下棋子的地方都放置一个“隐形的棋子”,当要在某个位置下子时就将该位置的棋子显示出来,在判断输赢逻辑里,我们根据这225个”隐形棋子”的状态(黑,白,无)判断输赢

涉及知识点

  1. 场景切换
  2. 按钮事件监听
  3. 节点事件监听
  4. 节点数组
  5. 循环中闭包的应用
  6. 动态更换sprite图片
  7. 定时器

关于人机算法

参考了http://blog.csdn.net/onezeros/article/details/5542379

  • 新建工程

  • 在Menu.js里添加开始游戏方法
cc.Class({
    extends: cc.Component,

    startGame:function(){
        cc.director.loadScene(‘Game‘);
    }
});
  • 然后将其添加为Menu场景的Canvas的组件

现在我们在Menu场景里点击一下人机按钮就会跳转到游戏场景了

  • 将其改名为Chess拖入下面assets文件夹使其成为预制资源
  • 制作一个结束场景

  • 新建Game脚步添加到ChessBoard节点下
cc.Class({
    extends: cc.Component,

    properties: {

        overSprite:{
            default:null,
            type:cc.Sprite,
        },

        overLabel:{
          default:null,
          type:cc.Label
        },

        chessPrefab:{//棋子的预制资源
            default:null,
            type:cc.Prefab
        },

        chessList:{//棋子节点的集合,用一维数组表示二维位置
            default: [],
            type: [cc.node]
        },

        whiteSpriteFrame:{//白棋的图片
            default:null,
            type:cc.SpriteFrame
        },

        blackSpriteFrame:{//黑棋的图片
            default:null,
            type:cc.SpriteFrame
        },

        touchChess:{//每一回合落下的棋子
            default:null,
            type:cc.Node,
            visible:false//属性窗口不显示
        },

        gameState:‘white‘,

        fiveGroup:[],//五元组

        fiveGroupScore:[]//五元组分数
    },
    //重新开始
    startGame(){
        cc.director.loadScene("Game");
    },
    //返回菜单
    toMenu(){
        cc.director.loadScene("Menu");
    },

    onLoad: function () {
        this.overSprite.node.x = 10000;//让结束画面位于屏幕外
        var self = this;
        //初始化棋盘上225个棋子节点,并为每个节点添加事件
        for(var y = 0;y<15;y++){
            for(var x = 0;x < 15;x++){
                var newNode = cc.instantiate(this.chessPrefab);//复制Chess预制资源
                this.node.addChild(newNode);
                newNode.setPosition(cc.p(x*40+20,y*40+20));//根据棋盘和棋子大小计算使每个棋子节点位于指定位置
                newNode.tag = y*15+x;//根据每个节点的tag就可以算出其二维坐标
                newNode.on(cc.Node.EventType.TOUCH_END,function(event){
                    self.touchChess = this;
                    if(self.gameState ===  ‘black‘ && this.getComponent(cc.Sprite).spriteFrame === null){
                        this.getComponent(cc.Sprite).spriteFrame = self.blackSpriteFrame;//下子后添加棋子图片使棋子显示
                        self.judgeOver();
                        if(self.gameState == ‘white‘){
                            self.scheduleOnce(function(){self.ai()},1);//延迟一秒电脑下棋
                        }
                    }
                });
                this.chessList.push(newNode);
            }
        }
        //开局白棋(电脑)在棋盘中央下一子
        this.chessList[112].getComponent(cc.Sprite).spriteFrame = this.whiteSpriteFrame;
        this.gameState = ‘black‘;
        //添加五元数组
        //横向
        for(var y=0;y<15;y++){
            for(var x=0;x<11;x++){
                this.fiveGroup.push([y*15+x,y*15+x+1,y*15+x+2,y*15+x+3,y*15+x+4]);
            }
        }
        //纵向
        for(var x=0;x<15;x++){
            for(var y=0;y<11;y++){
                this.fiveGroup.push([y*15+x,(y+1)*15+x,(y+2)*15+x,(y+3)*15+x,(y+4)*15+x]);
            }
        }
        //右上斜向
        for(var b=-10;b<=10;b++){
            for(var x=0;x<11;x++){
                if(b+x<0||b+x>10){
                    continue;
                }else{
                    this.fiveGroup.push([(b+x)*15+x,(b+x+1)*15+x+1,(b+x+2)*15+x+2,(b+x+3)*15+x+3,(b+x+4)*15+x+4]);
                }
            }
        }
        //右下斜向
        for(var b=4;b<=24;b++){
            for(var y=0;y<11;y++){
                if(b-y<4||b-y>14){
                    continue;
                }else{
                    this.fiveGroup.push([y*15+b-y,(y+1)*15+b-y-1,(y+2)*15+b-y-2,(y+3)*15+b-y-3,(y+4)*15+b-y-4]);
                }
            }
        }
    },

    //电脑下棋逻辑
    ai:function(){
        //评分
        for(var i=0;i<this.fiveGroup.length;i++){
            var b=0;//五元组里黑棋的个数
            var w=0;//五元组里白棋的个数
            for(var j=0;j<5;j++){
                this.getComponent(cc.Sprite).spriteFrame
                if(this.chessList[this.fiveGroup[i][j]].getComponent(cc.Sprite).spriteFrame == this.blackSpriteFrame){
                    b++;
                }else if(this.chessList[this.fiveGroup[i][j]].getComponent(cc.Sprite).spriteFrame == this.whiteSpriteFrame){
                    w++;
                }
            }
            if(b+w==0){
                this.fiveGroupScore[i] = 7;
            }else if(b>0&&w>0){
                this.fiveGroupScore[i] = 0;
            }else if(b==0&&w==1){
                this.fiveGroupScore[i] = 35;
            }else if(b==0&&w==2){
                this.fiveGroupScore[i] = 800;
            }else if(b==0&&w==3){
                this.fiveGroupScore[i] = 15000;
            }else if(b==0&&w==4){
                this.fiveGroupScore[i] = 800000;
            }else if(w==0&&b==1){
                this.fiveGroupScore[i] = 15;
            }else if(w==0&&b==2){
                this.fiveGroupScore[i] = 400;
            }else if(w==0&&b==3){
                this.fiveGroupScore[i] = 1800;
            }else if(w==0&&b==4){
                this.fiveGroupScore[i] = 100000;
            }
        }
        //找最高分的五元组
        var hScore=0;
        var mPosition=0;
        for(var i=0;i<this.fiveGroupScore.length;i++){
            if(this.fiveGroupScore[i]>hScore){
                hScore = this.fiveGroupScore[i];
                mPosition = (function(x){//js闭包
                    return x;
                    })(i);
            }
        }
        //在最高分的五元组里找到最优下子位置
        var flag1 = false;//无子
        var flag2 = false;//有子
        var nPosition = 0;
        for(var i=0;i<5;i++){
            if(!flag1&&this.chessList[this.fiveGroup[mPosition][i]].getComponent(cc.Sprite).spriteFrame == null){
                nPosition = (function(x){return x})(i);
            }
            if(!flag2&&this.chessList[this.fiveGroup[mPosition][i]].getComponent(cc.Sprite).spriteFrame != null){
                flag1 = true;
                flag2 = true;
            }
            if(flag2&&this.chessList[this.fiveGroup[mPosition][i]].getComponent(cc.Sprite).spriteFrame == null){
                nPosition = (function(x){return x})(i);
                break;
            }
        }
        //在最最优位置下子
        this.chessList[this.fiveGroup[mPosition][nPosition]].getComponent(cc.Sprite).spriteFrame = this.whiteSpriteFrame;
        this.touchChess = this.chessList[this.fiveGroup[mPosition][nPosition]];
        this.judgeOver();
    },

    judgeOver:function(){
        var x0 = this.touchChess.tag % 15;
        var y0 = parseInt(this.touchChess.tag / 15);
        //判断横向
        var fiveCount = 0;
        for(var x = 0;x < 15;x++){
            if((this.chessList[y0*15+x].getComponent(cc.Sprite)).spriteFrame === this.touchChess.getComponent(cc.Sprite).spriteFrame){
                fiveCount++;
                if(fiveCount==5){
                    if(this.gameState === ‘black‘){
                        this.overLabel.string = "你赢了";
                        this.overSprite.node.x = 0;
                    }else{
                        this.overLabel.string = "你输了";
                        this.overSprite.node.x = 0;
                    }
                    this.gameState = ‘over‘;
                    return;
                }
            }else{
                fiveCount=0;
            }
        }
        //判断纵向
        fiveCount = 0;
        for(var y = 0;y < 15;y++){
            if((this.chessList[y*15+x0].getComponent(cc.Sprite)).spriteFrame === this.touchChess.getComponent(cc.Sprite).spriteFrame){
                fiveCount++;
                if(fiveCount==5){
                    if(this.gameState === ‘black‘){
                        this.overLabel.string = "你赢了";
                        this.overSprite.node.x = 0;
                    }else{
                        this.overLabel.string = "你输了";
                        this.overSprite.node.x = 0;
                    }
                    this.gameState = ‘over‘;
                    return;
                }
            }else{
                fiveCount=0;
            }
        }
        //判断右上斜向
        var f = y0 - x0;
        fiveCount = 0;
        for(var x = 0;x < 15;x++){
            if(f+x < 0 || f+x > 14){
                continue;
            }
            if((this.chessList[(f+x)*15+x].getComponent(cc.Sprite)).spriteFrame === this.touchChess.getComponent(cc.Sprite).spriteFrame){
                fiveCount++;
                if(fiveCount==5){
                    if(this.gameState === ‘black‘){
                        this.overLabel.string = "你赢了";
                        this.overSprite.node.x = 0;
                    }else{
                        this.overLabel.string = "你输了";
                        this.overSprite.node.x = 0;
                    }
                    this.gameState = ‘over‘;
                    return;
                }
            }else{
                fiveCount=0;
            }
        }
        //判断右下斜向
        f = y0 + x0;
        fiveCount = 0;
        for(var x = 0;x < 15;x++){
            if(f-x < 0 || f-x > 14){
                continue;
            }
            if((this.chessList[(f-x)*15+x].getComponent(cc.Sprite)).spriteFrame === this.touchChess.getComponent(cc.Sprite).spriteFrame){
                fiveCount++;
                if(fiveCount==5){
                    if(this.gameState === ‘black‘){
                        this.overLabel.string = "你赢了";
                        this.overSprite.node.x = 0;
                    }else{
                        this.overLabel.string = "你输了";
                        this.overSprite.node.x = 0;
                    }
                    this.gameState = ‘over‘;
                    return;
                }
            }else{
                fiveCount=0;
            }
        }
        //没有输赢交换下子顺序
        if(this.gameState === ‘black‘){
            this.gameState = ‘white‘;
        }else{
            this.gameState = ‘black‘;
        }
    }

});

最终效果

对于初学者几个建议

1.虽然官方说对JavaScript的要求不高,但我还是建议大家能找一本js的书从头到尾的学习一下,比如循环中闭包的应用,如果不了解就会走很多弯路

2.官方文档api里的教程其实很全面了,但并不适合从头到尾那样”读着学“,我们应该找一些简单的游戏,亲自上手做,需要哪些功能就到文档里去找,做游戏的多了,也就可以脱离文档了

工程源码链接:http://pan.baidu.com/s/1gf0gQjh 密码:59ns

微信号:xinshouit

更新会在里面通知

时间: 2024-10-13 06:42:23

【Cocos Creator 实战教程(1)】——人机对战五子棋的相关文章

【Cocos Creator 实战教程(2)】——天天酷跑(动画、动作相关)

转载请保留原文链接,个人公众号:xinshouit(新手程序员),欢迎关注 准备工作 把背景图拉长,很长很长的那种....一会我们要让它滑动起来 背景动画 为背景节点添加滚动动画 现在背景就循环滚动起来了(图是我后来截的,这步猴哥还没登场呢) 猴哥动画 导弹动画 这里我们要添加两个Clip,一个是高空导弹,一个是低空导弹 这里我们要给导弹加几个帧事件,在导弹导弹猴哥头上的几个帧上添加judgeDown事件,当导弹到达猴哥头上,猴哥还没低头,那就游戏结束,低空导弹同理,需要猴哥跳起 结束场景 游戏

【COCOS CREATOR 系列教程之二】脚本开发篇&事件监听、常用函数等示例整合

[Cocos Creator ](千人群):  432818031 上一篇,介绍了Himi在使用过cc所有组件后的一篇总结,没有具体介绍每个组件的原因在于官方文档很齐全,而且也有视频的介绍. 所以希望童鞋们可以把我这两篇博文当成对组件.脚本两部分开发的整理与总结. 后续的文章,Himi应该主要更新一些官方还未补充或者还没有的教程.避免无用功. 下面直接放出代码,因为不是很难理解.所以不再一一赘述,都是常用的函数.事件监听.动作回调.定时器等开发过程中必接触的. 大致内容如下: cc 属性介绍 获

介绍一款Android小游戏--交互式人机对战五子棋

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6589025 学习Android系统开发之余,编写了一个小游戏--交互式人机对战五子棋,自娱自乐.之所以称之为交互式人机对战五子棋,一是因为在进入人机对战模式这前,你可以任意设置好开局,同时,在对战过程中,你可以看到机器的思考过程,还可以标识出每一个落子点的优劣势:二是因为可以为机器增加游戏经验,使得机器越来越聪明.希望喜欢五子棋的同学能够喜欢,

基于Qt Creator实现中国象棋人机对战, c++实现

GitHub地址: https://github.com/daleyzou/wobuku 这是自己大一学完c++后,在课程实践中写过的一个程序,实现象棋人机对战的算法还是有点难的, 自己当时差不多也是写了两个月左右吧!当时看书又有很多问题得不到解决,所以就在网上找了一个视频跟着写. 当然,这其中有很多功能都是自己扩展的. 我把视频分享出来,希望能对新手有帮助吧! 视频地址:链接:https://pan.baidu.com/s/1pIp6UMJ6LXsuJ3GT80NGfw 密码:9k8y 注意:

【COCOS CREATOR 系列教程之四】基于0.7.1先简单制作一个PAGEVIEW

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/cocos-creator/1999.html 由于当前版本还没有发布1.0,因此还有不少组件没有发布,那么Himi也看到Cocos Creator群里有几个童鞋问起过PageView的问题,那么Himi正好借此练手,基于当前版本制作一个PageView. 本文分为两部分进行讲解: 1. 制作PageView     2. 如何使用 一. 制作

初学Cocos Creator收集的视频教程

技术胖 Cocos Creator基础视频教程(共5集) 简介和HELLOWORLD 软件界面介绍和跳动的小球制作 SCENE介绍和基本操作 玩家输入事件监听操作 PREFAB和计时器 http://jspang.com/category/learn/jichu/ 技术胖 Cocos Creator实战-<橡皮怪勇闯地下室>视频教程(共10集) 游戏简介和项目分析 UI界面布局 主角的动作监听和左右跳动 随机生成地刺 点击生成地刺和地刺的移动 碰撞检测132 倒计时和分数增加 欢迎界面代码编写

cocos creator学习--骨骼动画入门教程

参考:Mark_Liu--cocos creator--DragonBones 骨骼动画入门 1.首先在网上下载dragonBones 的文件解压后有三个文件 2.将文件夹放入cocos creator, 3.新建一个空结点并添加渲染组件dragonBones,新建一个js文件,将js文件和节点绑定.将资源的两个json文件放入dragonBones对应的框中 4.查看SwordsMan的json文件,搜索  gotoAndPlay  ,该关键字对应的就是动作名称 5.打开js文件,写入代码 c

飘扬的旗帜!shader 编程实战!Cocos Creator!

用 shader + mesh 立个 flag 吧! 文章底部获取完整代码! 效果预览 使用方法 创建一个空节点 添加用户脚本组件 mesh-texture-flag 添加图片 修改对应属性 实现原理 概括来说就是创建 mesh 网格模型,通过顶点着色器对顶点坐标不断的修改,达到飘动的效果.关于 mesh 的介绍,可以参考上一篇文章. 确定顶点坐标 为了让顶点着色器里有多个顶点可以改变位置,需要把一个形状分割成多个方形(三角形).分割数量越大,效果越精细,但需要消耗更多的性能消耗.下图是分割成两

cocos creator主程入门教程(一)—— 初识creator

四邑隐侠,本名关健昌,10年游戏生涯,现隐居四邑.本系列文章以TypeScript为介绍语言. 我们在cocos creator新建一个Hello TypeScript项目,都会有一个assets/Scene/helloworld.fire文件.使用cocos creator开发游戏时,项目可以只有一个.fire文件.一般地,我会把这个文件夹改名为assets/scene,下面只有main.fire文件:assets/scene/main.fire. 双击main.fire文件,在层级管理器可以