五子棋人机对战:使用回溯法实现 AI 对手
package teachGoBang;/n/nimport java.awt.;/nimport java.awt.event.ActionEvent;/nimport java.awt.event.ActionListener;/nimport java.awt.event.MouseAdapter;/nimport java.awt.event.MouseEvent;/nimport java.io.;/n/n//import lqz3.Chess;/n/nimport javax.swing.;/n/n//在鼠标类中直接去继承MouseAdapter类而不是使用接口可以不用重写所有方法/npublic class Mouse extends MouseAdapter implements ActionListener, Basic {/n private Graphics g;// 定义画笔/n private int x, y, x1, y1;/n private int[][] chessArr = new int[line][line];// 定义二维数组,用于保存棋盘坐标对应的棋子颜色/n private ChessR[] chessB =new ChessR[lineline]; //定义一维数组存入棋子对象/n private int count = 0;// 定义计数器记录棋子个数/n private Color color;/n private String button;/n private boolean start=false;//定义布尔值,点击开始后start=true,判断输赢后start=false/n private MyPanel chesspanel;/n Win win = new Win(chessArr);//创建win对象并传入chessArr/n //通过构造方法,传入chesspanel/n public Mouse(MyPanel chesspanel) {/n this.chesspanel = chesspanel;/n }/n public void setGraphics(Graphics g) {/n this.g = g;/n }/n public int[][] getchessArr(){/n return chessArr;/n }/n public void setchessArr(int[][] chessArr) {/n this.chessArr = chessArr;/n }/n/n public void clean() {/n//遍历二维数组,让所有棋子颜色归零/n for(int i=0;i<chessArr.length;i++) {/n for(int j=0;j<chessArr[i].length;j++) {/n chessArr[i][j] = 0;/n }/n }/n //执行重绘方法,除去所有棋子/n chesspanel.paint(g);/n }/n/n public void actionPerformed(ActionEvent e) {/n button = e.getActionCommand();// 按钮内容对应鼠标点击信息/n switch (button) {/n case '开始'://点击开始/n clean();// 清空棋盘/n count = 0;//计数器清零/n start = true;// 允许开始/n break;/n case '认输':/n end();//弹出面板/n start = false;//不能再下棋/n break;/n case '人机':/n AI();//执行人机对战方法/n break;/n case '悔棋':/n regret();//弹出面板/n break;/n case '复盘':/n clean();/n repeat();//弹出面板/n break;/n case '存储棋局':/n save();// 存储棋局/n break;/n case '读取棋局':/n clean();/n load();// 读取棋局/n break;/n }/n }/n public void checkwin() {/n //如果以满足胜负条件/n if(win.checkwin(x1, y1)==1) {/n //end();//执行结束游戏方法/n JFrame jf = new JFrame();//创建窗口/n jf.setSize(100,100);//设置窗口大小/n jf.setLocationRelativeTo(null);//居中显示/n //设置流动布局/n jf.setLayout(new FlowLayout());/n JLabel label = new JLabel();/n label.setText('黑棋胜利');/n/n jf.add(label);/n/n jf.setVisible(true);/n }else if(win.checkwin(x1, y1)==-1){/n JFrame jf = new JFrame();//创建窗口/n jf.setSize(100,100);//设置窗口大小/n jf.setLocationRelativeTo(null);//居中显示/n //设置流动布局/n jf.setLayout(new FlowLayout());/n JLabel label = new JLabel();/n label.setText('白棋胜利');/n/n jf.add(label);/n/n jf.setVisible(true);/n }/n }/n public void mouseClicked (MouseEvent e){/n int x = e.getX();// 鼠标点击处获取x、y坐标/n int y = e.getY();/n // 获取落子坐标,此处进行判断让获取的坐标位于棋盘线交点处/n if ((x - x0) % size > size / 2) {/n x1 = (x - x0) / size + 1;/n/n } else if ((x - x0) % size <= size / 2) {/n x1 = (x - x0) / size;/n/n }/n/n if ((y - y0) % size > size / 2) {/n y1 = (y - y0) / size + 1;/n/n } else if ((y - y0) % size <= size / 2) {/n y1 = (y - y0) / size;/n/n }/n //下棋前添加判断条件:是否按了“开始”/n if (start == true) {/n/n // 判断棋子是否会越出棋盘界/n if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) {/n // 判断只有空位置才能下棋/n if (chessArr[y1][x1] == 0) {/n // 加for循环是为了给棋子添加3D效果/n for (int i = 0; i < 50; i++) {/n // count为双数下黑棋,为单数下白棋/n //下完黑棋在数组中存入1,白棋存入-1/n if (count % 2 == 0) {/n color = new Color(5 * i, 5 * i, 5 * i);// 3d效果/n g.setColor(color);// 设置画笔颜色/n g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y1][x1] = 1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)/n/n } else {/n color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);/n g.setColor(color);/n g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y1][x1] = -1;/n/n }/n/n }/n ChessR chess = new ChessR(x1,y1,color);//创建棋子对象存入棋子数值/n chessB[count] = chess;//以count为下标存入棋子对象/n count++;//每下完一颗棋,计数器加1/n checkwin();/n }/n } else {/n System.out.print('超出棋盘边界');/n }/n/n }/n }/n // 添加方法,使用回溯法实现五子棋人机对战/n/n // 输出游戏结束面板/n public void end() {/n //创建窗体/n JFrame jy = new JFrame();/n jy.setSize(1599, 559);/n jy.setLocationRelativeTo(null);/n jy.setDefaultCloseOperation(3);/n //设置流动布局/n jy.setLayout(new FlowLayout());/n //添加标签,载入图片/n JLabel jla = new JLabel(new ImageIcon('E://gccjava//wuziqi//游戏结束.png'));/n //设置标签大小/n jla.setPreferredSize(new Dimension(1599, 559));/n jy.add(jla);/n jy.setVisible(true);/n/n }/n // 悔棋方法/n public void regret() {/n if (count > 0) {//添加判断,有棋子时才能悔棋/n ChessR chessR = chessB[--count];// 取出数组中最后一颗棋子/n int x = chessR.x1;// 取出该棋子对应的x、y值/n int y = chessR.y1;/n chessArr[y][x] = 0;// 清空该棋子对应位置/n chesspanel.paint(g);/n }/n }/n // 复盘方法/n public void repeat() {/n for (int i = 0; i < count; i++) {/n ChessR chess = chessB[i];// 通过循环,正序取出棋子/n // 设置棋子重绘时间间隔/n try {/n Thread.sleep(1000);/n } catch (InterruptedException e) {/n/n e.printStackTrace();/n }/n //顺序双数绘黑棋,单数绘白棋/n if(i%2==0) {/n chessArr[chess.y1][chess.x1] = 1;/n }else {/n chessArr[chess.y1][chess.x1] = -1;/n }/n chesspanel.paint(g);//绘制棋子/n }/n count = 0;//计数器清零/n }/n // 存储棋局方法/n public void save() {/n try {/n FileWriter fw = new FileWriter('棋谱.txt');/n for (int i = 0; i < count; i++) {/n ChessR chess = chessB[i];// 通过循环,正序取出棋子/n fw.write(chess.x1 + ' ' + chess.y1 + ' ' + chess.color.getRGB() + '//n');// 将棋子信息写入文件/n }/n fw.close();/n } catch (IOException e) {/n e.printStackTrace();/n }/n }/n/n // 读取棋局方法/n public void load() {/n try {/n BufferedReader br = new BufferedReader(new FileReader('棋谱.txt'));/n String line;/n while ((line = br.readLine()) != null) {/n String[] chessInfo = line.split(' ');// 将一行棋子信息按空格拆分成数组/n int x = Integer.parseInt(chessInfo[0]);// 取出x、y坐标和颜色RGB值/n int y = Integer.parseInt(chessInfo[1]);/n int rgb = Integer.parseInt(chessInfo[2]);/n Color color = new Color(rgb);// 通过RGB值创建颜色对象/n ChessR chess = new ChessR(x, y, color);// 创建棋子对象/n // 设置棋子绘制时间间隔/n try {/n Thread.sleep(1000);/n } catch (InterruptedException e) {/n e.printStackTrace();/n }/n // 绘制棋子,并将棋子存入数组/n if (count % 2 == 0) {/n chessArr[y][x] = 1;/n } else {/n chessArr[y][x] = -1;/n }/n chessB[count] = chess;/n count++;/n chesspanel.paint(g);/n }/n br.close();/n } catch (IOException e) {/n e.printStackTrace();/n }/n }/n/n}/npackage teachGoBang;/n/nimport java.awt.Color;/n//创建棋子类/npublic class ChessR {/n public int x1,y1;/n public Color color;/n //构造方法初始化参数/n public ChessR(int x1,int y1,Color color) {/n this.x1 = x1;/n this.y1 = y1;/n this.color = color;/n }/n/n}/n/npublic void AI() {/n JFrame jf = new JFrame();//创建窗口/n jf.setSize(200, 200);//设置窗口大小/n jf.setLocationRelativeTo(null);//居中显示/n //设置流动布局/n jf.setLayout(new FlowLayout());/n JButton jb1 = new JButton('先手');/n JButton jb2 = new JButton('后手');/n jf.add(jb1);/n jf.add(jb2);/n jf.setVisible(true);/n jb1.addActionListener(new ActionListener() {//先手/n public void actionPerformed(ActionEvent e) {/n jf.dispose();//关闭窗口/n clean();// 清空棋盘/n count = 0;//计数器清零/n start = true;// 允许开始/n int x = 7,y = 7;//电脑先下中心点/n for(int i=0;i<50;i++) {// 添加动画效果/n color = new Color(5 * i, 5 * i, 5 * i);// 3d效果/n g.setColor(color);// 设置画笔颜色/n g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y][x] = 1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)/n }/n ChessR chess = new ChessR(x,y,color);//创建棋子对象存入棋子数值/n chessB[count] = chess;//以count为下标存入棋子对象/n count++;//每下完一颗棋,计数器加1/n while(true) {// 无限循环/n //人类下一步棋/n while(true) {/n if (start == true) {/n if (chessArr[y1][x1] == 0) {/n for (int i = 0; i < 50; i++) {/n if (count % 2 == 0) {/n color = new Color(5 * i, 5 * i, 5 * i);// 3d效果/n g.setColor(color);// 设置画笔颜色/n g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y1][x1] = 1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)/n } else {/n color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);/n g.setColor(color);/n g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y1][x1] = -1;/n }/n }/n ChessR chess1 = new ChessR(x1,y1,color);/n chessB[count] = chess1;/n count++;/n checkwin();// 判断输赢/n break;/n }/n }/n }/n //电脑下一步棋/n int[] res = new int[2];//存储最优下棋位置/n res = max(chessArr);//调用max方法/n x = res[0];//取出最优下棋位置/n y = res[1];/n for(int i=0;i<50;i++) {// 添加动画效果/n color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);/n g.setColor(color);// 设置画笔颜色/n g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y][x] = -1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)/n }/n ChessR chess2 = new ChessR(x,y,color);// 创建棋子对象/n chessB[count] = chess2;/n count++;// 每下完一颗棋,计数器加1/n checkwin();// 判断输赢/n }/n }/n });/n jb2.addActionListener(new ActionListener() {//后手/n public void actionPerformed(ActionEvent e) {/n jf.dispose();//关闭窗口/n clean();// 清空棋盘/n count = 0;//计数器清零/n start = true;// 允许开始/n while(true) {// 无限循环/n //人类下一步棋/n while(true) {/n if (start == true) {/n if (chessArr[y1][x1] == 0) {/n for (int i = 0; i < 50; i++) {/n if (count % 2 == 0) {/n color = new Color(5 * i, 5 * i, 5 * i);// 3d效果/n g.setColor(color);// 设置画笔颜色/n g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y1][x1] = 1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)/n } else {/n color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);/n g.setColor(color);/n g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y1][x1] = -1;/n }/n }/n ChessR chess1 = new ChessR(x1,y1,color);/n chessB[count] = chess1;/n count++;/n checkwin();// 判断输赢/n break;/n }/n }/n }/n //电脑下一步棋/n int[] res = new int[2];//存储最优下棋位置/n res = max(chessArr);//调用max方法/n x = res[0];//取出最优下棋位置/n y = res[1];/n for(int i=0;i<50;i++) {// 添加动画效果/n color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);/n g.setColor(color);// 设置画笔颜色/n g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);/n chessArr[y][x] = -1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)/n }/n ChessR chess2 = new ChessR(x,y,color);// 创建棋子对象/n chessB[count] = chess2;/n count++;// 每下完一颗棋,计数器加1/n checkwin();// 判断输赢/n }/n }/n });/n }/n public int[] max(int[][] chessArr) {/n int[] res = new int[2];/n // 使用回溯法实现 AI 算法,分析棋盘状态,找到最佳落子位置/n // ... /n return res;/n }/
原文地址: https://www.cveoy.top/t/topic/oRHN 著作权归作者所有。请勿转载和采集!