![610607aea8ef0b8852f9c2fccbd32850.png](https://i-blog.csdnimg.cn/blog_migrate/5489b5f0c3283324194ee0cb5c454b2e.png)
![3d28b8887276f9262343cab29888ba76.png](https://i-blog.csdnimg.cn/blog_migrate/d7749541c3b86b84d0d0560fdebfad59.jpeg)
Java五子棋小游戏,想必大佬们以前都做过,接下来我有说的不好的地方,欢迎大佬拍砖。
首先,我们先来看看我们要实现的功能,
1.按下“开始游戏”按钮后,我们才可以下棋,同时选定“人机对战”或“玩家对战”的下拉框被锁定,直到“重新开始”按钮按下。
2.按下悔棋按钮,实现:如果是“玩家对战”,悔一个棋子。如果是“人机对战”,悔两个棋子。
3.按下“认输”,弹出提示框显示执手的一方认输,另一方获胜,同时不能在界面上进行任何下棋的操作了,只能通过悔棋来进查看之前的步数。按下”重新开始“按钮后,则锁定解除。
4.黑白交替下子,且当某一方五子相连时,判定胜负,同时不能再下棋了。直至按下“重新开始”按钮。
4.实现人机对战的AI算法。
5.实现线上的玩家的网络对战(正在开发中)。
首先,要想下五子棋,我们得先有一个界面,同时为了让我们可以重绘,我们让该界面继承JFrame。(主函数大家也可以放到其他类里)。
/*这是设置界面的代码,可以看到为了让按钮排列有序,我们设置其为边框布局。
接下来我们要做啥?做过画图板的小伙伴肯定知道。没错就是加监听。(悔棋和重新开始的监听我们等等再说,来点不一样的)同时我们把画布和下拉框一起传过去。
listenner_4
接下来,我们要画一个棋盘,不然咋下棋啊?为了保证一开始棋盘就出现,我们把画棋盘的方法写到重绘里。我们设置的格子边长为40
public
同时我们参照之前画图板的方法在重绘里把之前数组里存的棋子一一画出
for (int k1 = 0; k1 < white.size(); k1++) {
shape_4 shape1 = white.get(k1);
if (white != null) {
g.setColor(Color.white);
shape1.draw(g);
}
}
for (int k = 0; k < black.size(); k++) {
shape_4 shape = black.get(k);
if (black != null) {
g.setColor(Color.black);
shape.draw(g);
}
}
}
这样,我们就画出了一个棋盘,接下来我们来实现黑白子交替下棋。我们不能保证鼠标每次点击都正在让棋子画在交叉点上,所以我们需要一些小小的计算坐标,考验数学功底的时候到啦!
int x1 = e.getX();
int y1 = e.getY();
// if the place is true,
if (x1 <= 600 && y1 <= 600) {//保证下子在格子内
// 计算出最近的坐标
if ((x1 % 40) < 20) {
x1 = (x1 - (x1 % 40));
} else {
x1 = x1 + (40 - (x1 % 40));
}
if ((y1 % 40) < 20) {
y1 = (y1 - (y1 % 40));
} else {
y1 = y1 + (40 - (y1 % 40));
}
// set oval heart
x1 = x1 - 35 / 2;
y1 = y1 - 35 / 2;
同时我们要保证下棋的位置是空的,直接暴力遍历棋子是否重复。方法如下
int
我们还必须保证下棋的时候已经开始游戏且胜负未定。我用int win=0来表示胜负情况,
int off=0表示是否开始游戏了。
if (off == 1 && win == 0) {......
利用black。size()是否与white。size()相等判断是否黑棋下。相等说明现在是黑方下,设颜色为黑。
if (black.size() == white.size()) {
g.setColor(Color.black);
每次落白子后都判断一次该白子的周围情况,方法名叫judgewhite,看是否五白子相连,诺五子相连,则win为judgewhite返回值1.
win = judgment_4.judgewhite(x1, y1);
落黑棋就调判断黑棋的方法
win = judgment_4.judgeblack(x1, y1);
同时我们实现“人机对战”和“玩家对战”两种模式,设置一个全局变量choose来控制。choose为1且胜负未分时,执行人机对战,否则执行玩家对战。
另外注意每次下完棋后把下棋的情况存入对应的队列。
该方法的代码如下。
if
人机对战的方法pvAI()如下;
if
如此一来我们就实现了五子棋的最基本的功能了,可以下棋了。
但是我们添加的按钮有啥用呢?不能成摆设啊,于是我们必须给按钮作用啊。看
public
还有悔棋和重新开始按钮的监听呢?这么这里没有啊?别急,为了方便,我们直接在在wuziqi_4上设监听。
思路简单,如果我们下拉框上是人机对战,那么我们一次悔两个子,也就是remove掉black和white队列里最后一个棋子,玩家对战就用black.size()) == (white.size()判断谁执手每次悔一个。
代码如下:
regret
那重新开始呢?更简单啦!直接重开一个窗口并关掉自己本身的窗口就可以啦,懒得调那么多参数啦!
restart
如此一来,我们就实现了五子棋的下棋和各按钮的作用啦!接下来就是判断输赢啦
为了便利,我们建一个裁判类judgement_4.并将队列传入。
思路简单,如果我们下了一个黑棋,我们就遍历黑棋的队列,看有没有可以五子相连的情况。代码如下。只部分写了左右的情况啦。如果判定五子相连返回1;否则返回0.
//为了思路的清晰,这里用了几个if,也可以直接用循环来控制,减少代码量。
这样一来我们的五子棋就简单的实现啦,AI机器人的设计思路有好多种,我们简单讲下最简单的权值法吧。
HashMap<String, Integer> hm = new HashMap<String, Integer>();//建一个hashmap。
兴建一个AI_4类,将对列传入,然后用一个数组int i[][]存每个空位的权值。
ps.小编的数据结构功底太差,可以优化的地方好多的
int i[][] = new int[650][650];
public void Integer() {
// set the integer
for (x = (40 - 35 / 2); x <= 600; x += 40) {
for (y = (40 - 35 / 2); y <= 600; y += 40) {
if (check(x, y) != 0) {//诺不是空位,不做任何操作
} else {
i[x][y] = setAIinteger(x, y);
i[x][y]+=setHNinteger(x, y);
}
}
}
//找到所有坐标中权值最大的点
int p = 0;
for (x = (40 - 35 / 2); x <= 600; x += 40) {
for (y = (40 - 35 / 2); y <= 600; y += 40) {
if (i[x][y] >= p) {
p = i[x][y];
x1 = x;
y1 = y; }}}
我们在设权值时设两次权值,一次为setAIinteger(x, y),另一次为setHNinteger(x, y)。表示该点AI下的价值和人下的价值,如果该点人下的价值大,AI也是要抢下的。
方法实施也好理解,我们设置几种情况来设权值,大家简单看看,毕竟以后还有更高级的方法,这个可看可不看。
public
我们再设两个方法可以在监听器里获得最优点的坐标,这样我们就实现了人机对战啦!
public
最后的最后,有同学好奇shape_4是啥,小编还是稍微讲讲吧
/*shape_4类用来画棋子和存棋子的
这个五子棋还有好多可以优化的地方,比如做一个接口来设置一些共有的东西,避免过多的传参等。控制胜负和开局用boolean量来控制啥的。
真的最后了,虽然肯定没人看......还是要求大家拍个砖啥的。欢迎大家加我微信1395349613.