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

📄 ai.java

📁 一款J2ME作得手机游戏
💻 JAVA
字号:
package org.javagarden.j2me.fivelink.client;


/**
 * 游戏的人式智能处理类。
 * @author Turbo Chen
 * @created 2005-4-5
 */
public class AI
{

    /**
     * 找到最佳下棋点。
     * 基本思路是, 先计算每个点的权值,在权值最高的位置下棋
     * @author Turbo Chen
     * @created 2005-5-11
     */ 
    public static Location findBestChessLocation( Player currentPlayer, FiveLinkModel model)
    {
        //权值数组
        int[][] power = new int[FiveLinkModel.BOARD_SIZE][FiveLinkModel.BOARD_SIZE];
        for ( short i = 0; i < FiveLinkModel.BOARD_SIZE; i++ )
        {
            for ( short j = 0; j < FiveLinkModel.BOARD_SIZE; j++ )
            {
                // 当已有子时将该点的权值设为-1
                if ( model.getChess()[i][j] !=0 )
                {
                    power[i][j] = -1; 
                }
                // 否则计算该点权值
                else
                {
                    power[i][j] = (short) calcPower(i, j, currentPlayer,model);
                }
            }
        }
        //计算完所有点的权值后, 再找出其中权值最大的点
        Location bestLoc = calcMaximumPowerLocation(power);
        power = null;
        return bestLoc;

    }

    /**
     * 找出权值最大点.
     * @param power
     * @return
     */
    private static Location calcMaximumPowerLocation(int[][] power)
    {
        int max = 0;
        short x = 0, y = 0;
        for ( short i = 0; i < FiveLinkModel.BOARD_SIZE; i++ )
        {
            for ( short j = 0; j < FiveLinkModel.BOARD_SIZE; j++ )
            {
                if ( power[i][j] > max )
                {
                    x = i;
                    y = j;
                    max = power[i][j];
                }
            }
        }
        return new Location(x,y);
    }

    /**
     * 检查m,n点的权值.<p>
     * 思路是, 假定在m,n位置下棋后,计算4个方向经过该点,同色相连的棋子数量, 不同的数量有不同的
     * 权值,将四个方向上权值相加即为该点的权值.计算完后恢复该点的状态.
     * @param m
     * @param n
     * @param currentPlayer
     * @param model
     * @return
     */
    private static int calcPower(short m, short n,  Player currentPlayer, FiveLinkModel model)
    {
        int p = 0;
        
        //找AI自己的取胜点,
        int p1 = 1000;
        //找AI自己的三个相连的点
        int p3 = 60;
        //找AI自己的两个相连的点
        int p5 = 20;
        //找AI自己的相连的点
        int p7 = 10;

        //找对手的取胜点
        int p2 = 85;
        //找对手的三个相连的点
        int p4 = 45;
        //找对手的两个相连的点
        int p6 = 15;
        //找对方的相连的点
        int p8 = 5;
        
        short[] arrLinks = new short[4];
        //如果当是我方下棋, 判断我方所持棋子的颜色, 在该点预下一子, 然后进行后续计算.
        if ( currentPlayer.getChessType()==Player.BLACK )
        {
            //我方是黑子
            model.setChess(m,n,1);
        }else
        {
            //我方是白子
            model.setChess(m,n,-1);
        }
        
        // 计算4个方向上同色相连棋子的数量.
        arrLinks = calcLinkCount(m,n,model.getChess());

        //如果m,n是中心点, 将权值加1
        if ( m == FiveLinkModel.BOARD_SIZE/2 && n == FiveLinkModel.BOARD_SIZE/2 )
        {
            p += 1;
        }
        //计算我方在该点四个方向的权值
        for ( short i = 0; i < 4; i++ )
        {
            if ( Math.abs(arrLinks[i]) == 5 )
            {
                p += p1;
            }
            if ( arrLinks[i] == 4 )
            {
                p += p3;
            }
            if ( arrLinks[i] == 3 )
            {
                p += p5;
            }
            if ( arrLinks[i] == 2 )
            {
                p += p7;
            }
        }
        //如果当是对手方下棋, 判断对方所持棋子的颜色, 在该点预下一子, 然后进行后续计算.
        if ( currentPlayer.getChessType()==1 )
        {
            //如果对方是白子, 
            model.setChess(m,n,-1);
        }else
        {
            //如果对方是黑子,
            model.setChess(m,n,1);
        }

        arrLinks = calcLinkCount(m,n,model.getChess());        
        //计算对手在该点四个方向的权值
        for ( short i = 0; i < 4; i++ )
        {
            if ( Math.abs(arrLinks[i]) == 5 )
            {
                p += p2;
            }
            if ( arrLinks[i] == 4 )
            {
                p += p4;
            }
            if ( arrLinks[i] == 3 )
            {
                p += p6;
            }
            if ( arrLinks[i] == 2 )
            {
                p += p8;
            }
        }
        //计算完后恢复该点的原来状态.
        model.setChess(m,n,0);
        arrLinks = null;
        return p;
    }

	/**
	 * 判断是否平局.
	 * @param arrchessboard
	 * @return
	 */ 
	public static boolean isTie(short[][] arrchessboard)
	{
		//当所有位置都有子时为平局
		for (short i=0;i<FiveLinkModel.BOARD_SIZE;i++)
		{
			for (short j=0;j<FiveLinkModel.BOARD_SIZE;j++)
			{
				if (arrchessboard[i][j] == 0)
					return false;
			}
		}
		return true;
	}

	/**
	 * 计算4个方向相连棋子的个数
	 * @param m
	 * @param n
	 * @param arrchessboard
	 * @return 返回一个4元素的数据,分别代表(m,n)点上四个方向听相连子的个数.
	 */
	private static short[] calcLinkCount(short m,short n, short[][] arrchessboard)
	{
	    short[] counts = new short[4];

	    //---------------------------------------
	    //检查是否无子可下(当flag=2时表示无子可下)
		short flag = 0;
		//连子个数
		short num = 1;

		//检查正东方向
		short x = (short)(m+1);
		int y = n+1;
		//不超出棋格
		for(;x < FiveLinkModel.BOARD_SIZE;)
		{
			//如果前方的棋子与m,n点不同则跳出循环
			if (arrchessboard[x][n] == arrchessboard[m][n])
			{
				num++;
				x++;
			}
			else
			{
				break;
			}
		}
		//正东方向超出棋格
		if (x==FiveLinkModel.BOARD_SIZE)
		{
			flag++;
		}
		else
		{
			//正东方向有别的子不可再下
			if(arrchessboard[x][n] != 0)
			{
				flag++;
			}
		}

		//检查正西方向
        x = (short)(m-1);
		for (;x >= 0;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[x][n] == arrchessboard[m][n])
			{
				num++;
				x--;
			}
			else
			{
				break;
			}
		}
		//正西方向超出棋格
		if (x == -1)
		{
			flag++;
		}
		else
		{
			//正西方向有别的子不可再下
			if(arrchessboard[x][n] != 0)
			{
				flag++;
			}
		}


		if (flag == 2)
		{
			counts[0] = (short)-num;
		}
		else
		{
			if (flag == 1 && num == 3 )
			{
				//连子数为3时有一边不能下就不是活三
			    counts[0] = (short)-num;
			}
			else
			{
				counts[0] = num;
			}
		}

		//---------------------------------------
		//检查是否无子可下(当flag=2时表示无子可下)
		flag = 0;
		//连子个数
		num = 1;
		//检查正南方向
		x = (short)(n+1);
		for(;x<FiveLinkModel.BOARD_SIZE;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[m][x] == arrchessboard[m][n])
			{
				num++;
				x++;
			}
			else
			{
				break;
			}
		}
		//正南方向超出棋格
		if (x==FiveLinkModel.BOARD_SIZE)
		{
			flag++;
		}
		else
		{
			//正南方向有别的子不可在下
			if(arrchessboard[m][x] != 0)
			{
				flag++;
			}
		}

		//检查正北方向
		x = (short) (n-1);
		for(;x >= 0;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[m][x] == arrchessboard[m][n])
			{
				num++;
				x--;
			}
			else
			{
				break;
			}
		}
		//正北方向超出棋格
		if (x == -1)
		{
			flag++;
		}
		else
		{
			//正北方向有别的子不可在下
			if(arrchessboard[m][x] != 0)
			{
				flag++;
			}
		}

		if (flag == 2)
		{
			counts[1] = (short)-num;
		}
		else
		{
			if (flag == 1 && num == 3 )
			{
				//连子数为3时有一边不能下就不是活三
				counts[1] = (short)-num;
			}
			else
			{
				counts[1] = num;
			}
		}
		
		//--------------------------------------
		//检查是否无子可下(当flag=2时表示无子可下)
		flag = 0;
		//连子个数
		num = 1;
		
		//检查东南方向
		x = (short)(m+1);
		//不超出棋格
		for(;x < FiveLinkModel.BOARD_SIZE && y < FiveLinkModel.BOARD_SIZE;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[x][y] == arrchessboard[m][n])
			{
				num++;
				x++;
				y++;
			}
			else
			{
				break;
			}
		}
		//东南方向超出棋格
		if (x==FiveLinkModel.BOARD_SIZE || y==FiveLinkModel.BOARD_SIZE)
		{
			flag++;
		}
		else
		{
			//东南方向有别的子不可在下
			if(arrchessboard[x][y] != 0)
			{
				flag++;
			}
		}

		//检查西北方向
		x = (short)(m-1);
		y = n-1;
		//不超出棋格
		for(;x >= 0 && y >= 0;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[x][y] == arrchessboard[m][n])
			{
				num++;
				x--;
				y--;
			}
			else
			{
				break;
			}
		}
		//西北方向超出棋格
		if (x == -1 || y == -1)
		{
			flag++;
		}
		else
		{
			//西北方向有别的子不可在下
			if(arrchessboard[x][y] != 0)
			{
				flag++;
			}
		}

		if (flag == 2)
		{
			counts[2] = (short)-num;
		}
		else
		{
			if (flag == 1 && num == 3 )
			{
				//连子数为3时有一边不能下就不是活三
				counts[2] = (short)-num;
			}
			else
			{
				counts[2] = num;
			}
		}
		
		//------------------------------------
		//检查是否无子可下(当flag=2时表示无子可下)
		flag = 0;
		//连子个数
		num = 1;

		//检查西南方向
		x = (short)(m-1);
		y = n+1;
		//不超出棋格
		for(;x >= 0 && y < FiveLinkModel.BOARD_SIZE;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[x][y] == arrchessboard[m][n])
			{
				num++;
				x--;
				y++;
			}
			else
			{
				break;
			}
		}
		//西南方向超出棋格
		if (x == -1 || y == FiveLinkModel.BOARD_SIZE)
		{
			flag++;
		}
		else
		{
			//西南方向有别的子不可在下
			if(arrchessboard[x][y] != 0)
			{
				flag++;
			}
		}

		//检查东北方向(
		x = (short)(m+1);
		y = n-1;
		//不超出棋格
		for(;x < FiveLinkModel.BOARD_SIZE && y >= 0;)
		{
			//前方的棋子与m,n点不同时跳出循环
			if (arrchessboard[x][y] == arrchessboard[m][n])
			{
				num++;
				x++;
				y--;
			}
			else
			{
				break;
			}
		}
		//东北方向超出棋格
		if (x == FiveLinkModel.BOARD_SIZE || y == -1)
		{
			flag++;
		}
		else
		{
			//东北方向有别的子不可在下
			if(arrchessboard[x][y] != 0)
			{
				flag++;
			}
		}

		if (flag == 2)
		{
			counts[3] = (short)-num;
		}
		else
		{
			if (flag == 1 && num == 3 )
			{
				//连子数为3时有一边不能下就不是活三
			    counts[3] = (short)-num;
			}
			else
			{
			    counts[3] = num;
			}
		}
	
		// 返回四个方向的相连子的个数。
		return counts;
	}
    
    
}

⌨️ 快捷键说明

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