Java版AI五子棋游戏

 更新时间:2018年09月28日 10:41:17   作者:elims小熊  
这篇文章主要为大家详细介绍了Java版AI五子棋游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了java五子棋游戏的具体代码,供大家参考,具体内容如下

AI思路:通过判断棋盘上每个空位的分数,去分数最高的几个点,随机下棋
分数计算思路:能成5个说明能赢了,给最高分
不能成5个,对方能成5个,说明对方要赢了,给第二高分
能成活4,给第三高分
能成活3,给第四高分
能成冲4,给第五高分
能成冲3,给第六高分
能成活2,给第七高分
能成冲2,给第八高分
其他,给最低分
分数设定可自己定义。

因为是去年写的了,思路记得大概就是这样。最近根据书上写了个棋类游戏的设计框架,待完善后再发上来,应该会更新AI思路
下面是去年写的AI五子棋的代码:

package FivechessClient;
 
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;
 
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
 
/**
 * 
 * @ClassName: Game
 * @Description: AI五子棋
 * @author xiaoxiong
 * @date 2015年7月3日 下午8:59:02
 *
 */
public class Game {
 BufferedImage table;
 BufferedImage black;
 BufferedImage white;
 
 BufferedImage selected;
 /**
 * 棋子个数
 */
 private static int BOARD_SIZE = 15;
 /**
 * 棋盘宽高
 */
 private final int TABLE_WIDTH = 535;
 private final int TABLE_HEIGHT = 536;
 /**
 * 棋盘15等分
 */
 private final int RATE = TABLE_WIDTH / BOARD_SIZE;
 /**
 * 棋盘外边距
 */
 private final int X_OFFSET = 5;
 private final int Y_OFFSET = 6;
 /**
 * 棋盘
 */
 private int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
 /**
 * AI分数
 */
 private int[][] computerScore = new int[BOARD_SIZE][BOARD_SIZE];
 // private int[][] gamerScore = new int[BOARD_SIZE][BOARD_SIZE];
 
 JFrame f = new JFrame("五子棋--小熊");
 
 ChessBoard chessBoard = new ChessBoard();
 
 private static int selectedX = -1;
 private static int selectedY = -1;
 private static int computerX = -1;
 private static int computerY = -1;
 
 private static boolean flagGamer = false; // 记录玩家是否赢了
 private static boolean flagComputer = false; // 记录电脑是否赢了
 
 private static int computerscore = 0; // 电脑最大分数
 private static int comx, comy; // 玩家下子坐标
 
 private final int HUO = 1;
 private final int CHONG = 2;
 private static int chesscou = 0;
 /**
 * 记录找到的分数一样的棋子,随机下这些棋子中的一个,以防步法固定
 */
 private ArrayList<ChessXY> chessList = new ArrayList<ChessXY>();
 
 Random rand = new Random();
 
 /**
 * 
 * @Title: initto @Description: 重置游戏 @param @return void @throws
 */
 public void initto() {
 for (int i = 0; i < BOARD_SIZE; ++i) {
 for (int j = 0; j < BOARD_SIZE; ++j) {
 board[i][j] = 0;
 computerScore[i][j] = 100000;
 }
 }
 chesscou = 0;
 computerX = -1;
 computerY = -1;
 flagGamer = false;
 flagComputer = false;
 }
 
 /**
 * 
 * @Title: isRun @Description: 判断该位置是否可以走 @param @param x @param @param
 * y @param @return @return boolean @throws
 */
 public boolean isRun(int x, int y) {
 if (board[x][y] == 0) {
 return true;
 }
 return false;
 }
 
 /**
 * 
 * @Title: isWin @Description: 判断下该子是否能赢 @param @param f 颜色 @param @param x
 * 坐标 @param @param y @param @return @return boolean @throws
 */
 public boolean isWin(int f, int x, int y) {
 int i, count = 1;
 boolean up, down, right, left, rup, lup, rdown, ldown;
 up = down = right = left = rup = lup = rdown = ldown = true;
 /**
 *
 * 上下 
 *
 */
 for (i = 1; i < 5; ++i) {
 if ((y + i) < BOARD_SIZE) {
 if (board[x][y + i] == f && down)
 count++;
 else
 down = false;
 }
 if ((y - i) >= 0) {
 if (board[x][y - i] == f && up)
 count++;
 else
 up = false;
 }
 }
 if (count >= 5) {
 return true;
 }
 count = 1;
 /**
 *
 * 左右 
 *
 */
 for (i = 1; i < 5; ++i) {
 if ((x + i) < BOARD_SIZE) {
 if (board[x + i][y] == f && right)
 count++;
 else
 right = false;
 }
 if ((x - i) >= 0) {
 if (board[x - i][y] == f && left)
 count++;
 else
 left = false;
 }
 }
 if (count >= 5) {
 return true;
 }
 count = 1;
 /**
 *
 * 左上右下 
 *
 */
 for (i = 1; i < 5; ++i) {
 if ((x + i) < BOARD_SIZE && (y + i) < BOARD_SIZE) {
 if (board[x + i][y + i] == f && rdown)
 count++;
 else
 rdown = false;
 }
 if ((x - i) >= 0 && (y - i) >= 0) {
 if (board[x - i][y - i] == f && lup)
 count++;
 else
 lup = false;
 }
 }
 if (count >= 5) {
 return true;
 }
 count = 1;
 /**
 *
 * 右上左下
 *
 */
 for (i = 1; i < 5; ++i) {
 if ((x + i) < BOARD_SIZE && (y - i) >= 0) {
 if (board[x + i][y - i] == f && rup)
 count++;
 else
 rup = false;
 }
 if ((x - i) >= 0 && (y + i) < BOARD_SIZE) {
 if (board[x - i][y + i] == f && ldown)
 count++;
 else
 ldown = false;
 }
 }
 if (count >= 5) {
 return true;
 }
 
 return false;
 }
 
 /**
 * 
 * @Title: Computer_AI @Description: AI下棋 @param @return void @throws
 */
 public void Computer_AI() {
 computerscore = 0;
 for (int i = 0; i < BOARD_SIZE; ++i) {
 for (int j = 0; j < BOARD_SIZE; ++j) {
 computerScore[i][j] = 0;
 // gamerScore[i][j] = 0;
 }
 }
 getScore();
 for (int i = 0; i < BOARD_SIZE; ++i) {
 for (int j = 0; j < BOARD_SIZE; ++j) {
 if (computerScore[i][j] == computerscore) {
 ChessXY chess = new ChessXY(i, j);
 chessList.add(chess);
 }
 }
 }
 int n = rand.nextInt(chessList.size()); // 电脑根据分值一样的点随机走,防止每次都走相同的步数
 comx = chessList.get(n).x;
 comy = chessList.get(n).y;
 chessList.clear();
 }
 
 /**
 * 
 * @Title: getScore @Description: 评分 @param @return void @throws
 */
 public void getScore() {
 for (int i = 0; i < BOARD_SIZE; ++i) {
 for (int j = 0; j < BOARD_SIZE; ++j) {
 if (board[i][j] == 0) {
 if (isWin(2, i, j)) // 电脑能赢,故给分最高,因为可以结束,所以不再检测
 {
 computerscore = 13;
 computerScore[i][j] = 13;
 
 return;
 } else if (isWin(1, i, j)) // 电脑不能赢,玩家能赢,要阻止,所以给12分
 {
 computerscore = 12;
 computerScore[i][j] = 12;
 } else if (isHuoOrChong(2, i, j, 4, HUO)) // 电脑玩家都不能赢,电脑能形成活四,给11分
 {
 computerscore = (computerscore > 11 ? computerscore : 11);
 computerScore[i][j] = 11;
 } else if (isHuoOrChong(2, i, j, 4, CHONG)) // 电脑玩家都不能赢,电脑能形成冲四,给10分
 {
 computerscore = (computerscore > 10 ? computerscore : 10);
 computerScore[i][j] = 10;
 } else if (isHuoOrChong(1, i, j, 4, HUO)) // 电脑玩家都不能赢,玩家能形成活四,给9分
 {
 computerscore = (computerscore > 9 ? computerscore : 9);
 computerScore[i][j] = 9;
 } else if (isHuoOrChong(2, i, j, 3, HUO)) // 电脑玩家都不能赢,电脑能形成活三,给8分
 {
 computerscore = (computerscore > 8 ? computerscore : 8);
 computerScore[i][j] = 8;
 } else if (isHuoOrChong(1, i, j, 4, CHONG)) // 电脑玩家都不能赢,玩家能形成冲四,给7分
 {
 computerscore = (computerscore > 7 ? computerscore : 7);
 computerScore[i][j] = 7;
 } else if (isHuoOrChong(2, i, j, 3, CHONG)) // 电脑玩家都不能赢,电脑能形成冲三,给6分
 {
 computerscore = (computerscore > 6 ? computerscore : 6);
 computerScore[i][j] = 6;
 } else if (isHuoOrChong(2, i, j, 2, HUO)) // 电脑玩家都不能赢,电脑能形成活二,给5分
 {
 computerscore = (computerscore > 5 ? computerscore : 5);
 computerScore[i][j] = 5;
 } else if (isHuoOrChong(1, i, j, 3, CHONG)) // 电脑玩家都不能赢,玩家能形成冲三,给4分
 {
 computerscore = (computerscore > 4 ? computerscore : 4);
 computerScore[i][j] = 4;
 } else if (isHuoOrChong(1, i, j, 2, HUO)) // 电脑玩家都不能赢,玩家能形成活二,给3分
 {
 computerscore = (computerscore > 3 ? computerscore : 3);
 computerScore[i][j] = 3;
 } else if (isHuoOrChong(2, i, j, 2, CHONG)) // 电脑玩家都不能赢,电脑能形成冲二,给2分
 {
 computerscore = (computerscore > 2 ? computerscore : 2);
 computerScore[i][j] = 2;
 } else if (isHuoOrChong(1, i, j, 2, CHONG)) // 电脑玩家都不能赢,玩家能形成冲二,给1分
 {
 computerscore = (computerscore > 1 ? computerscore : 1);
 computerScore[i][j] = 1;
 } else {
 computerScore[i][j] = 0;
 }
 }
 }
 }
 }
 
 /**
 * 
 * @Title: isHuoOrChong @Description: 判断是否为活 @param @param f @param @param
 * x @param @param y @param @param num @param @param
 * hORc @param @return @return boolean @throws
 */
 private boolean isHuoOrChong(int f, int x, int y, int num, int hORc) // 活
 {
 
 num += 1;
 int i, count = 1;
 boolean terminal1 = false;
 boolean terminal2 = false;
 boolean up, down, right, left, rup, lup, rdown, ldown;
 up = down = right = left = rup = lup = rdown = ldown = true;
 /**
 *
 * 上下 
 *
 */
 for (i = 1; i < num; ++i) {
 if ((y + i) < BOARD_SIZE) {
 if (board[x][y + i] == f && down)
 count++;
 else {
 if (board[x][y + i] == 0 && down) {
 terminal1 = true;
 }
 down = false;
 }
 }
 if ((y - i) >= 0) {
 if (board[x][y - i] == f && up)
 count++;
 else {
 if (board[x][y - i] == 0 && up) {
 terminal2 = true;
 }
 up = false;
 }
 }
 }
 if (count == num - 1 && hORc == HUO && terminal1 && terminal2) {
 return true;
 }
 if (count == num - 1 && hORc == CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
 return true;
 }
 count = 1;
 terminal1 = false;
 terminal2 = false;
 /* 左右 */
 for (i = 1; i < num; ++i) {
 if ((x + i) < BOARD_SIZE) {
 if (board[x + i][y] == f && right)
 count++;
 else {
 if (board[x + i][y] == 0 && right) {
 terminal1 = true;
 }
 right = false;
 }
 }
 if ((x - i) >= 0) {
 if (board[x - i][y] == f && left)
 count++;
 else {
 if (board[x - i][y] == 0 && left) {
 terminal2 = true;
 }
 left = false;
 }
 }
 }
 if (count == num - 1 && hORc == HUO && terminal1 && terminal2) {
 return true;
 }
 if (count == num - 1 && hORc == CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
 return true;
 }
 count = 1;
 terminal1 = false;
 terminal2 = false;
 /**
 *
 * 左上右下 
 *
 */
 for (i = 1; i < num; ++i) {
 if ((x + i) < BOARD_SIZE && (y + i) < BOARD_SIZE) {
 if (board[x + i][y + i] == f && rdown)
 count++;
 else {
 if (board[x + i][y + i] == 0 && rdown) {
 terminal1 = true;
 }
 rdown = false;
 }
 }
 if ((x - i) >= 0 && (y - i) >= 0) {
 if (board[x - i][y - i] == f && lup)
 count++;
 else {
 if (board[x - i][y - i] == 0 && lup) {
 terminal2 = true;
 }
 lup = false;
 }
 }
 }
 if (count == num - 1 && hORc == HUO && terminal1 && terminal2) {
 return true;
 }
 if (count == num - 1 && hORc == CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
 return true;
 }
 count = 1;
 terminal1 = false;
 terminal2 = false;
 /**
 *
 * 右上左下 
 *
 */
 for (i = 1; i < num; ++i) {
 if ((x + i) < BOARD_SIZE && (y - i) >= 0) {
 if (board[x + i][y - i] == f && rup)
 count++;
 else {
 if (board[x + i][y - i] == 0 && rup) {
 terminal1 = true;
 }
 rup = false;
 }
 }
 if ((x - i) >= 0 && (y + i) < BOARD_SIZE) {
 if (board[x - i][y + i] == f && ldown)
 count++;
 else {
 if (board[x - i][y + i] == 0 && ldown) {
 terminal2 = true;
 }
 ldown = false;
 }
 }
 }
 if (count == num - 1 && hORc == HUO && terminal1 && terminal2) {
 return true;
 }
 if (count == num - 1 && hORc == CHONG && ((terminal1 && !terminal2) || (!terminal1 && terminal2))) {
 return true;
 }
 
 return false;
 }
 
 public void init() throws Exception {
 table = ImageIO.read(new File("image/board.jpg"));
 black = ImageIO.read(new File("image/black.gif"));
 white = ImageIO.read(new File("image/white.gif"));
 selected = ImageIO.read(new File("image/selected.gif"));
 
 for (int i = 0; i < BOARD_SIZE; ++i) {
 for (int j = 0; j < BOARD_SIZE; ++j) {
 board[i][j] = 0;
 computerScore[i][j] = 0;
 }
 }
 chessBoard.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
 
 chessBoard.addMouseListener(new MouseAdapter() {
 public void mouseClicked(MouseEvent e) {
 int xPos = (int) ((e.getX() - X_OFFSET) / RATE);
 int yPos = (int) ((e.getY() - Y_OFFSET) / RATE);
 // System.out.println("1 " + xPos + " " + yPos);
 if (isRun(xPos, yPos)) {
 flagGamer = isWin(1, xPos, yPos);
 board[xPos][yPos] = 1;
 chesscou++;
 // do //电脑下棋,随机
 // {
 // comx = (rand.nextInt(535) - X_OFFSET) / RATE;
 // comy = (rand.nextInt(536) - Y_OFFSET) / RATE;
 // } while (!isRun(comx, comy));
 if (chesscou == (BOARD_SIZE * BOARD_SIZE)) {
 JOptionPane.showMessageDialog(null, "不相上下!!!\n再来一盘吧!!!", "结束", JOptionPane.ERROR_MESSAGE);
 initto();
 } else {
 Computer_AI(); // 电脑下棋,AI算法
 chesscou++;
 // System.out.println("2 " + comx + " " + comy);
 flagComputer = isWin(2, comx, comy);
 board[comx][comy] = 2;
 computerX = comx;
 computerY = comy;
 }
 }
 chessBoard.repaint();
 if (flagGamer) {
 JOptionPane.showMessageDialog(null, "厉害厉害!!!\n你赢了!!!", "结束", JOptionPane.ERROR_MESSAGE);
 initto();
 } else if (flagComputer) {
 JOptionPane.showMessageDialog(null, "哈哈哈哈!!!\n你输了!!!", "结束", JOptionPane.ERROR_MESSAGE);
 initto();
 }
 }
 
 public void mouseExited(MouseEvent e) {
 selectedX = -1;
 selectedY = -1;
 chessBoard.repaint();
 }
 });
 chessBoard.addMouseMotionListener(new MouseMotionAdapter() {
 public void mouseMoved(MouseEvent e) {
 selectedX = (e.getX() - X_OFFSET) / RATE;
 selectedY = (e.getY() - Y_OFFSET) / RATE;
 
 chessBoard.repaint();
 }
 });
 f.add(chessBoard);
 f.setCursor(new Cursor(Cursor.HAND_CURSOR));
 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 f.setResizable(false);
 f.pack();
 f.setVisible(true);
 }
 
 public static void main(String[] args) throws Exception {
 Game game = new Game();
 game.init();
 }
 
 @SuppressWarnings("serial")
 class ChessBoard extends JPanel {
 public void paint(Graphics g) {
 g.drawImage(table, 0, 0, null);
 if (selectedX >= 0 && selectedY >= 0) {
 g.drawImage(selected, selectedX * RATE + X_OFFSET, selectedY * RATE + Y_OFFSET, null);
 }
 if (computerX >= 0 && computerY >= 0) {
 g.drawImage(selected, computerX * RATE + X_OFFSET, computerY * RATE + Y_OFFSET, null);
 }
 for (int i = 0; i < BOARD_SIZE; ++i) {
 for (int j = 0; j < BOARD_SIZE; ++j) {
 if (board[i][j] == 1) {
 g.drawImage(black, i * RATE + X_OFFSET, j * RATE + Y_OFFSET, null);
 }
 if (board[i][j] == 2) {
 g.drawImage(white, i * RATE + X_OFFSET, j * RATE + Y_OFFSET, null);
 }
 }
 }
 }
 }
}
 
class ChessXY {
 int x;
 int y;
 
 public ChessXY(int x, int y) {
 this.x = x;
 this.y = y;
 }
}

更多精彩游戏,请参考专题《java经典小游戏》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java程序执行cmd命令全过程

    Java程序执行cmd命令全过程

    这篇文章主要介绍了Java程序执行cmd命令全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • maven中resource配置使用详解

    maven中resource配置使用详解

    这篇文章主要介绍了maven中resource配置使用,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • 初次体验MyBatis的注意事项

    初次体验MyBatis的注意事项

    今天给大家带来的是关于MyBatis的相关知识,文章围绕着MyBatis的用法展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Java实现树形菜单的方法总结

    Java实现树形菜单的方法总结

    当我们想要展示层级结构,如文件目录、组织结构或分类目录时,树形菜单是一个直观且有效的解决方案,本文为大家整理了java中几种常见方法,希望对大家有所帮助
    2023-08-08
  • Java实现顺时针输出螺旋二维数组的方法示例

    Java实现顺时针输出螺旋二维数组的方法示例

    这篇文章主要介绍了利用Java如何实现顺时针输出螺旋二维数组的方法示例,文中给出了详细的示例代码和注释,相信对大家具有一定的参考价值,有需要的朋友们下面来一起看看吧。
    2017-02-02
  • spring boot如何使用AOP统一处理web请求

    spring boot如何使用AOP统一处理web请求

    这篇文章主要介绍了spring boot如何使用AOP统一处理web请求,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java如何解决发送Post请求报Stream closed问题

    Java如何解决发送Post请求报Stream closed问题

    这篇文章主要介绍了Java如何解决发送Post请求报Stream closed问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Spring Data JPA映射自定义实体类操作

    Spring Data JPA映射自定义实体类操作

    这篇文章主要介绍了Spring Data JPA映射自定义实体类操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 第三方包jintellitype实现Java设置全局热键

    第三方包jintellitype实现Java设置全局热键

    本文主要介绍了,在java中使用第三方插件包jintellitype来实现全局热键,非常的简单,但是很实用,有需要的朋友可以参考下,欢迎一起来参与改进此项目
    2014-09-09
  • java 中遍历取值异常(Hashtable Enumerator)解决办法

    java 中遍历取值异常(Hashtable Enumerator)解决办法

    这篇文章主要介绍了java 中遍历取值异常(Hashtable Enumerator)解决办法的相关资料,用迭代器取值时抛出的异常:java.util.NoSuchElementException: Hashtable Enumerator ,需要的朋友可以参考下
    2017-08-08

最新评论