⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gobangai.java

📁 java写的五子棋
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.Math;
/**
 * @author  yeeku.H.lee kongyeeku@163.com
 * @version  1.0
 * <br>Copyright (C), 2005-2008, yeeku.H.Lee
 * <br>This program is protected by copyright laws.
 * <br>Program Name:
 * <br>Date: 
 */

class GobangAI
{
	//每个棋局要找出COUNT个得分最高的空格
	protected static int COUNT = 6;
	//考虑到DEPTH步棋
	protected static int DEPTH = 5;
	//定义棋盘的大小
	protected static int BOARD_SIZE = 15;
	//定义一个二维数组来充当棋盘,其中0是空位,1是电脑,2是玩家
	protected int[][] table = new int [BOARD_SIZE][BOARD_SIZE];
	protected static final int NOTHING = 0;
	protected static final int COMPUTER = 1;
	protected static final int PLAYER = 2;
	//定义一个二维数组,暂存棋盘情况(以防求AI的时候改变了table)
	protected int[][] tableAI = new int [BOARD_SIZE][BOARD_SIZE];
	//定义空位、玩家用的棋和电脑的棋
	protected String[] stone = new String[]{"╋","■","●"};
	//记录玩家和电脑上一步下的棋的行数
	protected int[] iLast = new int[]{0,0,0};
	//记录玩家和电脑上一步下的棋的列数
	protected int[] jLast = new int[]{0,0,0};
	//初始化单个方向的常量
	protected final int DIR = 8;                        //方向的总数
	protected final int UP = 0;
	protected final int UP_RIGHT = 1;
	protected final int RIGHT = 2;
	protected final int DOWN_RIGHT = 3;
	protected final int DOWN = 4;
	protected final int DOWN_LEFT = 5;
	protected final int LEFT = 6;
	protected final int UP_LEFT = 7;
	//初始化空位的单个方向的情况(这是下棋前的情况)
	int[][][][] situation = new int[3][BOARD_SIZE][BOARD_SIZE][DIR];
    protected final int LIFE_ZERO = 0;             //邻近为空格
	protected final int LIFE_ONE = 1;              //活一
	protected final int LIFE_TWO = 2;              //活二
	protected final int LIFE_THREE = 3;            //活三
	protected final int DEAD_ZERO = 10;            //邻近有对方的棋或边界
	protected final int DEAD_ONE = 11;             //堵一
	protected final int DEAD_TWO = 12;             //堵二
	protected final int DEAD_THREE = 13;           //堵三
	protected final int FINISH_BANG = 100;         //连珠
	//初始化空位的四个方向(即在一条直线上)的评分(这是下棋后的情况)
	int[][][][] markLink = new int[3][BOARD_SIZE][BOARD_SIZE][DIR];
	protected final int LINK_DEAD = 0;                  //邻近都被堵
	protected final int LINK_DEAD_ONE = 1;              //死一(其中一边为空)
	protected final int LINK_LIFE_ONE = 2;              //活一(两边都空)
	protected final int LINK_DEAD_TWO = 3;              //死二(其中一边为空)
	protected final int LINK_LIFE_TWO = 4;              //活二(两边都空)
	protected final int LINK_DEAD_THREE = 5;            //死三(其中一边为空)
	protected final int LINK_LIFE_THREE = 6;            //活三(两边都空)
	protected final int LINK_DEAD_FOUR = 7;			  //死四(其中一边为空)
	protected final int LINK_LIFE_FOUR = 8;             //活四(两边都空)
	protected final int LINK_BANG = 9;                  //连珠
	//初始化空位的总评分(这是下棋后的情况)
	int[][][] mark = new int[3][BOARD_SIZE][BOARD_SIZE];   //每个空位总评分
	protected final int MARK_BANG = 2000;	              //连珠
	protected final int MARK_L4_D4D4_D4L3 = 512;   //活4或者是双死4或者是死4活3
	protected final int MARK_L3L3 = 256;	              //双活3
	protected final int MARK_D3L3 = 128;                //死3活3
	protected final int MARK_D4 = 64;	                  //死4
	protected final int MARK_L3 = 32;                   //单活3
	protected final int MARK_L2L2 = 16;                 //双活2
	protected final int MARK_D3 = 8;                    //死3
	protected final int MARK_L2 = 4;                    //单活2
	protected final int MARK_D2 = 2;                    //死2
	//电脑的进攻性WEIGHT。即求利益的时候,加权平均值的权数(范围0到10)
	protected final int WEIGHT = 6;
	//对于最高分点记录点maxPoints,其第二个索引中3个值的含义
	protected final int I_MAX = 0;
	protected final int J_MAX = 1;
	protected final int PROFIT_MAX = 2;

/*=======================以下是实现五子棋的方法============================*/
	/**
	 *在控制台输出棋盘的方法
	 */
	public void printBoard()
	{
		System.out.print("  ");
		for (int i = 0; i < BOARD_SIZE ; i++)
		{
			System.out.print(i);
			if (i < 10)
			{
				System.out.print(" ");
			}
		}
		System.out.println();

		//打印每个数组元素
		for (int i = 0 ; i < BOARD_SIZE ; i++)
		{
			System.out.print(i);
			if (i < 10)
			{
				System.out.print(" ");
			}
			for (int j = 0 ; j < BOARD_SIZE ; j++)
			{
				System.out.print(stone[table[i][j]]);
			}
			System.out.print("\n");
		}
	}

	/**
	 *用户输入棋子的坐标,并作记录
	 */
	public void inputStone()
	{
		int i = 0;
		int j = 0;
		//判断是否成功输入的标识符
		boolean ifInput = false;
		BufferedReader br = new BufferedReader
			(new InputStreamReader(System.in));
		String inputStr = null;
		inputAgain:
		while (! ifInput)
		{
			try
			{
				System.out.println("请输入您下棋的座标,应以x,y的格式:");
				inputStr = br.readLine();
				//将用户输入的字符串以逗号(,)作为分隔符,分隔成2个字符串
				String[] posStrArr = inputStr.split(",");
				//将2个字符串转换成用户下棋的座标
				i = Integer.parseInt(posStrArr[0]);
				j = Integer.parseInt(posStrArr[1]);
			}
			catch (Exception e)
			{
				System.out.println("输入格式有误!需要从新输入!");
			}
			//判断坐标是否超出范围
			if (! ifIn(i,j))
			{
				System.out.println("坐标超出范围!需要从新输入!");
				continue inputAgain;
			}
			//判断坐标是否为空位
			if (table[i][j] != NOTHING)
			{
				System.out.println("该位置已经有棋!需要从新输入!");
				continue inputAgain;
			}
			//当输入正常时,记录输入的坐标
			table[i][j] = PLAYER;
			iLast[PLAYER] = i;
			jLast[PLAYER] = j;
			ifInput = true;
		}
	}

	/**
	 *电脑随机生成棋子的坐标,并作记录
	 */
	public void randomStone()
	{
		//判断是否成功输入的标识符
		boolean ifInput = false;
		while (! ifInput)
		{
			//以下随机生成电脑下棋的坐标
			double temp;
			temp = Math.random();
			int i = (int) (temp * BOARD_SIZE);
			temp = Math.random();
			int j = (int) (temp * BOARD_SIZE);
			//判断坐标是否符合要求,并作记录
			if (table[i][j] == NOTHING && ifIn(i,j))
			{
				iLast[COMPUTER] = i;
				jLast[COMPUTER] = j;
				table[i][j] = COMPUTER;
				ifInput = true;
			}
		}
		System.out.println("电脑下棋以后");
	}

	/**
	 *电脑的人工智能方法产生坐标(要调用到后半部分的AI方法),并作记录
	 */
	public void getAIStone()
	{
		int player = COMPUTER;                      //当前角色为电脑
		int[] solution = GobangAImain();
		int i = solution[0];
		int j = solution[1];
		iLast[player] = i;
		jLast[player] = j;
		table[i][j] = COMPUTER;
		System.out.println("电脑下棋在:" + i +"," + j);
	}

	/**
	 *判断棋局胜负
	 *@param player 代表下棋的人
	 *@return 返回棋局情况。若结束,返回true
	 */
	public boolean ifFinish(int player)
	{
		int i = iLast[player];
		int j = jLast[player];
		//检查纵向的路是否五子连珠
		for (int iFirst = i-4; iFirst <= i; iFirst ++)
		{
			if (ifIn(iFirst, j) && ifIn(iFirst + 4, j)) //待检查的坐标都在范围内
			{
				boolean ifLink = true;       //先假设它连珠
				for (int k = 0; k < 5; k ++)
				{
					if (table[iFirst + k][j] != player)
					//若有一个位置没有该角色的棋
					{
						ifLink = false;      //取消连珠的判断
					}
				}
				if (ifLink)                  //找到连珠
				{
					return true;
				}
			}
		}
		//检查横向的路是否五子连珠
		for (int jFirst = j-4; jFirst <= j; jFirst ++)
		{
			if (ifIn(i, jFirst) && ifIn(i, jFirst + 4)) //待检查的坐标都在范围内
			{
				boolean ifLink = true;       //先假设它连珠
				for (int k = 0; k < 5; k ++)
				{
					if (table[i][jFirst + k] != player)
					//若有一个位置没有该角色的棋
					{
						ifLink = false;      //取消连珠的判断
					}
				}
				if (ifLink)                  //找到连珠
				{
					return true;
				}
			}
		}
		//检查捺向的路是否五子连珠(左上到右下)
		for (int iFirst = i - 4, jFirst = j - 4; iFirst <= i; iFirst ++, jFirst ++)
		{
			if (ifIn(iFirst, jFirst) && ifIn(iFirst + 4, jFirst + 4))
				//待检查的坐标都在范围内
			{
				boolean ifLink = true;       //先假设它连珠
				for (int k = 0; k < 5; k ++)
				{
					if (table[iFirst + k][jFirst + k] != player)
					//若有一个位置没有该角色的棋
					{
						ifLink = false;      //取消连珠的判断
					}
				}
				if (ifLink)                  //找到连珠
				{
					return true;
				}
			}
		}
		//检查撇向的路是否五子连珠(右上到左下)
		for (int iFirst = i - 4, jFirst = j + 4; iFirst <= i; iFirst ++, jFirst --)
		{
			if (ifIn(iFirst, jFirst) && ifIn(iFirst + 4, jFirst - 4))
				//待检查的坐标都在范围内
			{
				boolean ifLink = true;       //先假设它连珠
				for (int k = 0; k < 5; k ++)
				{
					if (table[iFirst + k][jFirst - k] != player)
					//若有一个位置没有该角色的棋
					{
						ifLink = false;      //取消连珠的判断
					}
				}
				if (ifLink)                  //找到连珠
				{
					return true;
				}
			}
		}
		return false;
	}

	/**
	 *判断坐标是否在棋盘内
	 *@param i 棋的横坐标
	 *@param j 棋的纵坐标
	 *@return 若在棋盘内,返回true;否则,返回false
	 */
	protected boolean ifIn(int i, int j)
	{
		if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE)
		{
			return true;
		}
		else return false;
	}

	/**
	 *调换角色为对方
	 *@param player 原角色
	 *@return 返回对方
	 */
	protected int antiPlayer(int player)
	{
		if (player == COMPUTER)
		{
			return PLAYER;
		}
		else return COMPUTER;
	}

//	/**
//	 *主方法,实现五子棋的入口
//	 */
//    public static void main(String[] args)throws Exception
//    {
//        GobangAI gb = new GobangAI();
//		gb.printBoard();
//		//gb.testMethod();                           //测试
//		int player = PLAYER;                 //玩家先下棋
//		while (true)
//		{
//			if (player == PLAYER)
//			{
//				gb.inputStone();
//			}
//			else
//			{
//				//gb.randomStone();
//				gb.getAIStone();
//			}
//			gb.printBoard();
//			if (gb.ifFinish(player))         //有人赢了,结束
//			{
//				if (player == PLAYER)
//					System.out.println("恭喜!你赢了!");
//				else
//					System.out.println("很遗憾!电脑赢了!");
//				break;                       //跳出循环
//			}
//			else
//				player = gb.antiPlayer(player); //切换角色,轮流下棋
//		}
//    }

/*==========================以下建造人工智能==========================*/

/*=============================1.私有方法=============================*/
	/**
	 *上下移动一个格
	 *@param i 该格的行数
	 *@param dir 移动的方向
	 *@return 返回新的行数
	 */
	protected int iMove(int i,int dir)
	{
		switch (dir)
		{
		case UP:
		case UP_RIGHT:
		case UP_LEFT:
			i--;                          //向上
		break;
		case DOWN:
		case DOWN_RIGHT:
		case DOWN_LEFT:
			i++;                          //向下
		break;
		default:
		}
		return i;
	}

	/**
	 *左右移动一个格
	 *@param j 该格的列数
	 *@param dir 移动的方向

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -