在线五子棋对战 --- 人机对战的实现

这篇具有很好参考价值的文章主要介绍了在线五子棋对战 --- 人机对战的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 人机对战

要增添一个人机对战的模块, 最大的难点就是如何让人机知道下在什么位置是最好的, 不仅要具备进攻的能力, 还需要具备防守的能力.

这里当人机第一次走的时候, 采用标准开局, 下子在最中间.
当玩家走了之后, 人机就需要去判定下在什么位置合理.

这里采用的是评分表的方法来计算落子在每一个位置的分数, 根据最高分数来进行下子.

1.1 演示

在线五子棋对战 --- 人机对战的实现

1.2 评分表

分析棋形的几种情况.
例如, 自己是黑子.
"_" 代表 没有子, "1" 代表 黑子 , "0" 代表 白子

当落子只有一颗子的情况
_ 1 _
_ 1 0
0 1 _
0 1 0

当落子有两颗子的情况
_ 1 1 _
_ 1 1 0
0 1 1 _
0 1 1 0

当落子有三颗子的情况
_ 1 1 1 _
_ 1 1 1 0
0 1 1 1 _
0 1 1 1 0

当落子有四颗子的情况
_ 1 1 1 1 _
_ 1 1 1 1 0
0 1 1 1 1 _
0 1 1 1 1 0

当落子有五颗子的情况
_ 1 1 1 1 1 _
_ 1 1 1 1 1 0
0 1 1 1 1 1 _
0 1 1 1 1 1 0

这里大概的情况分为这几种, 分别对这几种情况进行一个分数的设定, 让机器人根据分数的高低优先去处理某种情况.

这里设计一种分数表

一子情况

在线五子棋对战 --- 人机对战的实现

二子情况

在线五子棋对战 --- 人机对战的实现

三子情况

在线五子棋对战 --- 人机对战的实现

四子情况

在线五子棋对战 --- 人机对战的实现

五子情况

在线五子棋对战 --- 人机对战的实现

1.3 算法思路

使用暴力搜索的方法, 将棋盘中每个空格的子, 当下子的时候, 去判定下子之后, 横向得分情况, 竖向得分情况, 左斜得分情况, 右斜的得分情况.

例如, 下子是黑子.
 
横向, 去看左边有多少个黑子, 多少白子, 去看右边有多少个黑子, 多少白子. 然后根据评分表, 算得分数.
 
纵向, 去看上方有多少黑子, 多少白子, 再去下方看有多少个黑子, 多少白子, 然后根据评分表, 算得分数.
 
左斜, 去左下方看有多少黑子, 多少白子, 再去右上方看有多少黑子, 多少白子, 然后根据评分表, 算得分数.
 
右斜. 去左上方看有多少黑子,多少白子, 再去右下方看有多少黑子, 多少白子, 然后根据评分表, 算得分数.

将四个方向的得分加起来, 算得分数, 进行下子.

这里这种算法, 只具备了进攻, 不具备防守的能力. 要想人机下棋具备防守的能力, 还需要让人机对玩家落子的分数进行评估, 如果玩家落子得分更高, 就需要考虑去防守了.

这里就让, 对每个位置, 机器人落子, 和玩家落子, 算得机器人落子的得分, 和玩家落子的得分, 对分数进行相加, 然后再去比较, 当前是最大的得分情况, 就去当前位置落子.

这里进行测试的时候, 发现出现四子的时候, 会出现不进攻 或者不防守的情况. 所以在判定的时候, 如果出现了五子连珠的情况, 首先进攻. 如果对方有四子, 自己没法五子, 首先防守.

1.4 具体代码

1.4.1 评分表方法

根据评分表来分配分数, my表示我下的棋子, his表示他下的棋子

public int score(int my,int his){
        if(my > 5) return 200000;
        if(my == 5 && his == 0) return 200000;
        if(my == 5 && his == 1) return 200000;
        if(my == 5 && his == 2) return 200000;
        if(my == 4 && his == 1) return 3000;
        if(my == 4 && his == 0) return 50000;
        if(my == 4 && his == 2) return 1000;
        if(my == 3 && his == 0) return 3000;
        if(my == 3 && his == 1) return 1000;
        if(my == 3 && his == 2) return 500;
        if(my == 2 && his == 0) return 500;
        if(my == 2 && his == 1) return 200;
        if(my == 2 && his == 2) return 100;
        if(my == 1 && his == 0) return 100;
        if(my == 1 && his == 1) return 50;
        if(my == 1 && his == 2) return 30;
        return 0;
    }

1.4.2 横向得分方法

算得横向自己棋子数, 和他的棋子数
如果遇到空格就不计算了, 遇到别人的棋子也不计算了

public int getXScore(int x,int y, int chess){
        int my = 1;
        int his = 0;
        for(int i = x-1; i >= 0; i--){
            if(chess == board[i][y]){
                my++;
            }else if(board[i][y] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        for(int i = x+1; i<board.length; i++) {
            if(chess == board[i][y]){
                my++;
            }else if(board[i][y] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        return score(my,his);
    }

1.4.3 纵向得分方法

算得纵向自己棋子数, 和他的棋子数
如果遇到空格就不计算了, 遇到别人的棋子也不计算了

    private int getYScore(int x, int y, int chess) {
        int my = 1;
        int his = 0;
        for(int i = y-1; i >= 0; i--){
            if(chess == board[x][i]){
                my++;
            }else if(board[x][i] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        for(int i = y+1; i < board.length; i++){
            if(chess == board[x][i]){
                my++;
            }else if(board[x][i] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        return score(my,his);
    }

1.4.4 左斜得分方法

算得左斜向自己棋子数, 和他的棋子数
如果遇到空格就不计算了, 遇到别人的棋子也不计算了

    private int getSkewScore2(int x, int y, int chess) {
        int my = 1;
        int his = 0;
        for(int i = x+1,j=y-1; i<board.length && j >=0; i++,j--){
            if(chess == board[i][j]){
                my++;
            }else if(board[i][j] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        for(int i = x-1,j=y+1; i>=0 && j<board.length; i--,j++){
            if(chess == board[i][j]){
                my++;
            }else if(board[i][j] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        return score(my,his);
    }

1.4.5 右斜得分方法

算得右斜向自己棋子数, 和他的棋子数
如果遇到空格就不计算了, 遇到别人的棋子也不计算了

 private int getSkewScore1(int x, int y, int chess) {
        int my = 1;
        int his = 0;
        for(int i = x-1,j =y-1; i >=0 && j>=0; i--,j--){
            if(chess == board[i][j]){
                my++;
            }else if(board[i][j] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        for(int i = x+1,j=y+1; j<board.length && i < board.length; i++,j++){
            if(chess == board[i][j]){
                my++;
            }else if(board[i][j] == 0){
                break;
            }else{
                his++;
                break;
            }
        }
        return score(my,his);
    }

1.4.6 落子总得分方法

这里如果自己下的子可以优先五子连珠就直接下棋.
如果没有这种情况, 再去判定是否他可以五子连珠, 如果有直接堵住
其他就计算总分数文章来源地址https://www.toymoban.com/news/detail-451679.html

    public int getScore(int x,int y) {
        int numX1 = getXScore(x,y,1);
        int numX2 = getXScore(x,y,2);
        int numY1 = getYScore(x,y,1);
        int numY2 = getYScore(x,y,2);
        int skew1 = getSkewScore1(x,y,1);
        int skew2 = getSkewScore1(x,y,2);
        int skew3 = getSkewScore2(x,y,1);
        int skew4 = getSkewScore2(x,y,2);
        if(numX2 >= 200000 || numY2 >= 200000 || skew2 >= 200000 || skew4 >= 200000) {
            return Integer.MAX_VALUE;
        }
        if(numX1 >= 200000 || numY1 >= 200000 || skew1 >= 200000 || skew3 >= 200000){
            return Integer.MAX_VALUE;
        }
        int xScore = getXScore(x,y,1)+getXScore(x,y,2);
        int yScore = getYScore(x,y,1)+getYScore(x,y,2);
        int skewScore1 = getSkewScore1(x,y,1)+getSkewScore1(x,y,2);
        int skewScore2 = getSkewScore2(x,y,1)+getSkewScore2(x,y,2);
        return xScore + yScore + skewScore1 + skewScore2;
    }

1.4.7 确认落子位置的方法

 public int[] concluate() {
        int[] res = new int[2];
        int max = 0;
        for(int i = 0; i < Constant.ROW; i++) {
            for(int j = 0; j < Constant.COL; j++) {
                if(board[i][j] != 0) {
                    continue;
                }
                int num = getScore(i,j);
                if(num == 200000){
                    res[0] = i;
                    res[1] = j;
                    return res;
                }
                if(num > max) {
                    max = num;
                    res[0] = i;
                    res[1] = j;
                }
            }
        }
        return res;
    }

到了这里,关于在线五子棋对战 --- 人机对战的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++项目:在线五子棋对战网页版--匹配对战模块开发

    玩家匹配是根据自己的天梯分数进行匹配的,而服务器中将玩家天梯分数分为三个档次: 1. 普通:天梯分数小于2000分 2. 高手:天梯分数介于2000~3000分之间 3. 大神:天梯分数大于3000分 当玩家进行对战匹配时,服务器会根据档次,将玩家送到不同档次的匹配队列当中。共有

    2024年02月13日
    浏览(35)
  • C++在线五子棋对战(网页版)项目:websocket协议

    目标:认识理解websocket协议、websocket切换过程和websocket协议格式。认识和学会使用websocketpp库常用接口。了解websocketpp库搭建服务器流程,认识和学会使用websocketpp库bin接口,最后使用websocketpp库搭建服务器。 平时我们在逛某宝,点击商品查看商品信息,从HTTP角度来看,就是客

    2024年02月13日
    浏览(49)
  • C++项目:在线五子棋对战网页版--数据模块开发

    数据管理模块,基于mysql数据库进行数据管理以及封装数据管理模块实现数据库访问。因此,在数据库中,我需要为每一张表创建出对应类,通过类实例化的对象来访问这张数据库表中的数 据,这样的话当我们要访问哪张表的时候,使⽤哪个类实例化的对象即可。 那么在五子

    2024年02月13日
    浏览(33)
  • 基于FPGA(basys3)的双人对战人机对战五子棋(vivado)课程设计项目

    目录 主界面显示与选择模式 双人对战 人机对战 胜利界面显示 部分源码 VGA显示器显示图片,显示图片利用Block Memory Generator将图片像素点储存在RAM里面。 效果图:(防止侵权打了马赛克)  通过开发板上的按键进行模式选择,模式确定 双人对战就是采用简单的存数组的办法

    2024年01月18日
    浏览(50)
  • C++ 实现对战AI五子棋

     个人主页: 日刷百题 系列专栏 : 〖C/C++小游戏〗 〖Linux〗 〖数据结构〗   〖 C语言 〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ ​      为了能够快速上手一门语言,我们往往在学习了基本语法后,采用写一个小项目的方式来加深理解语言的语法及运用,本文采

    2024年02月03日
    浏览(52)
  • JAVA五子棋手机网络对战游戏的设计与实现(源代码+论文)

    在现代社会中,手机及其它无线设备越来越多的走进普通老百姓的工作和生活。 随着3G技术的普及与应用,基于Java开发的软件在手机上的使用非常的广泛,手机增值服务的内容也是越来越多,对丰富人们的生活内容、提供快捷的资讯起着不可忽视的作用。 本文基于J2ME技术,以

    2024年02月09日
    浏览(43)
  • 【项目设计】网络对战五子棋(上)

    想回家过年… 1.1 http1.0/1.1和websocket协议 1. a. http协议在Linux的学习部分我们就已经学习过了,当时http和https是一块学的,我们当时其实已经了解了http的大部分知识内容,比如http请求和响应的格式,各自的报头字段都有哪些,cookie和session机制,http1.1的长连接策略keep-alive,还有

    2024年02月07日
    浏览(48)
  • Linux项目实战——五子棋(单机人人对战版)

    Linux操作系统项目实战——五子棋 GIF: 目录            Linux操作系统项目——五子棋 一、问题导引: 二、实现要求: 三、五子棋原理: 1.落子数据信息保存载体: 2.落子思路: 3.判断“五子连珠” 四、项目实现步骤: Ⅰ.创建目录及文件: 1.在Linux环境下创建名为Gobang的文

    2024年02月03日
    浏览(50)
  • 网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(四)对战模块

    匹配成功返回数据 1. message消息类别 2. ok 3. reson 4. 房间id 5. 双方id 6.白色玩家 一个类记录房间中的信息(房间id,两个用户id,是否为白棋) 信息提示框 处理匹配API 初始化游戏(棋盘,下一个棋子,接受棋子处理响应,判断是否结束) 1. 客户端连接到游戏房间后, 服务器返回

    2024年02月13日
    浏览(50)
  • 2.6.C++项目:网络版五子棋对战之数据管理模块-游戏房间管理模块的设计

    对匹配成功的玩家创建房间,建立起一个小范围的玩家之间的关联关系! 房间里一个玩家产生的动作将会广播给房间里的其他用户。 将这些房间管理起来,以便于进行房间生命周期的控制! 游戏房间类: // 实现两个部分: // 1. 房间的设计 // 2. 房间管理的设置 // 游戏房间的

    2024年02月08日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包