您好,登錄后才能下訂單哦!
使用Java怎么實現五子棋AI?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
思路:
①五子棋界面的實現
②交互下棋的實現
③重繪
④AI,實現人機對戰
五子棋和簡單AI的實現:
首先將五子棋的界面寫出來。
首先我們寫一個接口類,定義好棋盤的數據(目的是方便修改)。
public interface Config { public static final int X0=50;//左上角起點X值 public static final int Y0=50;//左上角起點Y值 public static final int ROWS=15;//橫向線數 public static final int COLUMNS=15;//縱向線數 public static final int CHESSSIZE=40;//棋子直徑 public static final int SIZE=50;//單元格大小 }
再來寫五子棋的界面。寫界面的方法和畫圖板是一樣的。
public class FiveChessUI extends JFrame implements Config { static FiveChessUI fcUI = new FiveChessUI(); public static void main(String[] args){ fcUI.initUI(); } private int [][] chesses = new int[ROWS][COLUMNS];//創建一個二維數組用來標記棋盤上的位置 /** * 初始化五子棋窗體的方法 */ public void initUI(){ ChessListener listener = new ChessListener(chesses,fcUI); this.setTitle("五子棋v1.0"); this.setSize(900, 800);//設置界面尺寸 this.setResizable(false);//界面不可改變大小 this.setLocationRelativeTo(null);//設置界面居中 this.setDefaultCloseOperation(3);//設置退出進程 BorderLayout bl = new BorderLayout();//設置界面布局為窗體式布局 this.setLayout(bl); JPanel jp = new JPanel(); jp.setPreferredSize(new Dimension(100,0)); this.add(jp,BorderLayout.EAST); String [] name ={"重新開始","黑棋先下","白棋先下","悔棋","人機對戰","人人對戰"}; for(int i=0;i<name.length;i++){//依次給按鈕添加動作監聽,這里用循環可減少代碼 JButton jbu = new JButton(name[i]); jbu.setPreferredSize(new Dimension(95,30)); jp.add(jbu); jbu.addActionListener(listener); } this.setVisible(true);//設置可見 listener.gr = this.getGraphics(); this.addMouseListener(listener);//給界面加上鼠標監聽 } /** * 重寫繪制窗體的方法 */ public void paint(Graphics g){ super.paint(g); //在重繪的同時繪制棋盤 drawChessTable(g); //在重繪的同時繪制棋子 drawChess(g); } public void drawChess(Graphics g){ ImageIcon bai = new ImageIcon("C:\\Users\\Administrator\\Pictures\\五子棋\\baizi.png");//添加白子圖片 ImageIcon hei = new ImageIcon("C:\\Users\\Administrator\\Pictures\\五子棋\\heizi.png");//添加黑子圖片 for(int i=0;i<chesses.length;i++){ for(int j=0;j<chesses.length;j++){ if(chesses[i][j]==1){ g.drawImage(hei.getImage(), X0 + SIZE * i - Config.CHESSSIZE / 2, Y0 + SIZE * j - Config.CHESSSIZE / 2, Config.CHESSSIZE, Config.CHESSSIZE, null); }else if(chesses[i][j]==-1){ g.drawImage(bai.getImage(), X0 + SIZE * i - Config.CHESSSIZE / 2, Y0 + SIZE * j - Config.CHESSSIZE / 2, Config.CHESSSIZE, Config.CHESSSIZE, null); } } } } public void drawChessTable(Graphics g){ //添加背景圖片 ImageIcon img= new ImageIcon("C:\\Users\\Administrator\\Pictures\\chesstable.jpg"); g.drawImage(img.getImage(), 0, 0, 800, 800,null); //畫棋盤橫線 for(int i=0;i<ROWS;i++){ g.drawLine(X0, Y0+i*SIZE, X0+(COLUMNS-1)*SIZE, Y0+i*SIZE); } //畫棋盤豎線 for(int j=0;j<Config.COLUMNS;j++){ g.drawLine(X0+j*SIZE, Y0, X0+j*SIZE,Y0+(ROWS-1)*SIZE ); } } }
監聽器類代碼如下:
import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.HashMap; import javax.swing.ImageIcon; import javax.swing.JOptionPane; public class ChessListener extends MouseAdapter implements Config, ActionListener { public Graphics gr; private int count = 0;// 計數器 private int[][] chesses;// 創建一個二維數組用來存放棋子的坐標 private String name; private int t, r; private int cl = 0, AI=2; private int i, j, x, y, z = 0, w = 0,zz=0,ww=0; private FiveChessUI fc;// 聲明FiveChessUI類的一個對象 private int setX[] = new int[ROWS * COLUMNS];// 創建一維數組setX[] private int setY[] = new int[ROWS * COLUMNS];// 創建一維數組setY[] private int[][] chessValue = new int[ROWS][COLUMNS]; private int index = 0;// 創建數組的下標 HashMap<String, Integer> hm = new HashMap<String, Integer>();//創建權值表 public ChessListener(int[][] chesses, FiveChessUI fc) { this.fc = fc; this.chesses = chesses; //權值設置,這個需要自己慢慢調,小編寫的一般,AI有時會出問題 hm.put("1", 20); hm.put("11", 60); hm.put("111", 200); hm.put("1111", 1000); hm.put("-1", 20); hm.put("-1-1", 60); hm.put("-1-1-1", 200); hm.put("-1-1-1-1", 1000); hm.put("1-1", 20); hm.put("11-1", 30); hm.put("111-1", 80); hm.put("1111-1", 1000); hm.put("-11", 20); hm.put("-111", 30); hm.put("-1111", 80); hm.put("-11111", 1000); hm.put("1-1", 20); hm.put("-1-11", 30); hm.put("-1-1-11", 80); hm.put("-1-1-1-11", 1000); hm.put("1-1", 20); hm.put("1-1-1", 30); hm.put("1-1-1-1", 80); hm.put("1-1-1-1-1", 1000); } public void mouseReleased(MouseEvent e) { // 得到鼠標事件發生的時候光標的位置 int x1 = e.getX(); int y1 = e.getY(); // 按行遍歷棋盤,坐標(i,j) for (j = 0; j < ROWS; j++) { for (i = 0; i < ROWS; i++) {// 得到交叉點的坐標 x = X0 + SIZE * i;// 橫坐標 y = Y0 + SIZE * j;// 縱坐標 // 與圓心的誤差為size/3 if (x1 > x - SIZE * 5 / 12 && x1 < x + SIZE * 5 / 12 && y1 > y - SIZE * 5 / 12 && y1 < y + SIZE * 5 / 12) { ImageIcon bai = new ImageIcon("C:\\Users\\Administrator\\Pictures\\baizi5.png"); ImageIcon hei = new ImageIcon("C:\\Users\\Administrator\\Pictures\\heizi4.png"); if (AI == 0) { // 人人對戰 if (chesses[i][j] == 0) {// 如果選的位置沒有棋子 if (count == 0) { chesses[i][j] = 1;// 如果是黑子,就為1 count++; gr.drawImage(hei.getImage(), X0 + SIZE * i - CHESSSIZE / 2, Y0 + SIZE * j - CHESSSIZE / 2, CHESSSIZE, CHESSSIZE, null); cl = 0; } else { chesses[i][j] = -1;// 如果是白子就為-1 count--; gr.drawImage(bai.getImage(), X0 + SIZE * i - CHESSSIZE / 2, Y0 + SIZE * j - CHESSSIZE / 2, CHESSSIZE, CHESSSIZE, null); cl = 1; } setX[index] = i;// 將下的棋子的橫坐標存入setX[] setY[index] = j;// 將下的棋子的縱坐標存入setY[] index++;// 存入一個坐標,一維數組角標加1 // 以交叉點畫圓 checkRow(i, j); z = 1; w = 1; return; } } if (AI == 1) { // 人機對戰 if (chesses[i][j] == 0) {// 如果選的位置沒有棋子 if (count == 0) { // 玩家下棋 chesses[i][j] = 1;// 如果是黑子,就為1 // count++; gr.drawImage(hei.getImage(), X0 + SIZE * i - CHESSSIZE / 2, Y0 + SIZE * j - CHESSSIZE / 2, CHESSSIZE, CHESSSIZE, null); cl = 0; count++; checkRow(i, j);//判斷是否勝利 setX[index] = i;// 將下的棋子的橫坐標存入setX[] setY[index] = j;// 將下的棋子的縱坐標存入setY[] index++;// 存入一個坐標,一維數組角標加1 } this.AI(); if (count == 1) { // 輸出所有點的權值 for (int j = 0; j < chessValue.length; j++) { for (int i = 0; i < chessValue.length; i++) { System.out.print(chessValue[i][j] + " "); } System.out.println(); } // 電腦下棋 // 篩選出chessValue最大值的交點坐標, 該坐標電腦下棋 for (int j = 0; j < chessValue.length; j++) { for (int i = 0; i < chessValue.length; i++) { if (chessValue[0][0] < chessValue[i][j]) { chessValue[0][0] = chessValue[i][j]; t = i; r = j; } } } count--; chesses[t][r] = -1; gr.drawImage(bai.getImage(), X0 + SIZE * t - CHESSSIZE / 2, Y0 + SIZE * r - CHESSSIZE / 2, CHESSSIZE, CHESSSIZE, null); cl = 1; setX[index] = r;// 將下的棋子的橫坐標存入setX[] setY[index] = t;// 將下的棋子的縱坐標存入setY[] index++;// 存入一個坐標,一維數組角標加1 checkRow(t, r);//判斷是否勝利 zz = 1;// ww = 1; // 清空value for (int i = 0; i < chessValue.length; i++) { for (int j = 0; j < chessValue.length; j++) { chessValue[i][j] = 0; } } } } } } } } } // 判斷勝利的條件 public int checkRow(int x, int y) { int count1 = 0, count2 = 0, count3 = 0, count4 = 0;// 定義4個棋子計數器,分別計數水平,豎直、斜向右下、斜向左下 for (int i = x + 1; i < chesses.length; i++) { if (chesses[i][y] == chesses[x][y]) { count1++; } else break; } for (int i = x; i >= 0; i--) { if (chesses[i][y] == chesses[x][y]) { count1++; } else break; } for (int j = y + 1; j < chesses.length; j++) { if (chesses[x][j] == chesses[x][y]) { count2++; } else break; } for (int j = y; j >= 0; j--) { if (chesses[x][y] == chesses[x][j]) { count2++; } else break; } for (int i = x + 1, j = y + 1; i < chesses.length && j < chesses.length; i++, j++) { if (chesses[i][j] == chesses[x][y]) { count3++; } else break; } for (int i = x, j = y; i >= 0 && j >= 0; i--, j--) { if (chesses[i][j] == chesses[x][y]) { count3++; } else break; } for (int i = x, j = y; i < chesses.length && j >= 0; i++, j--) { if (chesses[i][j] == chesses[x][y]) { count4++; } else break; } for (int i = x - 1, j = y + 1; i >= 0 && j < chesses.length; i--, j++) { if (chesses[i][j] == chesses[x][y]) { count4++; } else break; } if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5) { count = 0; if (cl == 0) { JOptionPane.showMessageDialog(null, "黑棋贏!"); for (int i = 0; i < chesses.length; i++) { for (int j = 0; j < chesses.length; j++) { chesses[i][j] = 0; } } fc.repaint(); } if (cl == 1) { JOptionPane.showMessageDialog(null, "白棋贏!"); for (int i = 0; i < chesses.length; i++) { for (int j = 0; j < chesses.length; j++) { chesses[i][j] = 0; } } fc.repaint(); } } return count; } public void actionPerformed(ActionEvent e) { name = e.getActionCommand(); if ("重新開始".equals(name)) { count = 0; z = 0; w = 0; for (int i = 0; i < chesses.length; i++) { for (int j = 0; j < chesses.length; j++) { chesses[i][j] = 0; } } fc.repaint(); } if ("白棋先下".equals(name)) { if (z == 0) { count = 1; z = 1; } } if ("黑棋先下".equals(name)) { if (w == 0) { count = 0; w = 1; } } if ("悔棋".equals(name)) { this.huiqi(); } if ("人機對戰".equals(name)) { if(w==0){ AI = 1; ww=1; } } if ("人人對戰".equals(name)) { if(z==0){ AI = 0; } } } public void huiqi() { if (index >= 0) { index--; if (index < 0) { index = 0; } x = setX[index]; y = setY[index]; if (chesses[x][y] == 1) { chesses[x][y] = 0; count = 0; } if (chesses[x][y] == -1) { chesses[x][y] = 0; count = 1; } if(chesses[t][r]==-1){ chesses[t][r]=0; count=1; } fc.repaint(); } } public void AI() { for (int i = 0; i < chesses.length; i++) { for (int j = 0; j < chesses.length; j++) { if (chesses[i][j] == 0) {// 判斷當前位置是否有棋子 // 定義兩個變量分別保存棋局,顏色 String code = ""; int color = 0; // 向右 for (int k = i + 1; k < chesses.length; k++) { if (chesses[k][j] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[k][j];// 保存顏色 code += chesses[k][j];// 保存棋局 } else if (chesses[k][j] == color) {// 右邊第二,第三同顏色棋子 code += chesses[k][j];// 保存棋局 } else { // 右邊不同顏色 code += chesses[k][j]; break; } } } // 根據code取出hm對應的權值 Integer value = hm.get(code); if (value != null) { chessValue[i][j] += value; } // 向左方向 code = ""; color = 0; for (int k = i - 1; k >= 0; k--) { if (chesses[k][j] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[k][j];// 保存顏色 code += chesses[k][j];// 保存棋局 } else if (chesses[k][j] == color) {// 右邊第二,第三同顏色棋子 code += chesses[k][j];// 保存棋局 } else { // 右邊不同顏色 code += chesses[k][j]; break; } } } // 根據code取出hm對應的權值 Integer value2 = hm.get(code); if (value2 != null) { chessValue[i][j] += value2; } // 向上方向 code = ""; color = 0; for (int k = j - 1; k >= 0; k--) { if (chesses[i][k] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[i][k];// 保存顏色 code += chesses[i][k];// 保存棋局 } else if (chesses[i][k] == color) {// 右邊第二,第三同顏色棋子 code += chesses[i][k];// 保存棋局 } else { // 右邊不同顏色 code += chesses[i][k]; break; } } } // 根據code取出hm對應的權值 Integer value3 = hm.get(code); if (value3 != null) { chessValue[i][j] += value3; } // 向下方向 code = ""; color = 0; for (int k = j + 1; k < chesses.length; k++) { if (chesses[i][k] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[i][k];// 保存顏色 code += chesses[i][k];// 保存棋局 } else if (chesses[i][k] == color) {// 右邊第二,第三同顏色棋子 code += chesses[i][k];// 保存棋局 } else { // 右邊不同顏色 code += chesses[i][k]; break; } } } // 根據code取出hm對應的權值 Integer value4 = hm.get(code); if (value4 != null) { chessValue[i][j] += value4; } // 右上方向 code = ""; color = 0; for (int k = j + 1, l = i - 1; l >= 0 && k < chesses.length; l--, k++) { if (chesses[l][k] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[l][k];// 保存顏色 code += chesses[l][k];// 保存棋局 } else if (chesses[l][k] == color) {// 右邊第二,第三同顏色棋子 code += chesses[l][k];// 保存棋局 } else { // 右邊不同顏色 code += chesses[l][k]; break; } } } // 根據code取出hm對應的權值 Integer value6 = hm.get(code); if (value6 != null) { chessValue[i][j] += value6; } // 左下方向 code = ""; color = 0; for (int k = i + 1, l = j - 1; l >= 0 && k < chesses.length; k++, l--) { if (chesses[k][l] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[k][l];// 保存顏色 code += chesses[k][l];// 保存棋局 } else if (chesses[k][l] == color) {// 右邊第二,第三同顏色棋子 code += chesses[k][l];// 保存棋局 } else { // 右邊不同顏色 code += chesses[k][l]; break; } } } // 根據code取出hm對應的權值 Integer value7 = hm.get(code); if (value7 != null) { chessValue[i][j] += value7; } // 右下方向 code = ""; color = 0; for (int k = i - 1, l = j - 1; l >= 0 && k >= 0; l--, k--) { if (chesses[k][l] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[k][l];// 保存顏色 code += chesses[k][l];// 保存棋局 } else if (chesses[k][l] == color) {// 右邊第二,第三同顏色棋子 code += chesses[k][l];// 保存棋局 } else { // 右邊不同顏色 code += chesses[k][l]; break; } } } // 根據code取出hm對應的權值 Integer value8 = hm.get(code); if (value8 != null) { chessValue[i][j] += value8; } // 左上方向 code = ""; color = 0; for (int k = i + 1, l = j + 1; k < chesses.length && l < chesses.length; l++, k++) { if (chesses[k][l] == 0) { break; } else { if (color == 0) {// 右邊第一顆棋子 color = chesses[k][l];// 保存顏色 code += chesses[k][l];// 保存棋局 } else if (chesses[k][l] == color) {// 右邊第二,第三同顏色棋子 code += chesses[k][l];// 保存棋局 } else { // 右邊不同顏色 code += chesses[k][l]; break; } } } // 根據code取出hm對應的權值 Integer value5 = hm.get(code); if (value5 != null) { chessValue[i][j] += value5; } } } } } }
看完上述內容,你們掌握使用Java怎么實現五子棋AI的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。