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 白 白 白 黑 黑 黑 白 白 黑 白 黑 白 黑 白 黑 黑
游戲結束