android开发五子棋人机对战

转载请注明出处:http://blog.csdn.net/sw950729/article/details/51954959
本文出自:马云飞的博客

昨天我们讲了双人对战的算法,今天我们来说说人机对战,因为代码比较多,比较复杂,我在这边大致说一下算法问题。当然,有不懂的地方可以提出来,我会一一解答。因为下午还有事情要做,我这边就不画图了。
我就用1代表白子(玩家),2代表黑子(电脑),0代表空子了。
电脑的判断顺序肯定是4,3,2,1.
当然这边有2种情况就是11011和1101的情况,我把他分别放出来了。这种情况算成5和成4的情况,不能按普通的2点相连来算。
电脑判断顺序:
1.checkBlackTwoTwo(BlackPoint)
出现电脑22022的时候,他肯定下中间直接成5点,而不会优先赌你的子。
2.checkWhiteTwoTwo(WhitePoint)
白子快成5的时候(11011),电脑下在中间。
3.checkBlackFourInLine(BlackPoint)
电脑冲5的时候需要判断左边,右边,左上,右下,是否属于在屏幕内。这边我把代码贴出来。后面所有的判断是差不多的。

 private boolean checkBlackFourInLine(ArrayList<Point> point) {
        for (Point p : point) {
            int x = p.x;
            int y = p.y;
            boolean checkHorizontal = checkBlackFourHorizontalInLine(x, y, point);
            if (checkHorizontal) {
                return true;
            }
            boolean checkVertical = checkBlackFourVerticalInLine(x, y, point);
            if (checkVertical) {
                return true;
            }
            boolean checkLeftDiagonal = checkBlackFourLeftInLine(x, y, point);
            if (checkLeftDiagonal) {
                return true;
            }
            boolean checkRightDiagonal = checkBlackFourRightInLine(x, y, point);
            if (checkRightDiagonal) {
                return true;
            }
        }
        return false;
    }

这里我也就放一个横向的,其他的改变x,,y的坐标即可。

 int count = 1;
        for (int i = 1; i < 4; i++) {
            if (point.contains(new Point(x - i, y))) {
                count++;
            } else {
                break;
            }
        }
        if (count == 4) {
            if (x - 4 < 0) {
                if (!BlackPoint.contains(new Point(x + 1, y)) && !WhitePoint.contains(new Point(x + 1, y))) {
                    BlackPoint.add(new Point(x + 1, y));
                    return true;
                }
            } else if (x + 1 > MAX_LINE - 1) {
                if (!BlackPoint.contains(new Point(x - 4, y)) && !WhitePoint.contains(new Point(x - 4, y))) {
                    BlackPoint.add(new Point(x - 4, y));
                    return true;
                }
            } else if (!BlackPoint.contains(new Point(x - 4, y)) && !BlackPoint.contains(new Point(x + 1, y))) {
                if (!WhitePoint.contains(new Point(x - 4, y)) && !WhitePoint.contains(new Point(x + 1, y))) {
                    BlackPoint.add(Math.random() > 0.5 ? new Point(x - 4, y) : new Point(x + 1, y));
                    return true;
                } else if (WhitePoint.contains(new Point(x - 4, y)) && !WhitePoint.contains(new Point(x + 1, y))) {
                    BlackPoint.add(new Point(x + 1, y));
                    return true;
                } else if (WhitePoint.contains(new Point(x + 1, y)) && !WhitePoint.contains(new Point(x - 4, y))) {
                    BlackPoint.add(new Point(x - 4, y));
                    return true;
                }
            }
        }
        return false;

注意,某些时候会出现白子覆盖黑子,或者黑子没有下的情况,那么这个该怎么解决。
问题:白子覆盖黑子,黑子覆盖黑子,黑子落在屏幕外面。
解决方案:每次都需要判断这个点是否有黑子和白子。没有则可以落子。
落在屏幕外面的情况你也是需要判断的。
我这边的方法:

(count == 4) {
            if (x - 4 < 0) {
                if (!BlackPoint.contains(new Point(x + 1, y)) && !WhitePoint.contains(new Point(x + 1, y))) {
                    BlackPoint.add(new Point(x + 1, y));
                    return true;
                }
            } else if (x + 1 > MAX_LINE - 1) {
                if (!BlackPoint.contains(new Point(x - 4, y)) && !WhitePoint.contains(new Point(x - 4, y))) {
                    BlackPoint.add(new Point(x - 4, y));
                    return true;
                }
            }

如果x-4<0,落在右边,如果x+1>max_line-1,则落在左边。
4.checkFourInLine(WhitePoint)
5.checkBlackTwoOne(BlackPoint)【这就是上面我所说的2202的情况】
6.checkWhiteTwoOne(WhitePoint)
后面注意了,这边都是冲4或者冲5的,所以黑子优先判断(即:黑子先攻后守)。而后面是白子3连的情况,这里需要进行先守后攻了,不然白子变4个的时候就守不住了。
7.checkThreeInLine(WhitePoint)
8.checkBlackThreeInLine(BlackPoint)
两子相连的情况,可以忽略,毕竟没有成3,不然很容易被人说,你这个电脑除了堵还会干啥?
9.checkBlackTwoInLine(BlackPoint)
10.checkTwoInLine(WhitePoint)
重点来了:
1.如果白子两两不相连,黑子也两两不相连,白子落完,黑子怎么走?
我这边是遍历整个棋盘,优先落在黑子左边,然后是上、右、下。
这边我为了方面你们理解,贴上代码:

 private boolean checkOneBlackLeft(ArrayList<Point> point) {
        for (Point p : point) {
            int x = p.x;
            int y = p.y;
            if (!WhitePoint.contains(new Point(x - 1, y)) && !BlackPoint.contains(new Point(x - 1, y))) {
                BlackPoint.add(new Point(x - 1, y));
                return true;
            }
        }
        return false;

这边好像还要判断下x-1不小于0.我给忘了- - 至于上,右,下,改坐标就可以了。
那么最后一种情况,遍历了所有棋盘,都没子可落。相当于黑子被白子给包围了。那么,你在遍历下棋盘,哪里空着就放哪。代码如下:

 private boolean NoPieceConnect() {
        for (int x = 0; x < 15; x++) {
            for (int y = 0; y < 15; y++) {
                if (!WhitePoint.contains(new Point(x, y)) && !BlackPoint.contains(new Point(x, y))) {
                    BlackPoint.add(new Point(x, y));
                    return true;
                }
            }
        }
        return false;
    }

这样一个人机五子棋就解决了。不过不知道你们发现没有,白子落下一个子的时候,黑子放哪?
下面是我的想法,上下左右随机落一个点,如果白子在最边上,那么黑子落在最中间。

if (WhitePoint.size() == 1) {
            for (Point p : WhitePoint) {
                int x = p.x;
                int y = p.y;
                if (x == 0 || y == 0 || x == MAX_LINE - 1 || y == MAX_LINE - 1) {
                    BlackPoint.add(new Point(MAX_LINE / 2, MAX_LINE / 2));
                } else if (x == MAX_LINE - 1 && y == 0) {
                    BlackPoint.add(Math.random() > 0.5 ? new Point(x - 1, y) : new Point(x, y + 1));
                } else if (x == 0 && y == MAX_LINE - 1) {
                    BlackPoint.add(Math.random() > 0.5 ? new Point(0, y - 1) : new Point(x + 1, y));
                } else if (Math.random() > 0.5) {
                    BlackPoint.add(Math.random() > 0.5 ? new Point(x + 1, y) : new Point(x - 1, y));
                } else {
                    BlackPoint.add(Math.random() > 0.5 ? new Point(x, y + 1) : new Point(x, y - 1));
                }
            }

这样。五子棋的人机对战其实就解决了。因为我还需要添一些功能,以内背景素材的,现在还没解决。等我把这个demo整理完了,我会附上demo。好了。重申一遍,有疑问可以提出来,如果我这边真的有问题,我会修改我的代码进行进一步的完善。
我的android交流群:232748032。欢迎博友的加入。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值