转载请注明出处: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。欢迎博友的加入。