java入门-五子棋游戏的制作
想要开发一个简单的五子棋游戏,需要实现五子棋的棋盘、棋子、输赢判定、重新开始游戏、悔棋、认输、人机大战以及退出游戏等功能。
1.实现五子棋的棋盘功能
想要实现这个功能,我们需要了解JFrame窗体容器,以及一些相应的可视化组件和元素组件,我们首先需要设置窗口的大小位置以及标题。窗口设置好了,我们需要使用paint(g)函数进行绘图,这里我选择的是20*20的网格,网格大小长宽各为20。在使用paint()函数绘制图形的时候,我们需要加上super.paint(g),这是对父类方法的重写,表示在原来图像的基础上,再画图。如果不加上的话,重绘时,会将原有的绘制清空。
//构造函数初始化
public youxi() {
// int w=Toolkit.getDefaultToolkit().getScreenSize().width;
this.setLayout(null);
this.setTitle("五子棋");
this.setBounds(700, 400, 600, 500);
// this.setBackground(Color.blue);
this.setResizable(false);
this.addMouseListener(this);
JLabel p = new JLabel();
p.setBounds(100, 435, 100, 30);
p.setText("剩余时间");
this.add(p);
this.setVisible(true);
this.setDefaultCloseOperation(3);
putMap();
}
//重写绘制组件的方法
public void paint(Graphics g) {
super.paint(g);
// 绘制棋盘
g.setColor(Color.black);
// 画横线
for (int i = 0; i < 20; i++) {
g.drawLine(30, 80 + 20 * i, 410, 80 + 20 * i);
// 画竖线
g.drawLine(30 + 20 * i, 80, 30 + 20 * i, 460);
}
2.棋子的绘制
五子棋一般只有黑白两种棋子`,使用for循环即可,i代表的是横坐标,j代表的是纵坐标,在这里我用的是一个二维数组对棋子的颜色进行存储,来判断(i,j)这个棋盘位置是黑棋还是白棋,由于数组的i,j是坐标值并不是实际的位置,所以我们需要将i,j转换为棋盘的位置,因为棋盘是从窗体的(30,80)开始画的,所以我们计算棋子的位置的时候需要分别加上30和80,g.fillOval(xx, yy, 20, 20);xx,yy是棋子左上角的位置,所以我们需要提前减去棋子的半径使鼠标点击的位置变成棋子的中心
// 建立数组缓存已经下好棋子的位置
int arr[][] = new int[20][20];
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++) {
xx = 20 * i + 30 - 10;
yy = 20 * j + 80 - 10;
if (arr[i][j] == 1) {
g.setColor(Color.black);
g.fillOval(xx, yy, 20, 20);
}
if (arr[i][j] == 2) {
g.setColor(Color.white);
g.fillOval(xx, yy, 20, 20);
}
}
3.下棋功能的实现
这里我们需要使用MouseListener鼠标事件监听器,在这里我们将鼠标点击作为事件源,鼠标按下时实现下棋功能,因为鼠标在棋盘上点击的位置并不是棋盘的交点位置,所以我们需要判断一下棋子该下在哪个位置,这里我是根据象限的不同来确定棋子到底下在哪个位置的,根据象限的不同对棋子的坐标值进行相应的调整,如代码所示
因为总是黑方先下,这里使用了一个布尔变量colorblack作为棋子颜色的标识,每下一步棋标识都发生改变,根据标识的不同来设置二维数组arr[x][y]的值
public void mouseClicked(MouseEvent e) {
// 获取鼠标的坐标
x = e.getX();
y = e.getY();
// 判断鼠标在哪一个象限,并将坐标值转换成对应的行和列
if (play) {
if (x > 30 && x < 410 && y > 80 && y < 460) {
if ((x - 30) % 20 > 10 && (y - 80) % 20 > 10) {
x = (x - 30) / 20 + 1;
y = (y - 80) / 20 + 1;
} else if ((x - 30) % 20 < 10 && (y - 80) % 20 > 10) {
x = (x - 30) / 20;
y = (y - 80) / 20 + 1;
} else if ((x - 30) % 20 > 10 && (y - 80) % 20 < 10) {
x = (x - 30) / 20 + 1;
y = (y - 80) / 20;
} else {
x = (x - 30) / 20;
y = (y - 80) / 20;
}
cx[countx++] = x;
cy[county++] = y;
// 记录每一行每一列棋子的颜色,arr[x][y] == 0是为了防止棋子覆盖
if (arr[x][y] == 0) {
if (colorblack) {
arr[x][y] = 1;
colorblack = false;
message = "白方下";
} else {
arr[x][y] = 2;
colorblack = true;
message = "黑方下";
}
}
}
4.判断输赢功能的实现
代码比较长但很简单,需要判断4个方向是否有5子连成,分别是横向、纵向以及两个斜向,这里使用count作为四个方向的计数变量,四个方向的判定方法都一样,只是参数改变了一些,我采用的是遍历整个棋盘的方式来判断是否有五子相连,如图箭头所指的棋子,这里用一个count变量来进行计数,如果遇到相同颜色的棋子count加1,遇到不同的直接跳出该方向的判断,继续进行搜索,直到count变为5,跳出循环,根据当前棋子的颜色判断输赢
public void iswin(int x, int y) {
int count = 1;
if (arr[x][y] != 0) {
int a = arr[x][y];
// 横向
for (int k = x + 1; k < arr.length; k++) {
// 棋子的颜色相同时,相应的计数变量增加,否则变为1继续进行判断
if (arr[k][y] == a) {
count++;
} else {
break;
}
// 计数变量大于等于5时即可根据当前棋子的颜色判断黑方赢还是白方赢,判断过后直接跳出循环
if (count >= 5) {
if (arr[k][y] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
for (int k = x - 1; k >= 0; k--) {
if (arr[k][y] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[k][y] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
count = 1;
// 纵向
for (int k = y - 1; k >= 0; k--) {
if (arr[x][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[x][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
for (int k = y + 1; k < arr.length; k++) {
if (arr[x][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[x][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
count = 1;
// 左下、右上
for (int m = x - 1, k = y + 1; k < arr.length && m >= 0; k++, m--) {
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
for (int m = x + 1, k = y - 1; m < arr.length && k >= 0; k--, m++) {
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
count = 1;
// 左上、右下
for (int m = x - 1, k = y - 1; m >= 0 && k >= 0; k--, m--) {
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
for (int m = x + 1, k = y + 1; m < arr.length && k < arr.length; k++, m++) {
if (arr[m][k] == 0) {
break;
}
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
}
break;
}
}
count = 1;
}
}
5.重新开始游戏
这里需要自己直接添加按钮,这里我是自己用画笔画了一个按钮,后面的功能按钮都是这么画的,目的是为了所有的事件源都是窗体,重新开始游戏,那么我们需要将一些变量都赋值为初始值,还需要将棋盘上的棋子清空,即二维数组的清空,比较简单
// 重新开始按钮绘制
g.drawRect(450, 100, 100, 30);
g.drawString("重新开始", 480, 118);
// 重新开始
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 100 && e.getY() < 130) {
int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏");
if (result == 0) {
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++) {
arr[i][j] = 0;
chessvalue[i][j] = 0;
}
for (int i = 0; i < cx.length; i++) {
cx[i] = 0;
cy[i] = 0;
}
colorblack = true;
message = "黑方下";
play = true;
isrenji = false;
renji = false;
}
}
6.悔棋
悔棋的话需要知道悔棋是黑方还是白方以及返回上一步棋盘上棋子的情况,这里用countx和county两个变量记录当前下了几个棋子,cx[],cy[],两个一维数组分别记下当前棋子的坐标,悔棋的话只需要countx-1和county-1得到上一步棋子的个数再通过数组即可得到坐标值,将该坐标值上的棋子颜色清零即可
// 悔棋按钮绘制
g.drawRect(450, 200, 100, 30);
g.drawString("悔棋", 495, 218);
// 悔棋
//先判断下一步棋子的颜色,如果下一步要下黑棋,则是白方悔棋,反之,黑方悔棋
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 200 && e.getY() < 230) {
int result = JOptionPane.showConfirmDialog(this, colorblack == false ? "黑方悔棋,白方是否同意" : "白方悔棋,黑方是否同意");
message = colorblack == false ? "黑方下" : "白方下";
//这里用countx和county两个变量记录当前下了几个棋子,cx[],cy[],两个一维数组分别记下当前棋子的坐标,悔棋的话只需要countx-1和county-1得到上一步棋子的个数再通过数组即可得到坐标值,将该坐标值上的棋子颜色清零即可
if (result == 0) {
arr[cx[--countx]][cy[--county]] = 0;
//悔棋之后颜色标识也得改变
colorblack = !colorblack;
play = true;
}
}
7.认输
按钮的绘制都和前面一样,实现很简单,只需要根据当前棋子颜色标识判断黑方还是白方认输,直接看代码吧
// 认输
g.drawRect(450, 300, 100, 30);
g.drawString("认输", 495, 318);
// 认输
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 300 && e.getY() < 330) {
int result = JOptionPane.showConfirmDialog(this, "是否认输");
if (result == 0) {
JOptionPane.showMessageDialog(null, colorblack == true ? "白方获胜" : "黑方获胜");
play = false;
}
}
8.退出功能
这个就很简单了,直接退出系统即可
// 退出游戏
g.drawRect(450, 400, 100, 30);
g.drawString("退出游戏", 480, 418);
// 退出
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 400 && e.getY() < 430) {
int result = JOptionPane.showConfirmDialog(this, "是否退出游戏");
if (result == 0) {
System.exit(0);
}
}
9.人机对战功能
人机功能的实现主要是利用权值算法来实现,首先需要创建权值表,里面具体的权值可以根据你自己来调,这里使用的是来创建权值表,权值表中的键代表的是相连棋子的个数,哈希值代表的是权重,以一个空白位置作为起始点对该点的八个位置进行搜索,碰到空位置直接跳出该方向的循环,遇到棋子的时候将该位置的棋子的颜色和棋局记录下来,继续进行该方向的搜索,重复这样的操作,该方向搜索完之后将权值累加并记录在一个二维数组中,其它七个方向方法都一样,循环结束比较每个位置的权值大小,权值最大的坐标点就是人机要下棋的位置
HashMap<String, Integer> hm = new HashMap<String, Integer>();
//创建权值表
public void putMap() {
hm.put("1", 20);//
hm.put("11", 200);
hm.put("111", 2000);
hm.put("1111", 3000);
hm.put("12", 10);
hm.put("112", 100);
hm.put("1112", 1000);
hm.put("11112", 2000);
hm.put("2", 30);
hm.put("22", 300);
hm.put("222", 3000);
hm.put("2222", 4000);
hm.put("21", 20);
hm.put("221", 200);
hm.put("2221", 2000);
hm.put("22221", 3000);
}
// 人机对战
if (isrenji && renji) {
// System.out.println("1234");
AI();
colorblack = !colorblack;
message = "黑方下";
}
public void AI() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
// 判断当前是否为空
if (arr[i][j] == 0) {
// 搜索该空位八个方向上棋局情况
// 定义两个变量分别保存棋局,以及颜色
String code = "";
int color = 0;
// 向下
for (int k = i + 1; k < arr.length; k++) {
if (arr[k][j] == 0) {
break;
} else {
if (color == 0) { // 下边第一颗棋子
color = arr[k][j]; // 保存颜色
code += arr[k][j]; // 保存棋局
} else if (arr[k][j] == color) { // 下边第二,三..同颜色棋子
code += arr[k][j]; // 保存棋局
} else { // 下边不同颜色
code += arr[k][j]; // 保存棋局
break;
}
}
}
// 根据code取出hm对应的权值
Integer value = hm.get(code);
// System.out.println("value"+value);
if (value != null) {
chessvalue[i][j] += value; // 权值累加
}
// System.out.println(chessvalue[i][j]);
// 剩余七个方向
code = "";
color = 0;
// 向上
for (int k = i - 1; k >= 0; k--) {
if (arr[k][j] == 0) {
break;
} else {
if (color == 0) { // 上边第一颗棋子
color = arr[k][j]; // 保存颜色
code += arr[k][j]; // 保存棋局
} else if (arr[k][j] == color) { // 上边第二,三..同颜色棋子
code += arr[k][j]; // 保存棋局
} else { // 上边不同颜色
code += arr[k][j]; // 保存棋局
break;
}
}
}
Integer value1 = hm.get(code);
if (value1 != null) {
chessvalue[i][j] += value1; // 权值累加
}
// 剩余六个方向
code = "";
color = 0;
// 向左
for (int k = j - 1; k >= 0; k--) {
if (arr[i][k] == 0) {
break;
} else {
if (color == 0) { // 左边第一颗棋子
color = arr[i][k]; // 保存颜色
code += arr[i][k]; // 保存棋局
} else if (arr[i][k] == color) { // 左边第二,三..同颜色棋子
code += arr[i][k]; // 保存棋局
} else { // 左边不同颜色
code += arr[i][k]; // 保存棋局
break;
}
}
}
Integer value2 = hm.get(code);
if (value2 != null) {
chessvalue[i][j] += value2; // 权值累加
}
// 剩余五个方向
code = "";
color = 0;
// 向右
for (int k = j + 1; k < arr.length; k++) {
if (arr[i][k] == 0) {
break;
} else {
if (color == 0) { // 右边第一颗棋子
color = arr[i][k]; // 保存颜色
code += arr[i][k]; // 保存棋局
} else if (arr[i][k] == color) { // 右边第二,三..同颜色棋子
code += arr[i][k]; // 保存棋局
} else { // 右边不同颜色
code += arr[i][k]; // 保存棋局
break;
}
}
}
Integer value3 = hm.get(code);
if (value3 != null) {
chessvalue[i][j] += value3; // 权值累加
}
// 剩余四个方向
code = "";
color = 0;
// 左下
for (int m = i + 1, k = j - 1; m < arr.length && k >= 0; k--, m++) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 左下第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 左下第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 左下不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value4 = hm.get(code);
if (value4 != null) {
chessvalue[i][j] += value4; // 权值累加
}
// 剩余四个方向
code = "";
color = 0;
// 右上
for (int m = i - 1, k = j + 1; m >= 0 && k < arr.length; k++, m--) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 右上第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 右上第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 右上不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value5 = hm.get(code);
if (value5 != null) {
chessvalue[i][j] += value5; // 权值累加
}
code = "";
color = 0;
// 左上
for (int m = i - 1, k = j - 1; m >= 0 && k >= 0; k--, m--) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 左上第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 左上第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 左上不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value6 = hm.get(code);
if (value6 != null) {
chessvalue[i][j] += value6; // 权值累加
}
code = "";
color = 0;
// 右下
for (int m = i + 1, k = j + 1; m < arr.length && k < arr.length; k++, m++) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 右下第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 右下第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 右下不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value7 = hm.get(code);
if (value7 != null) {
chessvalue[i][j] += value7; // 权值累加
}
code = "";
color = 0;
}
}
}
int max = 0;
for (int i = 0; i < chessvalue.length; i++)
for (int j = 0; j < chessvalue.length; j++) {
if (chessvalue[i][j] > max) {
max = chessvalue[i][j];
rx = i;
ry = j;
}
}
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++) {
chessvalue[i][j] = 0;
}
arr[rx][ry] = 2;
}
10.全部代码
package wuziqi;
//插入图形化界面相应的包1.javax.swing (可视化组件) 2.java.awt (元素组件)
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
public class youxi extends JFrame implements MouseListener {
// 建立数组缓存已经下好棋子的位置
int arr[][] = new int[20][20];
// 记录鼠标当前的位置
int x, y;
// 记录当前棋子的坐标,本代码使用颜色来判断棋子在棋盘上的情况,0代表无棋子,1代表黑色棋子,2代表白色棋子
int cx[] = new int[400];
int cy[] = new int[400];
// 记录当前棋子的个数
int countx, county;
int xx, yy;
int a = 1;
int rx, ry;
// 建立一些标识
boolean colorblack = true;// 当前棋子颜色标识,为了方便对arr[][]进行赋值
boolean play = true;// 判断游戏是否结束,结束则不能玩
boolean isrenji = false;// 人机对战标识,为true则人机互打
String message = "黑方下";
// 用来缓存在棋盘每个位置权值
int chessvalue[][] = new int[20][20];
HashMap<String, Integer> hm = new HashMap<String, Integer>();
//创建权值表
public void putMap() {
hm.put("1", 20);
hm.put("11", 200);
hm.put("111", 2000);
hm.put("1111", 3000);
hm.put("12", 10);
hm.put("112", 100);
hm.put("1112", 1000);
hm.put("11112", 2000);
hm.put("2", 30);
hm.put("22", 300);
hm.put("222", 3000);
hm.put("2222", 4000);
hm.put("21", 20);
hm.put("221", 200);
hm.put("2221", 2000);
hm.put("22221", 3000);
}
//构造函数初始化
public youxi() {
// int w=Toolkit.getDefaultToolkit().getScreenSize().width;
this.setLayout(null);// 绝对布局
this.setTitle("五子棋");// 设置标题
this.setBounds(700, 400, 600, 500);// 设置大小位置
this.setResizable(false);// 形状固定
this.addMouseListener(this);// 添加鼠标监听对象
JLabel p = new JLabel();
p.setBounds(100, 435, 100, 30);
p.setText("剩余时间");
this.add(p);
this.setVisible(true);
this.setDefaultCloseOperation(3);
putMap();
}
//重写绘制组件的方法
public void paint(Graphics g) {
super.paint(g);
//添加背景
ImageIcon icon=new ImageIcon("F:\\2.jpg");
g.drawImage(icon.getImage(), 30, 80, 380, 380, null);
// 绘制棋盘
g.setColor(Color.black);
// 画横线
for (int i = 0; i < 20; i++) {
g.drawLine(30, 80 + 20 * i, 410, 80 + 20 * i);
// 画竖线
g.drawLine(30 + 20 * i, 80, 30 + 20 * i, 460);
}
// 提示
g.setColor(Color.black);
g.drawString("提示:" + message, 50, 55);
// 重新开始按钮绘制
g.drawRect(450, 100, 100, 30);
g.drawString("重新开始", 480, 118);
// 悔棋按钮绘制
g.drawRect(450, 200, 100, 30);
g.drawString("悔棋", 495, 218);
// 认输
g.drawRect(450, 300, 100, 30);
g.drawString("认输", 495, 318);
// 退出游戏
g.drawRect(450, 400, 100, 30);
g.drawString("退出游戏", 480, 418);
// 人机对战
g.drawRect(250, 35, 100, 30);
g.drawString("人机大战", 280, 55);
// 画棋子
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++) {
xx = 20 * i + 30 - 10;
yy = 20 * j + 80 - 10;
if (arr[i][j] == 1) {
g.setColor(Color.black);
g.fillOval(xx, yy, 20, 20);
}
if (arr[i][j] == 2) {
g.setColor(Color.white);
g.fillOval(xx, yy, 20, 20);
}
}
}
public void mouseClicked(MouseEvent e) {
// 获取鼠标的坐标
x = e.getX();
y = e.getY();
// 判断鼠标在哪一个象限,并将坐标值转换成对应的行和列
if (play) {
if (x > 30 && x < 410 && y > 80 && y < 460) {
if ((x - 30) % 20 > 10 && (y - 80) % 20 > 10) {
x = (x - 30) / 20 + 1;
y = (y - 80) / 20 + 1;
} else if ((x - 30) % 20 < 10 && (y - 80) % 20 > 10) {
x = (x - 30) / 20;
y = (y - 80) / 20 + 1;
} else if ((x - 30) % 20 > 10 && (y - 80) % 20 < 10) {
x = (x - 30) / 20 + 1;
y = (y - 80) / 20;
} else {
x = (x - 30) / 20;
y = (y - 80) / 20;
}
cx[countx++] = x;
cy[county++] = y;
// 记录每一行每一列棋子的颜色,arr[x][y] == 0是为了防止棋子覆盖
if (arr[x][y] == 0) {
if (colorblack) {
arr[x][y] = 1;
colorblack = false;
message = "白方下";
iswin(x, y);
// 人机对战
if (isrenji) {
AI();
colorblack = !colorblack;
message = "黑方下";
iswin(rx, ry);
}
} else {
arr[x][y] = 2;
colorblack = true;
message = "黑方下";
iswin(x, y);
}
}
}
}
// 重新开始
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 100 && e.getY() < 130) {
int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏");
if (result == 0) {
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++) {
arr[i][j] = 0;
chessvalue[i][j] = 0;
}
for (int i = 0; i < cx.length; i++) {
cx[i] = 0;
cy[i] = 0;
}
colorblack = true;
message = "黑方下";
play = true;
isrenji = false;
}
}
// 悔棋
// 先判断下一步棋子的颜色,如果下一步要下黑棋,则是白方悔棋,反之,黑方悔棋
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 200 && e.getY() < 230) {
int result = JOptionPane.showConfirmDialog(this, colorblack == false ? "黑方悔棋,白方是否同意" : "白方悔棋,黑方是否同意");
message = colorblack == false ? "黑方下" : "白方下";
// 这里用countx和county两个变量记录当前下了几个棋子,cx[],cy[],两个一维数组分别记下当前棋子的坐标,悔棋的话只需要countx-1和county-1得到上一步棋子的个数再通过数组即可得到坐标值,将该坐标值上的棋子颜色清零即可
if (result == 0) {
arr[cx[--countx]][cy[--county]] = 0;
// 悔棋之后颜色标识也得改变
colorblack = !colorblack;
play = true;
}
}
// 认输
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 300 && e.getY() < 330) {
int result = JOptionPane.showConfirmDialog(this, "是否认输");
if (result == 0) {
JOptionPane.showMessageDialog(null, colorblack == true ? "白方获胜" : "黑方获胜");
play = false;
}
}
// 退出
if (e.getX() > 450 && e.getX() < 550 && e.getY() > 400 && e.getY() < 430) {
int result = JOptionPane.showConfirmDialog(this, "是否退出游戏");
if (result == 0) {
System.exit(0);
}
}
// 人机对战
if (e.getX() > 250 && e.getX() < 350 && e.getY() > 35 && e.getY() < 65) {
int result = JOptionPane.showConfirmDialog(this, "是否人机大战");
if (result == 0) {
isrenji = true;
}
}
// 重绘棋盘
this.repaint();
}
public void AI() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
// 判断当前是否为空
if (arr[i][j] == 0) {
// 搜索该空位八个方向上棋局情况
// 定义两个变量分别保存棋局,以及颜色
String code = "";
int color = 0;
// 向下
for (int k = i + 1; k < arr.length; k++) {
if (arr[k][j] == 0) {
break;
} else {
if (color == 0) { // 下边第一颗棋子
color = arr[k][j]; // 保存颜色
code += arr[k][j]; // 保存棋局
} else if (arr[k][j] == color) { // 下边第二,三..同颜色棋子
code += arr[k][j]; // 保存棋局
} else { // 下边不同颜色
code += arr[k][j]; // 保存棋局
break;
}
}
}
// 根据code取出hm对应的权值
Integer value = hm.get(code);
// System.out.println("value"+value);
if (value != null) {
chessvalue[i][j] += value; // 权值累加
}
// System.out.println(chessvalue[i][j]);
// 剩余七个方向
code = "";
color = 0;
// 向上
for (int k = i - 1; k >= 0; k--) {
if (arr[k][j] == 0) {
break;
} else {
if (color == 0) { // 上边第一颗棋子
color = arr[k][j]; // 保存颜色
code += arr[k][j]; // 保存棋局
} else if (arr[k][j] == color) { // 上边第二,三..同颜色棋子
code += arr[k][j]; // 保存棋局
} else { // 上边不同颜色
code += arr[k][j]; // 保存棋局
break;
}
}
}
Integer value1 = hm.get(code);
if (value1 != null) {
chessvalue[i][j] += value1; // 权值累加
}
// 剩余六个方向
code = "";
color = 0;
// 向左
for (int k = j - 1; k >= 0; k--) {
if (arr[i][k] == 0) {
break;
} else {
if (color == 0) { // 左边第一颗棋子
color = arr[i][k]; // 保存颜色
code += arr[i][k]; // 保存棋局
} else if (arr[i][k] == color) { // 左边第二,三..同颜色棋子
code += arr[i][k]; // 保存棋局
} else { // 左边不同颜色
code += arr[i][k]; // 保存棋局
break;
}
}
}
Integer value2 = hm.get(code);
if (value2 != null) {
chessvalue[i][j] += value2; // 权值累加
}
// 剩余五个方向
code = "";
color = 0;
// 向右
for (int k = j + 1; k < arr.length; k++) {
if (arr[i][k] == 0) {
break;
} else {
if (color == 0) { // 右边第一颗棋子
color = arr[i][k]; // 保存颜色
code += arr[i][k]; // 保存棋局
} else if (arr[i][k] == color) { // 右边第二,三..同颜色棋子
code += arr[i][k]; // 保存棋局
} else { // 右边不同颜色
code += arr[i][k]; // 保存棋局
break;
}
}
}
Integer value3 = hm.get(code);
if (value3 != null) {
chessvalue[i][j] += value3; // 权值累加
}
// 剩余四个方向
code = "";
color = 0;
// 左下
for (int m = i + 1, k = j - 1; m < arr.length && k >= 0; k--, m++) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 左下第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 左下第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 左下不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value4 = hm.get(code);
if (value4 != null) {
chessvalue[i][j] += value4; // 权值累加
}
// 剩余四个方向
code = "";
color = 0;
// 右上
for (int m = i - 1, k = j + 1; m >= 0 && k < arr.length; k++, m--) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 右上第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 右上第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 右上不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value5 = hm.get(code);
if (value5 != null) {
chessvalue[i][j] += value5; // 权值累加
}
code = "";
color = 0;
// 左上
for (int m = i - 1, k = j - 1; m >= 0 && k >= 0; k--, m--) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 左上第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 左上第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 左上不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value6 = hm.get(code);
if (value6 != null) {
chessvalue[i][j] += value6; // 权值累加
}
code = "";
color = 0;
// 右下
for (int m = i + 1, k = j + 1; m < arr.length && k < arr.length; k++, m++) {
if (arr[m][k] == 0) {
break;
} else {
if (color == 0) { // 右下第一颗棋子
color = arr[m][k]; // 保存颜色
code += arr[m][k]; // 保存棋局
} else if (arr[m][k] == color) { // 右下第二,三..同颜色棋子
code += arr[m][k]; // 保存棋局
} else { // 右下不同颜色
code += arr[m][k]; // 保存棋局
break;
}
}
}
Integer value7 = hm.get(code);
if (value7 != null) {
chessvalue[i][j] += value7; // 权值累加
}
code = "";
color = 0;
}
}
}
int max = 0;
for (int i = 0; i < chessvalue.length; i++)
for (int j = 0; j < chessvalue.length; j++) {
if (chessvalue[i][j] > max) {
max = chessvalue[i][j];
rx = i;
ry = j;
}
}
for (int i = 0; i < 20; i++)
for (int j = 0; j < 20; j++) {
chessvalue[i][j] = 0;
}
arr[rx][ry] = 2;
}
public void iswin(int x, int y) {
int count = 1;
if (arr[x][y] != 0) {
int a = arr[x][y];
// 横向
for (int k = x + 1; k < arr.length; k++) {
// 棋子的颜色相同时,相应的计数变量增加,否则变为1继续进行判断
if (arr[k][y] == a) {
count++;
} else {
break;
}
// 计数变量大于等于5时即可根据当前棋子的颜色判断黑方赢还是白方赢,判断过后直接跳出循环
if (count >= 5) {
if (arr[k][y] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
for (int k = x - 1; k >= 0; k--) {
if (arr[k][y] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[k][y] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
count = 1;
// 纵向
for (int k = y - 1; k >= 0; k--) {
if (arr[x][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[x][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
for (int k = y + 1; k < arr.length; k++) {
if (arr[x][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[x][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
count = 1;
// 左下、右上
for (int m = x - 1, k = y + 1; k < arr.length && m >= 0; k++, m--) {
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
for (int m = x + 1, k = y - 1; m < arr.length && k >= 0; k--, m++) {
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
count = 1;
// 左上、右下
for (int m = x - 1, k = y - 1; m >= 0 && k >= 0; k--, m--) {
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
for (int m = x + 1, k = y + 1; m < arr.length && k < arr.length; k++, m++) {
if (arr[m][k] == 0) {
break;
}
if (arr[m][k] == a) {
count++;
} else {
break;
}
if (count >= 5) {
if (arr[m][k] == 1) {
JOptionPane.showMessageDialog(null, "黑方赢");
play = false;
isrenji=false;
} else {
JOptionPane.showMessageDialog(null, "白方赢");
play = false;
isrenji=false;
}
break;
}
}
count = 1;
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
// TODO Auto-generated method stub
youxi yx = new youxi();
}
}