五子棋监听器实现

五子棋的监听器实现
1.下棋的实现
我们玩五子棋最基本的实现的功能就是你往棋盘上面点一下,就会在相应的地方下一个棋子。我们想要实现这个功能就一定要给这个画板提供一个鼠标监听器,所以我们的五子棋监听器就要继承鼠标监听器。我们之前也写过有关鼠标监听器的,这里就不再赘述。当鼠标点击一个点的时候就获取到一个坐标的值,我们就在最近的交叉处画出一个圆,也就是我们的棋子。我们也就直接可以在释放鼠标的函数中完成这个过程。

我们重写MouseRealese方法,当实现了这个操作的时候就要记下坐标的xy值,然后找到最近的交叉处,这个过程怎么实现。咱们可以整个棋盘进行遍历,我们的允许误差是三分之棋盘格子大小。也就是说在这个交叉处的方圆三分之棋盘格子的地方点到的时候,这个交叉处就可以画上一个棋子。我们下棋的时候当然是下了一个黑棋之后就一定要下一个白棋。这个我们可以定义一个参数来指示一下当前该下黑棋还是该下白棋。Count当它是1的时候下白棋,当它是0的时候下黑棋。
for (int j = 0; j < config.ROWS; j++) {
for (int i = 0; i < config.columns; i++) {
int x = config.SIZE * i + config.x0;
int y = config.SIZE * j + config.y0;

			if (x1 > x - config.SIZE / 3 && x1 < x + config.SIZE / 3 && y1 > y - config.SIZE / 3
					&& y1 < y + config.SIZE / 3 && cheeses[i][j] == 0) {

				if (count == 0) {
					cheeses[i][j] = 1;
					g.setColor(Color.black);
					g.fillOval(x - config.CHESS_SIZE / 2, y - config.CHESS_SIZE / 2, config.CHESS_SIZE,
							config.CHESS_SIZE);
					count++;}
				
			else{
						cheeses[i][j] = -1;
						g.setColor(Color.white);
						g.fillOval(x - config.CHESS_SIZE / 2, y - config.CHESS_SIZE / 2, config.CHESS_SIZE,
								config.CHESS_SIZE);
						count--;
					}
		}
	}

这样我们就可以实现下一个黑棋,下一个白棋。
2.一系列按钮的实现
我们已经添加了“人机对战”“人人对战”“悔棋”“重新开始”四个按钮,“人机对战”由于需要涉及到具体的权值算法,放到下个博客上讲。当我们点击“悔棋”的时候就需要抹掉刚刚下的最后一步棋,并且需要将count恢复到上一步,也就是需要把棋子的颜色也恢复到上一步的棋子颜色。当然还有最重要的是添加行为监听器,当点击“悔棋”这个按钮的时候就要进行这一系列的操作。那么问题又回来了,我们只知道如何画图像,好像没有学过如何擦除图像。我们忽略掉了之前的一个步骤,我们为了使我们画的图像不管怎么变都不会消失而进行了重绘的过程,也就是运用链表将所有的棋子都存储起来,点过悔棋按钮之后就从这个链表中移除刚刚存进去的这个棋子,并进行重绘一次,这样就相当于移除了这枚棋子。
if (button.getText().equals(“悔棋”)) {
list.remove(list.size() - 1);
jfr.repaint();

		if (count == 1)
			count--;
		else
			count++;
	}

当我们点击“重新开始”按钮的时候要进行的操作其实和“悔棋”差不多。一个是只清除掉加入的最后一个元素,一个是清除掉链表里的所有元素。
for (int i = 0; i < cheeses.length; i++) {
for (int j = 0; j < cheeses[0].length; j++) {
cheeses[i][j] = 0;
}
}

		for (int i = list.size() - 1; i >= 0; i--) {
			list.remove(i);
		}

		jfr.repaint();
		count = 0;

我们可以看到代码中的cheeses数组,为什么我们要定义一个这样的数组呢。我们在画棋子的时候当然需要判断一下该位置是否有棋子,并且我们还需要知道这个地方是什么棋子,因为后面还需要判断谁赢得比赛。Cheeses数组我们开始将它初始化为全部是0,也就是说棋盘上的各个位置当这里的数值为0的时候就表示这里没有棋子,当这里是1的时候表示这里已经下过黑棋了,当值为-1的时候表示这里已经下过白棋了。(当然这里的黑棋和白棋是我们自己定义的,你也可以定义你自己喜欢的数字)
这样当我们点击这两个按钮的时候就可以实现相应的悔棋和重新开始了。

3.判断输赢的办法
刚刚我们提到了判断输赢的地方,我们这里就把判断输赢的方法讲了吧。我们刚刚已经做好了准备工作,就是声明了一个数组并且将棋盘上每个地方的棋子情况通过数组记录了下来。我们现在就要进行判断,那我们的这个判断函数写在哪里呢。当然是在我们每下一个棋之后都要进行一次的判断啦,因为每下一个棋之后都有可能分出胜负。

我们每下一个棋之后都要先得到当前所下的棋的颜色,然后我们要从四个方向进行判断:横、竖、斜右上、斜左上。每个方向的判断都要进行两个循环,比如横向的判断。首先向上查看颜色一样的棋子,查看颜色一样的棋子也就是查看cheeses数组里面与当前的颜色值相同的,并记录个数;然后向下做同样的操作,将棋子个数继续进行增加。当有五个相同的就可以判断输赢,当前的棋子颜色方赢得胜利。
赢得胜利可以用很多不同的方式表示,我在这里是重新画出一个窗体并输出输赢结果。
public void panduan(int i, int j) {
if (checkRow(i, j) >= 5 || checkLine(i, j) >= 5 || checkZuoshang(i, j) >= 5 || checkYoushang(i, j) >= 5) {
if (cheeses[i][j] == 1) {

			JFrame jk = new JFrame();
			jk.setSize(300, 200);
			jk.setVisible(true);
			JLabel label = new JLabel();
			label.setText("黑棋胜");
			jk.add(label);
		} else if (cheeses[i][j] == -1) {

			JFrame jk = new JFrame();
			jk.setSize(300, 200);
			jk.setVisible(true);
			JLabel label = new JLabel();
			label.setText("白棋胜");
			jk.add(label);
		}
	}
}

public int checkRow(int x, int y) {
	int coot = 0;
	if (x < cheeses[x].length) {
		for (int i = x; i < cheeses.length; i++) {
			if (cheeses[i][y] == cheeses[x][y]) {
				coot++;
			} else
				break;
		}
	}
	for (int i = x; i >= 0; i--) {
		if (cheeses[i][y] == cheeses[x][y]) {
			coot++;
		} else
			break;
	}
	return coot - 1;
}

public int checkLine(int x, int y) {
	int coot = 0;
	if (y < cheeses[x].length) {
		for (int i = y; i < cheeses[x].length; i++) {
			if (cheeses[x][i] == cheeses[x][y]) {
				coot++;
			} else
				break;
		}
	}
	for (int i = y; i >= 0; i--) {
		if (cheeses[x][i] == cheeses[x][y]) {
			coot++;
		} else
			break;
	}
	return coot - 1;
}

public int checkYoushang(int x, int y) {
	int coot = 0;
	for (int i = x + 1, j = y + 1; i < cheeses.length && j < cheeses[i].length; i++, j++) {
		if (cheeses[x][y] == cheeses[i][j]) {
			coot++;
		} else
			break;
	}
	for (int i = x, j = y; i >= 0 && j > 0; i--, j--) {
		if (cheeses[x][y] == cheeses[i][j]) {
			coot++;
		} else
			break;
	}
	return coot;
}

public int checkZuoshang(int x, int y) {
	int coot = 0;
	for (int i = x - 1, j = y + 1; i > 0 && j < cheeses[i].length; i--, j++) {
		if (cheeses[x][y] == cheeses[i][j]) {
			coot++;
		} else
			break;
	}
	for (int i = x, j = y; i < cheeses.length && j > 0; i++, j--) {
		if (cheeses[x][y] == cheeses[i][j]) {
			coot++;
		} else
			break;
	}
	return coot;
}

这样一来我们就实现了简单的人人对战,而且可以实现判断输赢。
五子棋监听器实现