Java五子棋Ai-权值法

  • 一、 什么是权值法?
  • 二、实现权值法Ai会面临的问题
    • 1、如何表达棋盘上未下处的横竖斜的棋子情况?(类似01120)
    • 2、如何将未下处的横竖斜情况和权值联系起来?(Hashmap)
    • 3、设置权值的思路是什么?
  • 三、具体代码的实现
    • 1、实现计算机遍历整个棋盘,分析出每个可下点的横竖斜情况
    • 2、实现权值的设置
    • 3、实现根据权值找到最优解

一、 什么是权值法?

权值法顾名思义,即是权衡不同的情况并赋予不同的数值,这个数值即代表着这个情况的重要性。
例如,当我们进行五子棋对战的时候,我们每下一个棋子就要判断这个点横竖斜的情况,对于不同的情况我们有不同的应对措施。而怎样做出最佳的判断,就需要权衡不同点的情况,在对自己最有利的地方下棋。
而我们的这种思考过程其实就是一种权值法,现在我们只是通过代码将自己的下棋思路赋予电脑,让 电脑每下一步棋的时候能够按照我们对不同情况理解来找到最优解,从而实现Ai。

二、实现权值法Ai会面临的问题

1、如何表达棋盘上未下处的横竖斜的棋子情况?(类似01120)

首先,整个棋盘就是一个15*15的二维数组记为doublearray[15][15],当没有下棋的时候,整个二维数组都是0。

然后,每当黑棋下在棋盘上,则记录此位置并将0变为1。同理,白旗也是如此。

那么,整个棋盘就通过包含012三种元素的二维数组将棋局保存了。

接着就是创建另一个二维数组来保存每一个点的权值并记为weightarray[15][15]。

每当我们遍历到doublearray中的一个点的时候,我们首先判断是否是0,因为对于以下的地方我们没有计算权值的必要,我们只需要我们还可以下的地方的权值就行。

如果现在找到了doublearray中的doublarray[i][j],并且这个数为零,那么我们可以对这个地方进行权值的计算。但计算权值之前,我们要记录下这个地方的横竖斜的棋局情况。

那么我们可以通过从这个点出发,向左、向右、向上、向下、向左上、向右下、向右上、向左下来记录下不同方向的棋子分布情况并且保存,然后每一个方向的情况对应一个权值,最后将所有方向的权值相加就是这个点的权值了。

具体代码见(三)(1

2、如何将未下处的横竖斜情况和权值联系起来?(Hashmap)

HashMap<String, Integer> map = new HashMap<String, Integer>()
这个就是创建了一个HashMap的对象,Java里面的HashMap类就有将字符串和对应的数字联系起来的功能,因此通过将代表棋局的012串和已经设置好的权值进行比较,即可实现权值和棋局的联系。

3、设置权值的思路是什么?

     眠                   活
一连      12("10")            10("20")
二连      112("30")         110("50")
三连      1112("60")            1110("100")
四连      11112("200")          11111("10")

上面的矩阵图只是一个思路,其中并没有涉及到具体的很多特殊情况和细节,其中眠和活分别指的是相连的同色棋的两端有没有敌方的棋堵住。我们可以根据这样的一个矩阵图思路清晰的写出自己对不同情况的认知,其中不仅仅需要考虑到单种情况的权值,还需要考虑到其中两个的权值和与其它的权值比较,例如当遍历到一个可下地方的时候发现对方存在两个活二,那么这个点就是十分危险的点了,必须要拦截,所以两个活三的和一定要比较大,才能让电脑发现这个情况的紧急。

三、具体代码的实现

1、实现计算机遍历整个棋盘,分析出每个可下点的横竖斜情况

public  int[][] GetWeightarray(){int weightarray[][] = new int[15][15];//遍历代表棋盘棋局的二维数组for(int i = 0; i < doublearray.length;i++){for(int j = 0; j < doublearray[i].length;j++){//对遍历到的地方判断是否存在棋子if(doublearray[i][j] == 0){int color = 0;String code = "";//向左求权值//为何隔两个间隔就不需要继续记录了呢,因为所有相连情况没有两个间隔的//相连情况有一连、二连、三连、四连for(int k = j - 1; k >= 0; k--){//如果此处没有棋子if(doublearray[i][k] == 0){if(doublearray[i][k] == doublearray[i][k+1])break;else code += doublearray[i][k];color = 0;}//如果此处有棋子else if(doublearray[i][k] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[i][k];code += doublearray[i][k];}//记录相连的同色棋子else if(doublearray[i][k] == color){code += doublearray[i][k];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[i][k] != color){color = doublearray[i][k];code += doublearray[i][k];}}}//得到向左的权值if(map.get(code) != null)weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向右求权值for(int k = j + 1; k < doublearray.length; k++){//如果此处没有棋子if(doublearray[i][k] == 0){if(doublearray[i][k] == doublearray[i][k-1])break;else code += doublearray[i][k];color = 0;}//如果此处有棋子else if(doublearray[i][k] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[i][k];code += doublearray[i][k];}//记录相连的同色棋子else if(doublearray[i][k] == color){code += doublearray[i][k];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[i][k] != color){color = doublearray[i][k];code += doublearray[i][k];break;}}}//得到向右的权值if(map.get(code) != null)weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向上求权值for(int k = i - 1; k >= 0; k--){//如果此处没有棋子if(doublearray[k][j] == 0){if(doublearray[k][j] == doublearray[k+1][j])break;else code += doublearray[k][j];color = 0;}//如果此处有棋子else if(doublearray[k][j] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[k][j];code += doublearray[k][j];}//记录相连的同色棋子else if(doublearray[k][j] == color){code += doublearray[k][j];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[k][j] != color){color = doublearray[k][j];code += doublearray[k][j];break;}}}//得到向上的权值if(map.get(code) != null)weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向下求权值for(int k = i + 1; k < doublearray.length; k++){//如果此处没有棋子if(doublearray[k][j] == 0){if(doublearray[k][j] == doublearray[k-1][j])break;else code += doublearray[k][j];color = 0;}//如果此处有棋子else if(doublearray[k][j] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[k][j];code += doublearray[k][j];}//记录相连的同色棋子else if(doublearray[k][j] == color){code += doublearray[k][j];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[k][j] != color){color = doublearray[k][j];code += doublearray[k][j];break;}}}if(map.get(code) != null)//得到向下的权值weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向左上角求权值for(int k = i - 1,m = j - 1; k >= 0 && m >= 0; k--,m--){//如果此处没有棋子if(doublearray[k][m] == 0){if(doublearray[k][m] == doublearray[k+1][m+1])break;else code += doublearray[k][m];color = 0;}//如果此处有棋子else if(doublearray[k][m] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[k][m];code += doublearray[k][m];}//记录相连的同色棋子else if(doublearray[k][m] == color){code += doublearray[k][m];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[k][m] != color){color = doublearray[k][m];code += doublearray[k][m];break;}}}if(map.get(code) != null)//得到向左上的权值weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向右下角求权值for(int k = i + 1,m = j + 1; k < doublearray.length && m < doublearray.length; k++,m++){//如果此处没有棋子if(doublearray[k][m] == 0){if(doublearray[k][m] == doublearray[k-1][m-1])break;else code += doublearray[k][m];color = 0;}//如果此处有棋子else if(doublearray[k][m] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[k][m];code += doublearray[k][m];}//记录相连的同色棋子else if(doublearray[k][m] == color){code += doublearray[k][m];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[k][m] != color){color = doublearray[k][m];code += doublearray[k][m];break;}}}if(map.get(code) != null)//得到右下的权值weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向右上角求权值for(int k = i - 1,m = j + 1; k >= 0 && m < doublearray.length; k--,m++){//如果此处没有棋子if(doublearray[k][m] == 0){if(doublearray[k][m] == doublearray[k+1][m-1])break;else code += doublearray[k][m];color = 0;}//如果此处有棋子else if(doublearray[k][m] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[k][m];code += doublearray[k][m];}//记录相连的同色棋子else if(doublearray[k][m] == color){code += doublearray[k][m];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[k][m] != color){color = doublearray[k][m];code += doublearray[k][m];break;}}}if(map.get(code) != null)//得到右上的权值weightarray[i][j] += map.get(code);//初始化颜色以及编码color = 0;code = "";//向左下角求权值for(int k = i + 1,m = j - 1; k < doublearray.length && m >= 0; k++,m--){//如果此处没有棋子if(doublearray[k][m] == 0){if(doublearray[k][m] == doublearray[k-1][m+1])break;else code += doublearray[k][m];color = 0;}//如果此处有棋子else if(doublearray[k][m] != 0){//记录第一个非零的棋子if(color == 0){color = doublearray[k][m];code += doublearray[k][m];}//记录相连的同色棋子else if(doublearray[k][m] == color){code += doublearray[k][m];}//记录到了第一个和之前相连的相同棋子的不同颜色棋子else if(doublearray[k][m] != color){color = doublearray[k][m];code += doublearray[k][m];break;}}}if(map.get(code) != null)//得到左下的权值weightarray[i][j] += map.get(code);//下面的不用管这些括号}}}return weightarray;}

2、实现权值的设置

这里还有很多特殊情况没有考虑,仅供参考!


//一活map.put("10", 30);map.put("1020", 30);map.put("1021", 30);//一眠map.put("12", 10);//二活map.put("110", 100);map.put("11020", 100);map.put("11021", 100);map.put("1010", 100);map.put("101012", 100);map.put("101020",100);map.put("101021", 100);map.put("220", 150);map.put("22010", 150);map.put("22012", 150);map.put("2020", 150);map.put("202021", 150);map.put("202010", 150);map.put("202012", 150);//二眠map.put("112", 80);map.put("1012", 80);//三活map.put("1110", 200);map.put("111010", 200);map.put("111012", 200);map.put("10110", 200);map.put("1011021", 200);map.put("1011020", 200);map.put("2220", 250);map.put("222020", 250);map.put("222021", 250);map.put("20220", 250);map.put("2022012", 250);map.put("2022010", 250);//三眠map.put("1112", 90);map.put("11012", 90);map.put("10112", 90);map.put("2221", 95);map.put("22021", 95);map.put("20221", 95);//四活map.put("22220", 2000);map.put("2222010", 2000);map.put("22220110", 2000);map.put("2222012", 2000);map.put("22220", 2000);//四眠map.put("11112", 1000);map.put("22221", 2000);map.put("22221", 2000);

3、实现根据权值找到最优解

 public void drawAI(Graphics g){g.setColor(Color.WHITE);int x = 0,y = 0;//找到权值表上权值最大的点for(int i = 0; i < weightarray.length;i++){for(int j = 0; j < weightarray[i].length;j++){if(weightarray[i][j]>=weightarray[x][y]){x = i;y = j;}}}//在棋盘上画出这个棋子g.fillOval(y*50+25, x*50+25, 50, 50);shapearray[count++] = new Shape(Color.white, y*50+25, x*50+25);//在doublearray棋局上面下一个白子doublearray[x][y] = 2;}

Java五子棋Ai-权值法相关推荐

  1. 简易五子棋AI权值法(2)

    简易五子棋&AI权值法(2) 权值法 权值法实现AI,就是给每个无子的地方给一个权值,然后选出权值最大的让电脑落子. 具体到每个位置,权值根据周围一定范围的落子情况给出. 就我的想法来说,我觉 ...

  2. 权值法实现五子棋AI

    权值法实现五子棋AI 前言 五子棋AI,能根据棋盘局势判断棋子应落在何处获胜,主要有权值法和博弈树法两种实现方案.本篇博客将就权值法展开介绍,笔者水平有限,望各路大神有所建议评论提出,谢谢. 权值法 ...

  3. Java 五子棋AI博弈树算法实现

    实际上现在的棋类AI都是采用了效率更高的算法(如蒙特卡洛树搜索)+Deep Learning实现.今天我们只探讨较简单的五子棋AI,大致有两种算法:五元组和博弈树. Java学习笔记 第一节 Java ...

  4. 五子棋java程序=权值法_五子棋(人机对弈)——Java权值法五子棋博弈

    五子棋人机博弈 五子棋,人与人之间博弈,我们不用考虑太多,都是玩家自动思考. 但是如果我们要玩一个单机的五子棋,实现人机的对战,那么我就得"帮"电脑考虑下走哪步了. 实现的方法大概 ...

  5. JAVA权值法实现五子棋_java游戏之 五子棋实现人人对战!

    五子棋,是我们大家都喜爱玩的智力棋类游戏,在学完了界面以及绘图之后便一直想做一个,如今终于如愿以偿,虽然还没有更好的美化该游戏,但是大局已定.高兴! 五子棋我们需要很多常量,比如说棋子的大小,棋盘格子 ...

  6. 五子棋(人机对弈)——Java权值法五子棋博弈

    五子棋人机博弈 五子棋,人与人之间博弈,我们不用考虑太多,都是玩家自动思考. 但是如果我们要玩一个单机的五子棋,实现人机的对战,那么我就得"帮"电脑考虑下走哪步了. 实现的方法大概 ...

  7. java五子棋AI算法人机对战(春物彩羽版可下载试玩PC端)

    五子棋AI算法 前言: 坐标西安,写于疫情封城期间.改进了之前写的基于极大极小值策略AI五子棋游戏,是用java实现的,采用了java老旧的jframe窗体和绘图类.写好之后整理成了这篇博客. 游戏采 ...

  8. 五子棋_AI权值算法(2)

    小编已经隔了好久没有更新了,原因我就不多说啦,接下来我要立个每周更新的flag啦. 上一篇我们的成果是这样的 然后如果我们要实现人机的话就需要算法啦,这里就使用比较简单的算法,其他的还有博弈树等比较高 ...

  9. JAVA五子棋AI(人机对战 颜色选择 悔棋等 可直接使用)

    五子棋是全国智力运动会竞技项目之一,容易上手,老少皆宜,而且趣味横生,引人入胜,不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性.当然,用 JAVA 语言编写五子棋 AI 小游戏也是一件非常 ...

  10. java二叉树求权值_百度笔试题目:二叉树路径权值和【转】

    数据结构课程 百度笔试题目: 给出一个二叉树,和一个整型值,求出二叉树上所有从根到叶子的路径,并且此路径上各个节点的权值之和等于给出的整型值. 解题思路: 根据二叉树的先根遍历思想,通过一个栈保存从根 ...

最新文章

  1. 物理服务器对应多个虚拟节点,一台物理机如何开多个云服务器
  2. 说一说,求一个正整数的二进制中0的个数
  3. akka_Akka的字数统计MapReduce
  4. 电子技术基础数字部分第六版_大部分数字图书馆技术特点与应用分析
  5. 《剑指Offer》 调整数组顺序使奇数位于偶数前面
  6. bzoj1046(HAOI2007)上升序列
  7. matlab hrv,利用ECG信号进行HRV分析
  8. 一键清理Quartus工程编译垃圾
  9. 2013年深圳百公里徒步感悟
  10. 怎么在计算机上面掉出CMD,电脑没有cmd怎么办
  11. 微信分享iOS Universal Link配置说明
  12. STM32定时触发ADC 采样频率等问题总结
  13. AutoCAD 2007创建块
  14. LTV预估与留存曲线拟合:指数函数还是幂函数?
  15. Cesium 获取当前视图的中心经纬度
  16. C++ accumulate()用法
  17. Java的基本程序设计
  18. 播放器播放视频画面均变暗(但网页视频正常)的解决方案
  19. flash文本竖排效果实现(AS3)
  20. 如何使用bat批处理文件打开多个指定网页,很简单

热门文章

  1. 大蟒蛇python头像_程序员用Python获取了自己以前的QQ历史头像,以前的非主流形象简直不忍直视...
  2. PayPal轮询收单系统升级之PayPalme亲友支付
  3. indesign中调出字符样式快捷键_InDesign快捷键大全 InDesign常用快捷键分享
  4. ubuntu 8.04.2
  5. 解读Sea Limited新财报:核心业务增速加快,离盈利还有多远?
  6. 从零开始学习3D可视化之摄像机
  7. 【ACM】杭电1178:Heritage from father 小心溢出!
  8. 值得看,为什么跨境电商一定要自建网站?
  9. (更新时间)2021年6月5日 商城高并发秒杀系统(.NET Core版) 36-高并发秒杀项目k8s集群部署
  10. Windows驱动_文件系统微小过滤驱动之一初识MiniFilter