前言

改了又改,查了又查,想了又想,我真的不知道怎样让它再聪明了,大多时候走的都是正确的,但偶尔会蹦出那么一步臭棋,全盘皆输。希望有相关经验的道友看到后可以指出原因和不足。

效果图

按钮什么的还未完成,只是能实现正常的下棋了。

完成过程

UI部分

本来准备找张棋盘图片做背景,想了下我们还有人机界面课呢,权当复习一下java GUI了,事实上过程比我想象中简单许多。现在界面部分输出游戏结果和按钮什么的还没来得及弄,只是凑合可以玩了,闲了再加上,先贴出来,找点动力再说。

棋盘部分 -- 实现落子,撤子,判断是否成五子(游戏结束)。对局面的评估函数(这个很重要,下面专门会解释)
AI部分(这个更重要了) , 主要功能就是得出AI的下一步走法。

alpha_beta剪枝搜索

未了解过此算法的可先去看
最大最小搜索
Alpha-Beta剪枝
上面两文解释的很清楚了,在此就不再赘述。

估值函数

判断是否能成5, 如果是机器方的话给予100000分,如果是人方的话给予-100000 分;
判断是否能成活4或者是双死4或者是死4活3,如果是机器方的话给予10000分,如果是人方的话给予-10000分;
判断是否已成双活3,如果是机器方的话给予5000分,如果是人方的话给予-5000 分;
判断是否成死3活3,如果是机器方的话给予1000分,如果是人方的话给予-1000 分;
判断是否能成死4,如果是机器方的话给予500分,如果是人方的话给予-500分;
判断是否能成单活3,如果是机器方的话给予200分,如果是人方的话给予-200分;
判断是否已成双活2,如果是机器方的话给予100分,如果是人方的话给予-100分;
判断是否能成死3,如果是机器方的话给予50分,如果是人方的话给予-50分;
判断是否能成双活2,如果是机器方的话给予10分,如果是人方的话给予-10分;
判断是否能成活2,如果是机器方的话给予5分,如果是人方的话给予-5分;
判断是否能成死2,如果是机器方的话给予3分,如果是人方的话给予-3分。

存在的问题以及未完成的地方

最主要的问题就是偶尔会走臭棋。反复调试找原因,甚至把搜索方法又重新写了一遍,还是无果。觉得问题出现在估值函数上,但又想不出如何解决。
未完成的地方当然是提高搜索的效率了,每次估值都是要全盘进行估值,这样造成的时间影响是很大的,还可以用位棋盘来保存局面的情况,每走一步进行更新,每次回溯时再恢复,这样估值时之用考虑最近的一步,而不是全局了。这个等日后有时间再好好改进一下吧。
对于输赢的判断已经有了,但是还少了UI部分的显示,只是仅仅输出提示在命令行上。

代码

AI走法搜索部分 --

import java.util.Random;/*** Created by shiyi on 16/3/14.*/
public class Robot {private static ChessBoard chess = ChessBoard.getInstance();private Robot() {}private static int depth = 1;private static int robotColor = chess.BLACK;private static Robot robot = new Robot();public static Robot getRobot() {return robot;}/* alpha_beta剪枝搜索 */public int alpha_betaFind(int depth, int alpha, int beta, int color, int prex, int prey) {if(depth >= Robot.depth || 0 != chess.isEnd(prex, prey, color%2+1)) {int ans = chess.reckon(robotColor) - chess.reckon(robotColor%2 + 1);if(depth % 2 == 0)ans = -ans;return ans;}for(int x=1; x<=chess.N; x++) {for(int y=1; y<=chess.N; y++) {if(!chess.isEmpty(x, y))continue;chess.makeMove(x, y, color);int val = -alpha_betaFind(depth+1, -beta, -alpha, color%2+1, x, y);chess.unMove(x, y);if(val >= beta)return beta;if(val > alpha)alpha = val;}}return alpha;}/* 返回AI走法 */public int[] getNext(int color) {int rel[] = new int[2];int ans = -100000000;Random random = new Random();for(int x=1; x<=chess.N; x++) {for(int y=1; y<=chess.N; y++) {if(!chess.isEmpty(x, y))continue;chess.makeMove(x, y, color);int val = -alpha_betaFind(0, -100000000, 100000000, color%2 + 1, x, y);int ra = random.nextInt(100);if(val > ans || val == ans && ra >= 50) {ans = val;rel[0] = x;rel[1] = y;}chess.unMove(x, y);}}return rel;}
}

落子撤子以及估值 --ChessBoard

/*** Created by shiyi on 16/3/14.*/
public class ChessBoard {public final int N = 15;public final int EMPTY = 0;public final int BLACK = 1;public final int WHITE = 2;public int[][] board = new int[N+1][N+1];private ChessBoard() {}private static final ChessBoard chess = new ChessBoard();/* 返回类单例 */public static ChessBoard getInstance() {return chess;}/*  判断该位置是否无子 */public boolean isEmpty(int x, int y) {return board[x][y] == EMPTY;}/* 落子 */public void makeMove(int x, int y, int color) {board[x][y] = color;}/* 撤子 */public void unMove(int x, int y) {board[x][y] = EMPTY;}public int reckon(int color) {int dx[] = {1, 0, 1, 1};int dy[] = {0, 1, 1, -1};int ans = 0;for(int x=1; x<=N; x++) {for (int y = 1; y <= N; y++) {if (board[x][y] != color)continue;int num[][] = new int[2][100];for (int i = 0; i < 4; i++) {int sum = 1;int flag1 = 0, flag2 = 0;int tx = x + dx[i];int ty = y + dy[i];while (tx > 0 && tx <= N&& ty > 0 && ty <= N&& board[tx][ty] == color) {tx += dx[i];ty += dy[i];++sum;}if(tx > 0 && tx <= N&& ty > 0 && ty <= N&& board[tx][ty] == EMPTY)flag1 = 1;tx = x - dx[i];ty = y - dy[i];while (tx > 0 && tx <= N&& ty > 0 && ty <= N&& board[tx][ty] == color) {tx -= dx[i];ty -= dy[i];++sum;}if(tx > 0 && tx <= N&& ty > 0 && ty <= N&& board[tx][ty] == EMPTY)flag2 = 1;if(flag1 + flag2 > 0)++num[flag1 + flag2 - 1][sum];}//成5if(num[0][5] + num[1][5] > 0)ans = Math.max(ans, 100000);//活4 | 双死四 | 死4活3else if(num[1][4] > 0|| num[0][4] > 1|| (num[0][4] > 0 && num[1][3] > 0))ans = Math.max(ans, 10000);//双活3else if(num[1][3] > 1)ans = Math.max(ans, 5000);//死3活3else if(num[1][3] > 0 && num[0][3] > 0)ans = Math.max(ans, 1000);//死4else if(num[0][4] > 0)ans = Math.max(ans, 500);//单活3else if(num[1][3] > 0)ans = Math.max(ans, 200);//双活2else if(num[1][2] > 1)ans = Math.max(ans, 100);//死3else if(num[0][3] > 0)ans = Math.max(ans, 50);//双活2else if(num[1][2] > 1)ans = Math.max(ans, 10);//单活2else if(num[1][2] > 0)ans = Math.max(ans, 5);//死2else if(num[0][2] > 0)ans = Math.max(ans, 1);}}return ans;}/* 判断局面是否结束 0未结束 1WHITE赢 2BLACK赢 */public int isEnd(int x, int y, int color) {int dx[] = {1, 0, 1, 1};int dy[] = {0, 1, 1, -1};for (int i = 0; i < 4; i++) {int sum = 1;int tx = x + dx[i];int ty = y + dy[i];while (tx > 0 && tx <= N&& ty > 0 && ty <= N&& board[tx][ty] == color) {tx += dx[i];ty += dy[i];++sum;}tx = x - dx[i];ty = y - dy[i];while (tx > 0 && tx <= N&& ty > 0 && ty <= N&& board[tx][ty] == color) {tx -= dx[i];ty -= dy[i];++sum;}if(sum >= 5)return color;}return 0;}
}

UI部分

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;/*** Created by shiyi on 16/3/15.*/
public class UI {private ChessBoard chess = ChessBoard.getInstance();private int userColor = chess.WHITE;private int robotColor = chess.BLACK;private Frame frame = new Frame("绘制棋盘");private MyChess drawArea = new MyChess();private Robot robot = Robot.getRobot();public void init(){Panel p = new Panel();//机器执先chess.makeMove(chess.N/2+1, chess.N/2+1, chess.BLACK);drawArea.setPreferredSize(new Dimension(720, 720));drawArea.addMouseListener(new MouseListener() {@Overridepublic void mouseClicked(MouseEvent e) {int x = e.getX();int y = e.getY();int i = (x-60)/40+1;int j = (y-60)/40+1;System.out.println(i+"---"+j);if(chess.isEmpty(i, j)) {chess.makeMove(i, j, userColor);int rel = chess.isEnd(i, j, userColor);if(rel != 0) {System.out.println("玩家胜利");return;}drawArea.repaint();int rob[] = robot.getNext(robotColor);chess.makeMove(rob[0], rob[1], robotColor);rel = chess.isEnd(rob[0], rob[1], robotColor);if(rel != 0) {System.out.println("机器胜利");return;}drawArea.repaint();}}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}});frame.add(drawArea);frame.setSize(900, 720);frame.setVisible(true);}
}class MyChess extends Canvas {private ChessBoard chess = ChessBoard.getInstance();private final int N = chess.N + 2;private final int square = 40;private final int stx = square;private final int sty = square;private final int length = (N-1)*square;public void drawPiece(int color, int x, int y, Graphics g) {if (color == chess.BLACK) {g.setColor(new Color(0, 0, 0));g.fillArc(stx + x * square - 19, sty + y * square - 19, 38, 38, 0, 360);} else if (color == chess.WHITE) {g.setColor(new Color(255, 255, 255));g.fillArc(stx + x * square - 19, sty + y * square - 19, 38, 38, 0, 360);}}public void paint(Graphics g) {g.setColor(new Color(0, 0, 0));g.fillRect(stx-8, sty-8, stx+(N-2)*square+15, sty+(N-2)*square+15);g.setColor(new Color(139, 255, 71));g.fillRect(stx-4, sty-4, stx+(N-2)*square+7, sty+(N-2)*square+7);g.setColor(new Color(0, 0, 0));g.fillArc(stx+8*square-6, sty+8*square-6, 12, 12, 0, 360);g.fillArc(stx+4*square-6, sty+4*square-6, 12, 12, 0, 360);g.fillArc(stx+4*square-6, sty+12*square-6, 12, 12, 0, 360);g.fillArc(stx+12*square-6, sty+4*square-6, 12, 12, 0, 360);g.fillArc(stx+12*square-6, sty+12*square-6, 12, 12, 0, 360);for(int i = 0; i < N; i++) {g.drawLine(stx+i*square, sty, stx+i*square, sty+length);g.drawLine(stx, sty+i*square, stx+length, sty+i*square);}for(int i=1; i<=chess.N; i++) {for(int j=1; j<=chess.N; j++) {drawPiece(chess.board[i][j], i, j, g);}}}
}

Main

/*** Created by shiyi on 16/3/14.*/
public class Main {public static void main(String[] args) {System.out.println("游戏开始");UI ui = new UI();ui.init();}
}

五子棋AI图形界面人机对战(JAVA实现)相关推荐

  1. C语言 五子棋 图形界面 人机对战

    项目仓库:https://gitee.com/siwenzhi/gobang 内容 直接放当时的答辩PPT吧 其实每个页面都是一个小视频 代码 #include<graphics.h> # ...

  2. 【C语言五子棋、三子棋人机对战篇的详细介绍】

    C语言--五子棋.井字棋人机对"战" 针对 "[C语言实现五子棋.三子棋人机对战,包含电脑人工智能对战(可攻可守)](非标题党)" 的详细介绍 五子棋.三子棋人 ...

  3. 【C语言实现五子棋、三子棋人机对战,包含电脑人工智能对战(可攻可守)】(非标题党)

    C语言--五子棋.井字棋人机对"战" 针对C语言学习过程中的五子棋.三子棋实现记录 五子棋人机对战 C语言--五子棋.井字棋人机对"战" 实际效果 一.头文件( ...

  4. Java 五子棋人人对战和人机对战简单实现

    废话不多说,咱直接进入正题 首先,为了方便,咱们先用一个Java接口把一些全局要用的数据写到接口里,这样就不用传来传去了 package wuziqi;public interface Gobang ...

  5. c语言五子棋人机对弈算法,使用canvas基于AI算法实现人机对战之五子棋

    这是我使用canvas基于AI算法实现的人机对战之五子棋 黑棋是我 下了几局,真心下不过啊!!! 不说了,源码奉上: 人机大战之五子棋 canvas{ display: block; margin:5 ...

  6. Android 蓝牙对战五子棋项目实现(含人机对战功能)

    上周花了一周时间做的课程设计的项目,实现的功能如下: 基本功能: (1) 该APP能够通过蓝牙自动搜索周围其他使用了该APP的手机,用户可选择其中某一个APP发起对战的要求,被发起方可以同意或者拒绝: ...

  7. java图形界面猜字游戏,java程序,猜字游戏,希望大神帮忙

    package com.may.eighteen; import java.util.Random; import java.util.Scanner; public class WeekDemo1  ...

  8. java 井字棋 人机_井字游戏 人机对战 java实现

    package com.ecnu.Main; /** * 主函数触发游戏 */ public class MainApplication { public static void main(Strin ...

  9. java图形界面 关闭_用 java编写的图形用户界面运行后怎么关不掉

    importjava.awt.*;importjavax.swing.*;publicclassGUIDemo{publicstaticvoidmain(String[]args){Framef=ne ...

最新文章

  1. oracle 三表关联更新_Oracle数据库入门
  2. 数字图像处理:附录-程序实例、参考文献、标准图片集合
  3. 掌握这些 Redis 技巧,百亿数据量不在话下!
  4. MySQL - 日常操作二 备份还原
  5. java内存问题怎么排查,java占内存高排查 java应用占用内存过高排查的解决方案...
  6. JS----JavaScript数组去重(12种方法,史上最全)
  7. 如何在myeclipse中导入jar包?
  8. warning: function declaration isn’t a prototype(函数声明不是原型)的解决办法
  9. transactional注解的使用_Java:Spring @Transactional工作原理
  10. eclipse项目一直显示有错,但是一直找不到错误在哪里
  11. 几个预防并发搞垮下游服务的方法
  12. Java集合Collection接口中的常用方法演示
  13. 智能循迹小车_校园智能车障碍断路方案浅谈
  14. MySQL 批量插入,如何不插入重复数据?
  15. 目标检测算法——小目标检测相关数据集(附下载链接)
  16. 蓝桥杯 画积木 /洛谷 P1990 墙壁覆盖
  17. 云、PaaS、DevOps难以名状的三角恋,你怎么看?
  18. 随机,摇号、彩票,生成随机数或是随机字符串(万能的evaluate) 。如何找到随机中的规律
  19. 从多臂老虎机开始学习强化学习中的探索与利用
  20. EASYOPS系列|谨慎!勿让持续交付变成bug自动化发布

热门文章

  1. 逐浪字库打造最全的书法字体,最全的合集(字体书法欣赏下载)
  2. 淘宝商品类目查询方法
  3. 我对云原生软件架构的观察与思考
  4. 树形图计算机系统组成,C数据结构的通用树结构和二进制排序树的基本操作
  5. 解决qt.qpa.plugin: Could not find the Qt platform plugin “xcb“ in ““
  6. 安卓是一个独立的操作系统
  7. 【2019-游记】中山纪念中学暑期游Day1
  8. 微小区V2 v2.3.4 小区 智能设备 智慧物业
  9. X64dbg使用技巧
  10. 充电宝不耐用怎么恢复?2022最耐用的充电宝排行榜