界面开发部分:
1
:创建窗体
继承
JFrame
调用
JFrame
设置标题 尺寸 关闭 可视化 布局等功能
设置布局为
null
布局 ,按钮都需要指定位置
2
:绘制棋盘
重写
JFrame
的
paint
方法
绘制背景矩形 绘制网格
监听器部分:
1
: 按钮监听
ActionListener
2
: 鼠标监听器:
MouseListener
存储棋子部分:
1
: 二维数组存储棋子
2
: 实现重绘棋子 在重绘的方法中
paint
方法中
3
: 判断输赢
悔棋:
1: 知道每一颗棋子的顺序
2: 创建一个棋子类,将棋子的坐标以及棋子标识设置为属性 每次下棋时 创建一个棋子对象 存入一个棋子对象一维数组中
3; 点击悔棋按钮时,将棋子对象数组中的最后一个棋子对象取出获取其行列值 删除二维数组中的数据 再删除一维数组中的棋子对象 重置标识 自动刷新
package Gobang;
import javax.swing.*;
import java.awt.*;
public class GoUI extends JFrame {
int X = 50, Y = 75, SIZE = 50, ROWS = 15, COLS = 15;
GoListener goListener = new GoListener();
public void showUI() {
// 子类调用父类的方法 继承到的方法
setTitle("五子棋");
setSize(1000, 900);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(null);// 空布局
JButton btn1 = new JButton("开始游戏");
JButton btnRb = new JButton("悔棋");
// 设置位置 和 尺寸
btn1.setBounds(X + COLS * SIZE + SIZE, 100, 100, 35);
btnRb.setBounds(X + COLS * SIZE + SIZE, 150, 100, 35);
Font font = new Font("宋体", Font.BOLD, 15);
btn1.setFont(font);
btnRb.setFont(font);
add(btn1);// 添加到窗体上
add(btnRb);
setVisible(true);
// 窗体添加鼠标监听器
addMouseListener(goListener);
//按钮添加动作监听器
btn1.addActionListener(goListener);
btnRb.addActionListener(goListener);
// 获取窗体对象上的画笔对象
Graphics gr = getGraphics();
// 讲画笔对象名中存储画笔对象地址 复制一份给监听器中的对象变量名
// 初始化监听器中的画笔对象变量名 赋值
goListener.g = gr;
}
int count = 0;
// 重写paint方法了
@Override
//自动刷新
public void paint(Graphics g){
super.paint(g);
goListener.paintChessPad(g);
}
public static void main(String[] args) {
GoUI goUI = new GoUI();
goUI.showUI();
}
}
这段代码是一个使用Java编写的五子棋(Gobang)游戏界面,使用Swing库来创建GUI界面。
package Gobang;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.concurrent.ConcurrentSkipListSet;
public class GoListener implements MouseListener, ActionListener{
Graphics g;// 图形渲染工具 绘制一些基础图形 直线 圆 矩形 文字
// 1: 必须在组件上获取 窗体对象上获取 只能在窗体上获取,使用的坐标系也是窗体的坐标系
// 2: 必须在可视化之后获取 在窗体可视化之前获取的话,获取到的是空值
int X = 50, Y = 75, SIZE = 50, ROWS = 15, COLS = 15;
int chessFlag=0;// 0不能下棋 1黑棋 2白棋
int[][] chessArr = new int[ROWS+1][COLS+1];
//存储棋子数组线性
Chess[] chessList = new Chess[(ROWS+1)*(COLS+1)];
int listIndex=0;
public void actionPerformed(ActionEvent e){
System.out.println ("按钮被点击了");
// 获取按钮的文本
String btnStr = e.getActionCommand ();
// 获取按钮的对象
JButton btn = (JButton) e.getSource ();
if(btnStr.equals ("开始游戏")){
chessFlag=1;// 设置标识 为 黑棋先下
// 点击开始游戏按钮之后 将文本替换成 结束游戏
btn.setText ("结束游戏");
}else if(btnStr.equals ("结束游戏")){
chessFlag=0;// 设置标识 不能下棋
chessArr = new int[ROWS+1][COLS+1];
paintChessPad(g);
// 点击结束游戏按钮 替换成开始游戏
btn.setText ("开始游戏");
} else if (btnStr.equals("悔棋")) {
if (listIndex <= 1) {
JOptionPane.showMessageDialog(null, "已经没有棋子可以悔棋了");
return;
}
Chess chess = chessList[listIndex - 1];
// 最后一个棋子
chessArr[chess.r][chess.c] = 0;// 删棋盘上的数据
chessList[listIndex - 1] = null;// 删除棋子对象
listIndex--;// 下标减1
chessFlag = chess.chessFlag;
paintChessPad(g);//刷新棋盘界面
}
}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("鼠标按下");
if (chessFlag == 0) {
System.out.println("游戏未开始");
// 弹窗
JOptionPane.showMessageDialog(null, "游戏未开始");
return;// 结束方法
}
int x = e.getX();
int y = e.getY();
System.out.println("x = " + x + " y = " + y);
// 校正坐标 1步: 将x y 换算成 行列值 0-0 开始
int c = (x - 50 + 25) / 50;
int r = (y - 75 + 25) / 50;
System.out.println("c = " + c + " r = " + r);
// 根据行列值判断下棋的范围
if (c < 0 || c > 15 || r < 0 || r > 15) {
System.out.println("此处不能下棋");
// 弹窗
JOptionPane.showMessageDialog(null, "此处不能下棋");
return;// 结束下棋 结束方法
}
//判断是否重复下棋
if (chessArr[r][c] != 0) {
JOptionPane.showMessageDialog(null, "此处已有棋子,请重新下棋");
return;
}
// 将棋子存入棋盘数组
chessArr[r][c] = chessFlag;
//将数据转为一个棋子对象
Chess chess = new Chess();
chess.r=r;
chess.c=c;
chess.chessFlag= chessFlag;
//存入棋子对象数组中
chessList[listIndex]=chess;
listIndex++;
// 能够确定可以下棋了 才能设置颜色 交换标识
// 2步:根据行列还原 标准坐标
int chessX = c * 50 + 50 - 25;
int chessY = r * 50 + 75 - 25;
if (chessFlag == 1) {
for (int i = 0; i < SIZE; i++) {
Color color = new Color(1+i , 1+i , 1+i );
g.setColor(color);
g.fillOval(chessX + i / 2, chessY + i / 2, SIZE - i, SIZE - i);
}
chessFlag = 2;
} else if (chessFlag == 2) {
for (int i = 0; i < SIZE; i++) {
Color color = new Color(210 + i, 200 + i, 200 + i);
g.setColor(color);
g.fillOval(chessX + i / 2, chessY + i / 2, SIZE - i, SIZE - i);
chessFlag = 1;
}
}
//判断输赢c
boolean winFlag = GoIsWin.isWin(r,c,chessArr);
if(winFlag) {
if (chessFlag == 1) {
JOptionPane.showMessageDialog(null, "白棋赢了");
} else if (chessFlag == 2) {
JOptionPane.showMessageDialog(null, "黑棋赢了");
}
chessFlag = 0;
}
//g.fillOval(chessX, chessY, SIZE, SIZE);
/*if(chessFlag==1){
g.setColor (Color.BLACK);
chessFlag=2;
}else if(chessFlag==2){
g.setColor (Color.WHITE);
chessFlag=1;
}*/
}
//自动刷新
public void paintChessPad(Graphics g){
// 绘制背景
Color color = new Color(84, 190, 163);//0-255
g.setColor(color);
g.fillRect(X - SIZE / 2, Y - SIZE / 2, SIZE * ROWS + SIZE, SIZE * ROWS + SIZE);
// 绘制棋盘
int X = 50, Y = 75, SIZE = 50, ROWS = 15, COLS = 15;
g.setColor(Color.PINK);
for (int i = 0; i <= 15; i++) {
g.drawLine(X, Y + i * SIZE, X + COLS * SIZE, Y + i * SIZE);
g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + ROWS * SIZE);
}
g.setColor(Color.PINK);
g.drawRect(X - 25, Y - 25, SIZE * COLS + SIZE, SIZE * ROWS + SIZE);
//使用监听器调用二维数组
for (int i = 0; i < chessArr.length; i++) {
for (int j = 0; j < chessArr[i].length; j++) {
int n = chessArr[i][j];
// 先判断是不是0 0代表没有棋子
if (n != 0) {
int chessX = j * 50 + 50 - 25;
int chessY = i * 50 + 75 - 25;
// g.fillOval(X+j*SIZE-SIZE/2, Y+i*SIZE-SIZE/2, SIZE, SIZE);
if (n == 1) {
for (int m = 0; m < SIZE; m++) {
Color color2 = new Color(m * 5, m * 5, m * 5);
g.setColor(color2);
g.fillOval(chessX + m / 2, chessY + m / 2, SIZE - m, SIZE - m);
}
}
else if (n == 2) {
for (int m = 0; m < SIZE; m++) {
Color color1 = new Color(200 + m, 200 + m, 200 + m);
g.setColor(color1);
g.fillOval(chessX + m / 2, chessY + m / 2, SIZE - m, SIZE - m);
}
}
}
}
}
}
@Override
public void mouseClicked(MouseEvent e){
}
@Override
public void mouseReleased(MouseEvent e){
}
@Override
public void mouseEntered(MouseEvent e){
}
@Override
public void mouseExited(MouseEvent e){
}
}
这段代码是五子棋游戏的事件监听器类 GoListener
,它实现了 MouseListener
和 ActionListener
接口,用于处理鼠标事件和按钮点击事件。
package Gobang;
public class GoIsWin {
public static boolean isWin(int r,int c,int[][] chessArr){
if(row(r,c,chessArr) >= 5 ||
col(r,c,chessArr) >= 5||
left(r,c,chessArr) >= 5||
right(r,c,chessArr) >= 5){
return true;
}
return false;
}
private static int right(int r, int c, int[][] chessArr) {
int count = 0;
int c1 = chessArr[r][c];
// 右上方
for (int i = r - 1, j = c + 1; i >= 0 && j < chessArr[0].length; i--, j++) {
if (c1 == chessArr[i][j]) {
count++;
} else {
break;
}
}
for (int i = r + 1, j = c - 1; i < chessArr.length && j >= 0; i++, j--) {
if (c1 == chessArr[i][j]) {
count++;
} else {
break;
}
}
count ++;
return count;
}
private static int left(int r, int c, int[][] chessArr) {
int count = 0;
int c1 = chessArr[r][c];
for (int i = r + 1, j = c + 1; i < chessArr.length && j < chessArr[0].length; i++, j++) {
if (c1 == chessArr[i][j]) {
count++;
} else {
break;
}
}
for (int i = r - 1, j = c - 1; i >= 0 && j >= 0; i--, j--) {
if (c1 == chessArr[i][j]) {
count++;
} else {
break;
}
}
count++;
return count;
}
private static int col ( int r, int c, int[][] chessArr){
int count = 0;
int c1 = chessArr[r][c];
for (int i = r + 1; i < chessArr.length; i++) {
if (c1 == chessArr[i][c]) {
count++;
} else {
break;
}
}
for (int i = r - 1; i >= 0; i++) {
if (c1 == chessArr[i][c]) {
count++;
} else {
break;
}
}
count++;
return count;
}
private static int row ( int r, int c, int[][] chessArr){
int count = 0;
int c1 = chessArr[r][c];
for (int i = 0; i < chessArr.length; i++) {
if (c1 == chessArr[r][i]) {
count++;
} else {
break;
}
}
for (int i = c - 1; i >= 0; i--) {
if (c1 == chessArr[r][i]) {
count++;
} else {
break;
}
}
count++;
return count;
}
}
五子棋游戏中的胜利判断逻辑,用于检测玩家是否获胜。以下是代码的主要功能和解释: