Java五子棋小游戏(控制台纯Ai算法)
继续之前的那个五子棋程序 修复了一些已知的小Bug
这里是之前的五子棋程序 原文链接
修复了一些算法缺陷 本次增加了AI算法
可以人机对战 也可以Ai对Ai看戏
本次Ai算法属于初级算法 稍微用点小套路还是可以干掉他的
以后会更新高级算法
本次还对程序进行了模块化 拆分成了几个文件
下面请看源码关联
下面请看源代码
GameApp.Java
游戏入口类
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(); } }
Gobang.java
游戏核心控制类
这里控制游戏核心算法 例如游戏的胜负算法
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("游戏结束"); } }
Player.java
玩家类
这里是玩家使用控制台下棋算法
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; } }
AiPlayer.java
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; } /**判断危机**/ }
Piece.java
棋子类 这里没啥可用的 就是写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 + '}'; } }
Ai vs Ai的话可能会出现这样的场景
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 白 白 白 黑 黑 黑 白 白 黑 白 黑 白 黑 白 黑 黑 游戏结束
来源:https://www.cnblogs.com/xiaoshuai123/p/12189631.html