繼續以前的那個五子棋程序 修復了一些已知的小Bughtml
這裏是以前的五子棋程序 原文連接java
修復了一些算法缺陷 本次增長了AI算法
能夠人機對戰 也能夠Ai對Ai看戲
本次Ai算法屬於初級算法 稍微用點小套路仍是能夠幹掉他的
之後會更新高級算法算法
本次還對程序進行了模塊化 拆分紅了幾個文件緩存
下面請看源碼關聯架構
遊戲入口類app
package main.game; /** 遊戲入口類 **/ public class GameApp { /** 遊戲入口 */ public static void main(String[] args) { Gobang game = new Gobang(); //Player Vs Ai Player p1 = new Player("玩家",'彩');//就這麼特殊 就用彩棋 熱性! Player p2 = new AiPlayer("機器人",'白'); //Player Vs Player //Player p1 = new Player("玩家",'黑'); //Player p2 = new Player("玩家2",'白'); //Ai Vs Ai //Player p1 = new AiPlayer("玩家",'黑'); //Player p2 = new AiPlayer("機器人",'白'); game.createGame(p1,p2); game.start(); } }
遊戲核心控制類
這裏控制遊戲核心算法 例如遊戲的勝負算法dom
package main.game; /** * 控制檯五子棋遊戲 */ public class Gobang { private boolean gameover = false; //15*15棋盤 private char[][] table = new char[16][16]; //兩個玩家 private Player p1,p2; //回合 private int huihe = 0; public Player getP1() { return p1; } public Player getP2() { return p2; } public void createGame(Player p1, Player p2){ this.p1=p1; this.p2=p2; } public char[][] getTable() {return table;} /** 展現棋局 **/ private void show(){ int xx =0; System.out.println(" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "); for(char[] cs :table){ System.out.print(" "+xx+(xx>9?"":" ")+" "); for(char c : cs){ if(c==0) System.out.print("·"); System.out.print(c+" "); } System.out.println(); xx++; } } /** 獲取下一個走棋的 **/ private Player getPlayer(){ //p1先走 if (huihe==0) return p1; if (huihe%2!=0) return p2; return p1; } /** 判斷是否獲勝 **/ private boolean isWin(int x,int y,char c){ /* x 和 y 表明座標 * xx :x方向須要增長的值 * yy :y方向須要增長的值 * * 例如xx = -1 yy= -1 * 表明須要獲取(x-1,y-1)的棋子顏色 * * xx = 1 yy= 1 * 表明須要獲取(x+1,y+1)的棋子顏色 * * */ int xx = 0,yy=0; for (int i =1 ;i<9 ;i++ ){ switch (i){ case 1: xx=-1;yy=-1; break; case 2: xx=-1;yy=1; break; case 3: xx=-1;yy=0; break; case 4: xx = 1;yy = -1; break; case 5: xx = 1;yy = 1; break; case 6: xx = 1 ;yy = 0; break; case 7: xx = 0;yy = -1; break; case 8: xx = 0;yy = 1; break; } int n = ishas(x,y,xx,yy,0,c)+ishas(x,y,-xx,-yy,0,c); if(n>=4)return true; } return false; } /** * 檢測是否有棋子 * @param x x座標 * @param y y座標 * @param xx x方向 * @param yy y方向 * @param size 緩存 * @param c 顏色 * @return 權重 */ private int ishas(int x,int y,int xx,int yy,int size ,char c){ if((x==0&&xx==-1)|| (x==15&&xx==1) || (y==0&&yy==-1) || (y== 15&&yy==1)) return size; if(table[x+xx][y+yy] == c){ return ishas(x+xx,y+yy,xx,yy,size+1,c); } return size; } /** 下棋 **/ public boolean put(int x,int y,Player p){ if (table[x][y]==Character.MIN_VALUE) { table[x][y] = p.getColor(); if(isWin(x,y,p.color)){ gameover = true; System.out.println(p.username+"("+p.color+")贏得了勝利"); } return true; } return false; } /** 遊戲運行 **/ public void start(){ //本回合下子選手 Player p = null; while (!gameover){ //棋盤已滿 if(huihe/2+1 == 129)break; if(p==null)p=getPlayer(); System.out.println("第"+(huihe/2+1)+"回合,下子方:"+p.getUsername()+"("+p.getColor()+")"); System.out.println("請輸入你要下的位置(空格隔開) 例如:10 5"); int ps = p.run(this); //下子錯誤 if (ps == 0)continue; //遊戲結束 用戶輸入了exit else if( ps == 1)break; show(); p=null; huihe++; } System.out.println("遊戲結束"); } }
玩家類
這裏是玩家使用控制檯下棋算法ide
package main.game; import java.util.Scanner; public /** 玩家類 **/ class Player{ String username; char color; Scanner scan; public Player(String username, char color) { this.username = username; this.color = color; System.out.println(username+"攜帶"+color+"顏色的棋子加入遊戲"); scan = new Scanner(System.in); } public String getUsername() { return username; } public char getColor() { return color; } /** 玩家須要獲控制檯輸入的值 **/ public int run(Gobang app) { //下棋失敗從新開始本回合 String[] strArr ; String in = scan.nextLine().trim(); if ("exit".equals(in)) return 1; try { strArr = in.split(" "); if (!app.put(Integer.parseInt(strArr[0]), Integer.parseInt(strArr[1]), this)) return 0; }catch (Exception e){ return 0; } return -1; } }
Ai機器人算法類
這裏有ai機器人下棋算法思路
本算髮用點套路仍是能夠很輕鬆的幹掉Ai的
本算法屬於初級算法 後期會更新高級的模塊化
package main.game; import java.util.*; public /** 機器人 **/ class AiPlayer extends Player { private Random r = new Random(); private List<Piece> pieces = new LinkedList<>(); private char p2 ; private char[][] table; /** 建立Ai機器人 **/ public AiPlayer(String username, char color) { super(username, color); } @Override /** Ai機器人的算法 **/ public int run(Gobang app){ if (p2 == Character.MIN_VALUE || app.getP1()==this){ this.p2 = app.getP2().color; }else{ this.p2= app.getP1().color; } Piece args = up(app); System.out.println("智能下棋("+args.x+","+args.y+")"); try { if (!app.put(args.x, args.y, this)) return 0; }catch (Exception e){ return 0; } return -1; } /** 測試用,隨緣下棋 **/ private Piece test(){ for (int i =0;i<3;i++){ int x = r.nextInt(3)+6; int y = r.nextInt(3)+6; if(table[x][y] == Character.MIN_VALUE){ return new Piece(x,y,0,this.color); } } while (true){ int x = r.nextInt(16); int y = r.nextInt(16); if(table[x][y] == Character.MIN_VALUE){ return new Piece(x,y,0,this.color); } } } /** 智能算法下棋 **/ private Piece up(Gobang app){ pieces.clear(); table = app.getTable(); for (int x = 0;x <16; x++){ for (int y = 0;y <16; y++){ //判斷空餘地方獲勝概率 if (table[x][y] == Character.MIN_VALUE){ //判斷本身權重 sub(x,y,this.color); //判斷對手權重 sub(x,y,p2); } } } return get(); } /** 計算權重 **/ private void sub(int x,int y,char c){ char m = this.color; int xx = 0,yy=0; int num = 0 ; for (int i =0 ;i<8 ;i++ ){ switch (i){ case 0: xx = 0;yy = 1; break; case 1: xx=-1;yy=-1; break; case 2: xx=-1;yy=1; break; case 3: xx=-1;yy=0; break; case 4: xx = 1;yy = -1; break; case 5: xx = 1;yy = 1; break; case 6: xx = 1 ;yy = 0; break; case 7: xx = 0;yy = -1; break; } if(c == this.color){ //查本身下子權重 int a = ishas(x, y, xx, yy, 0,this.color,p2)+ishas(x, y, -xx, -yy, 0,this.color,p2); if (a>num)num=a; m = this.color; // num += ishas(x, y, xx, yy, 0,this.color,p2)+ishas(x, y, -xx, -yy, 0,this.color,p2); }else{ //檢測對手威脅權重 int a = ishas(x, y, xx, yy, 0,p2,this.color)+ishas(x, y, -xx, -yy, 0,p2,this.color); if (a>num)num=a; m=p2; // num +=ishas(x, y, xx, yy, 0,p2,this.color)+ishas(x, y, -xx, -yy, 0,p2,this.color); } } pieces.add(new Piece(x,y,num,m)); } /** 檢測周圍有沒有棋子 **/ private Piece get(){ // 挑選權重最大的 pieces.sort(new Comparator<Piece>() { @Override public int compare(Piece o1, Piece o2) { return o1.info< o2 .info ? 1:(o1.info == o2.info ? 0: -1); } }); //隨緣棋子 System.out.println(pieces); if(pieces.size()==0 || pieces.get(0).info == 0)return test(); int max = pieces.get(0).info; Piece index = pieces.get(0); for(Piece ps : pieces ){ if(ps.info<max){ return index; } index = ps; } return index ; } /** 檢測棋子 **/ private int ishas(int x,int y,int xx,int yy,int size ,char c,char c2){ if((x==0&&xx==-1)|| (x==15&&xx==1) || (y==0&&yy==-1) || (y== 15&&yy==1)) return size; if(table[x+xx][y+yy] == c){ return ishas(x+xx,y+yy,xx,yy,size+1,c,c2); }else if(table[x+xx][y+yy] == c2){ return size>3 ? size+2:size-1; } return size; } /**判斷危機**/ }
棋子類 這裏沒啥可用的 就是寫Ai算法時候調用方便測試
package main.game; /** Ai算法棋子類 **/ public class Piece { //座標 int x; int y; char color; //權重 int info; public Piece(int x, int y, int info,char color) { this.x = x; this.y = y; this.info = info; this.color = color; } @Override public String toString() { return "Piece"+color+"{" + "x=" + x + ", y=" + y + ", info=" + info + '}'; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 0 黑 白 白 黑 黑 黑 黑 白 白 黑 白 黑 白 黑 白 黑 1 黑 白 黑 黑 白 白 白 黑 黑 白 黑 黑 黑 白 白 白 2 黑 黑 白 白 白 黑 白 白 白 黑 黑 白 黑 白 黑 白 3 白 白 黑 黑 白 黑 白 黑 白 黑 白 白 黑 黑 黑 白 4 黑 黑 白 白 白 黑 黑 白 白 白 白 黑 白 黑 白 黑 5 黑 白 黑 白 黑 黑 白 黑 黑 白 黑 黑 白 黑 白 白 6 黑 白 白 黑 黑 白 白 白 黑 白 黑 黑 白 白 黑 黑 7 白 黑 白 白 黑 白 黑 黑 黑 白 黑 白 黑 白 白 黑 8 黑 白 黑 白 黑 白 黑 黑 黑 黑 白 白 白 黑 黑 黑 9 白 黑 黑 白 白 白 白 黑 白 黑 白 黑 黑 白 白 白 10 白 黑 白 黑 黑 黑 白 白 白 白 黑 白 白 白 黑 黑 11 白 黑 白 黑 黑 黑 黑 白 黑 黑 白 白 白 白 黑 黑 12 黑 白 黑 白 白 白 黑 白 白 白 黑 黑 黑 白 白 黑 13 黑 白 黑 白 黑 白 白 白 白 黑 黑 黑 白 黑 黑 黑 14 黑 黑 黑 黑 白 白 黑 黑 黑 白 白 白 黑 白 白 白 15 白 白 白 黑 黑 黑 白 白 黑 白 黑 白 黑 白 黑 黑 遊戲結束