Java五子棋小遊戲(控制檯純Ai算法)

Java五子棋小遊戲(控制檯純Ai算法)

繼續以前的那個五子棋程序 修復了一些已知的小Bughtml

這裏是以前的五子棋程序 原文連接java

修復了一些算法缺陷 本次增長了AI算法
能夠人機對戰 也能夠Ai對Ai看戲
本次Ai算法屬於初級算法 稍微用點小套路仍是能夠幹掉他的
之後會更新高級算法算法

本次還對程序進行了模塊化 拆分紅了幾個文件緩存

下面請看源碼關聯架構

程序架構圖

下面請看源代碼

GameApp.Java

遊戲入口類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();
    }
}

Gobang.java

遊戲核心控制類
這裏控制遊戲核心算法 例如遊戲的勝負算法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("遊戲結束");

    }
}

Player.java

玩家類
這裏是玩家使用控制檯下棋算法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;

    }


}

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 白 白 白 黑 黑 黑 白 白 黑 白 黑 白 黑 白 黑 黑 
遊戲結束
相關文章
相關標籤/搜索