FiveChess的优化第二篇

优化FiveChess的一些心得记录,包含框架布局、算法改进和代码优化。

Posted by LJJ on November 5, 2018

小记demo

第二天/第三天

吐槽一下,这是不够专注和有点累的两天。

  • 简化了五子连线的判断方法

就不贴上原先的代码了,直接看到我们的改变:

public boolean CheckWin(int xIndex, int yIndex) {
        int max = 0;
        int tempXIndex = xIndex;
        int tempYIndex = yIndex;
        
        int countConect;
        boolean flag;
        // 三维数组记录横向,纵向,左斜,右斜的移动
        int[][][] dir = new int[][][] {
                // 横向
                { { -1, 0 }, { 1, 0 } },
                // 竖着
                { { 0, -1 }, { 0, 1 } },
                // 左斜
                { { -1, -1 }, { 1, 1 } },
                // 右斜
                { { 1, -1 }, { -1, 1 } } };
 
        // 两层循环遍历了落子点以2为半径的周围棋子
        for (int i = 0; i < 4; i++) {
            countConect = 1;
            for (int j = 0; j < 2; j++) {
                flag = true;
                // while循环会一直往一个方向遍历
                while (flag) {
                    tempXIndex = tempXIndex + dir[i][j][0];
                    tempYIndex = tempYIndex + dir[i][j][1];
 
                    // 判断一个方向上的三颗棋子颜色
                    if (tempXIndex >= 0 && tempXIndex <= 15 && tempYIndex >= 0 && tempYIndex <= 15) {
                        if ((chessArray[tempXIndex][tempYIndex] == chessArray[xIndex][yIndex])) 
                            countConect++;
                        else
                            flag = false;
                    }else{
                        flag = false;
                    }
                    
                }
                tempXIndex = xIndex;
                tempYIndex = yIndex;
            }
            // 当满足五子相连条件
            if (countConect >= 5) {
                max = 1;
                break;
            } else
                max = 0;
        }
        if (max == 1)
            return true;
        else
            return false;
    }

这段代码从优秀的博主那借鉴更改的,原先的判断方法非常冗杂。上面代码主要是优化在用三位数组将遍历棋子的上下左右斜等过程完全覆盖到了。通过while循环对一个方向进行遍历,加以判断语句,很方便地实现了五颗棋子连线的判断。

  • 利用权值算法实现AI落子

下面的代码相当于构建了一个完整储存所有落子可能的哈希权值表:

HashMap<String, Integer> hm = new HashMap<String, Integer>();
// 给各种下棋点位赋上权值生成完整的哈希表
		hm.put("-1", 20);
		hm.put("-1-1", 400);
		hm.put("-1-1-1", 420);
		hm.put("-1-1-1-1", 3000);
		hm.put("-11", 4); 
		hm.put("-1-11", 40);
		hm.put("-1-1-11", 400);
		hm.put("-1-1-1-11", 10000);
		hm.put("1-1-1-1-1", 10000);
		hm.put("1", 8);
		hm.put("11", 80);
		hm.put("111", 1000);
		hm.put("1111", 5000);
		hm.put("1111-1", 5000);
		hm.put("1111-1-1", 5000);
		hm.put("1-1", 6);
		hm.put("11-1", 60);
		hm.put("111-1", 600);
		hm.put("-11-1", 5);
		hm.put("-111-1", 5);
		hm.put("1-1-11", 5);
		hm.put("1-11", 5);

再下棋的时候直接根据权值大小的判断进行下棋即可。在五子棋算法中也有很多可以扩展的地方,但由于时间原因这里就不深入了,博弈树算法也是可以的。

  • 修正了悔棋后棋子仍然会导致产生锯齿的bug

边缘锯齿的产生我们前面也讲过了,但悔棋功能使用的repaint()还是会造成边缘锯齿的产生。于是,将其修改为:

if (e.getActionCommand().equals("悔棋")) {
			
			if (chooseModule==2) {
				chessArray[xx][yy] = 0;
				chessColor = 0;
				// 重绘画面
				j.update(g);
			}else {
				// 弹出人人对战不可悔棋
				winFrame(0);
	    	}
		
    	}

这里的update()可以代替repaint()完成。但是会产生画面闪烁.

总结

总的来说,做的不是很满意,因为时间比较紧张,很多东西没有扩展修改出来。五子棋的算法还是存在很大的的问题,我下赢了几次,说明算法还不够成熟,但也只能先做到这了。需要开始后面的学习了。

源码放在了我的github
仅供学习,觉得有用的话star一下吧。