一. 程序基本思路:
1.写窗口、棋盘面板、控制面板;
2.绘制棋盘;
3.绘制棋子;
4.添加组件功能;
5.判断输赢;
6.悔棋;
7.复盘。
二.实际操作
1.创建窗口、添加面板
package teachGoBang;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GoBang {
public void drawUI() {
JFrame jf = new JFrame("五子棋");//创建窗口
jf.setSize(980,900);//设置窗口大小
jf.setLocationRelativeTo(null);//居中显示
jf.setDefaultCloseOperation(3);//设置窗口后台关闭
jf.setLayout(new BorderLayout());//将窗体设为边框布局
JPanel chesspanel = new JPanel();//创建棋盘对象
jf.setBackground(Color.WHITE);//设置棋盘颜色
jf.add(chesspanel,BorderLayout.CENTER);//将面板添加到窗体中间
Mouse mouse = new Mouse();//创建鼠标对象
//直接在面板后创建鼠标对象便于对象在类之间的传递
JPanel buttonpanel = new JPanel();//创建操控面板
buttonpanel.setBackground(Color.GRAY);//设置棋盘颜色
buttonpanel.setPreferredSize(new Dimension(180,900));//设置控制面板大小
jf.add(buttonpanel,BorderLayout.EAST);//将面板添加到窗体右侧布局
String[] button = {"开始","人机","悔棋","认输","复盘"};//创建按钮数组
for(int i=0;i<button.length;i++) {
JButton jbu = new JButton(button[i]);//创建按钮对象,并赋给其数组值
jbu.setPreferredSize(new Dimension(160,100));//设置按钮大小
jbu.setFont(new Font("思源宋体",Font.BOLD,18));//设置按钮字体
buttonpanel.add(jbu);//给操控面板添加按钮组件
jbu.addActionListener(mouse);//给按钮添加鼠标监听器
}
jf.setVisible(true);//设置窗体课件
mouse.setGraphics(chesspanel.getGraphics());//创建画笔对象并传递给Mouse类
chesspanel.addMouseListener(mouse);//给棋盘添加鼠标监听器
}
public static void main(String[]args) {
GoBang go = new GoBang();
go.drawUI();
}
}
效果图:
2.绘制棋盘
为了棋盘线在窗体刷新后仍能保存,我们直接重写chesspanel的paint方法,将棋盘绘制写在paint方法中。为了调用方便,我们先写一个接口,用于保存绘制棋盘要用的数据。
package teachGoBang;
public interface Basic {
public int x0 = 50, y0 = 50, size = 50, line = 15;
//x0,y0围棋盘线的起始点,size为行距,line为行数
}
package teachGoBang;
import java.awt.Graphics;
import javax.swing.JPanel;
//写一个MyPanel类继承类,重写paint方法
public class MyPanel extends JPanel implements Basic{
public void paint(Graphics g) {
super.paint(g);//先将父类自带的paint方法再写一遍
for (int i = 0; i < line; i++) {
g.drawLine(x0, y0 + i * size, x0 + (line - 1) * size, y0 + i * size);
g.drawLine(x0 + i * size, y0, x0 + i * size, y0 + (line - 1) * size);
}
}
}
同时要记得将先前的chesspanel对象的类名改为MyPanel
MyPanel chesspanel = new MyPanel();//创建棋盘对象
效果图
3.绘制棋子
棋子绘制写在鼠标类中,通过鼠标点击位置获取棋子坐标。绘制后的棋子要保存到数组中,然后在MyPanel类的paint方法中再绘制一次棋子,完成已绘制棋子的保存。
package teachGoBang;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import lqz3.Chess;
//在鼠标类中直接去继承MouseAdapter类而不是使用接口可以不用重写所有方法
public class Mouse extends MouseAdapter implements ActionListener, Basic {
private Graphics g;// 定义画笔
private int x, y, x1, y1;
private int[][] chessArr = new int[line][line];// 定义二维数组,用于保存棋盘坐标对应的棋子颜色
private int count = 0;// 定义计数器记录棋子个数
private Color color;
public void setGraphics(Graphics g) {
this.g = g;
}
public int[][] getchessArr(){
return chessArr;
}
public void actionPerformed(ActionEvent e) {
}
public void mouseClicked(MouseEvent e) {
int x = e.getX();// 鼠标点击处获取x、y坐标
int y = e.getY();
// 获取落子坐标,此处进行判断让获取的坐标位于棋盘线交点处
if ((x - x0) % size > size / 2) {
x1 = (x - x0) / size + 1;
} else if ((x - x0) % size <= size / 2) {
x1 = (x - x0) / size;
}
if ((y - y0) % size > size / 2) {
y1 = (y - y0) / size + 1;
} else if ((y - y0) % size <= size / 2) {
y1 = (y - y0) / size;
}
// 判断棋子是否会越出棋盘界
if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) {
// 判断只有空位置才能下棋
if (chessArr[y1][x1] == 0) {
// 加for循环是为了给棋子添加3D效果
for (int i = 0; i < 50; i++) {
// count为双数下黑棋,为单数下白棋
//下完黑棋在数组中存入1,白棋存入-1
if (count % 2 == 0) {
color = new Color(5 * i, 5 * i, 5 * i);// 3d效果
g.setColor(color);// 设置画笔颜色
g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);
chessArr[y1][x1] = 1;// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)
} else {
color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);
g.setColor(color);
g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);
chessArr[y1][x1] = -1;
}
}
count++;//每下完一颗棋,计数器加1
}
}else {
System.out.print("超出棋盘边界");
}
}
}
接下来要在MyPanel的paint方法中重绘棋子。先在两个类中写set和get方法,再将chessArr数组传递到MyPanel类中,由于GoBang类中同时出现chesspanel和mouse对象,因此在GoBang中传递该数组。为了防止MyPanel中出现重绘棋盘时要用到chessArr数组而chessArr数组还没传过来的情况发生,我们直接在创建chesspanel对象后就把数组传过去
Mouse mouse = new Mouse();//创建鼠标对象
chesspanel.setchseeArr(mouse.getchessArr());//传递数组
public void paint(Graphics g) {
super.paint(g);// 先将父类自带的paint方法再写一遍
//绘制棋盘
for (int i = 0; i < line; i++) {
g.drawLine(x0, y0 + i * size, x0 + (line - 1) * size, y0 + i * size);
g.drawLine(x0 + i * size, y0, x0 + i * size, y0 + (line - 1) * size);
}
//绘制棋子
for (int i = 0; i < chessArr.length; i++) {
for (int j = 0; j < chessArr[0].length; j++) {
int chesscolor = chessArr[i][j];//取出棋子颜色对应的值
if (chesscolor != 0) {
if (chesscolor == 1) {//下黑棋
for (int a = 0; a < 50; a++) {
g.setColor(new Color(5 * a, 5 * a, 5 * a));
g.fillOval(j * size + x0 + a / 2 - 25, i * size + y0 + a / 2 - 25, 50 - a, 50 - a);
}
} else {//下白棋
for (int a = 0; a < 50; a++) {
g.setColor(new Color(155 + 2 * a, 155 + 2 * a, 155 + 2 * a));
g.fillOval(j * size + x0 + a / 2 - 25, i * size + y0 + a / 2 - 25, 50 - a, 50 - a);
}
}
}
}
}
}
效果图
此步骤重点有:用计数器单双决定棋色、棋子要下在交点处、用二维数组保存棋色对应值、传递二维数组、实现棋子重绘。
4.添加组件功能
我们先写“开始”和“认输”这两个功能。
开始:
在鼠标类中
private String button;
private boolean start=false;//定义布尔值,点击开始后start=true,判断输赢后start=false
在下棋前加入判断条件
//下棋前添加判断条件:是否按了“开始”
if (start == true) {
// 判断棋子是否会越出棋盘界
if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) {
点击开始后要要清空棋盘,因此我们在Mouse类中写一个清空棋盘的方法。
为此我们要将chesspanel对象传入Mouse类中:
private boolean start = false;// 定义布尔值,点击开始后start=true,判断输赢后start=false
private MyPanel chesspanel;
//通过构造方法,传入chesspanel
public Mouse(MyPanel chesspanel) {
this.chesspanel = chesspanel;
}
在GoBang类创建mouse对象时传入chesspanel
Mouse mouse = new Mouse(chesspanel);//创建鼠标对象,并传入chesspanel
接着在Mouse中写一个clean方法:
public void clean() {
//遍历二维数组,让所有棋子颜色归零
for(int i=0;i<chessArr.length;i++) {
for(int j=0;j<chessArr[i].length;j++) {
chessArr[i][j] = 0;
}
}
//执行重绘方法,除去所有棋子
chesspanel.paint(g);
}
最后对应按钮功能
public void actionPerformed(ActionEvent e) {
button = e.getActionCommand();// 按钮内容对应鼠标点击信息
switch (button) {
case "开始"://点击开始
clean();// 清空棋盘
count = 0;//计数器清零
start = true;// 允许开始
break;
}
}
认输:
这里的“认输”功能我们采用点击按钮后弹出窗口显示游戏结束的做法,并且点击“认输”按钮后不能再下棋。我们直接写一个end方法。
// 输出游戏结束面板
public void end() {
//创建窗体
JFrame jy = new JFrame();
jy.setSize(500, 500);
jy.setLocationRelativeTo(null);
jy.setDefaultCloseOperation(3);
//设置流动布局
jy.setLayout(new FlowLayout());
//添加标签,载入图片
JLabel jla = new JLabel(new ImageIcon("D:\\java\\java\\10.16五子棋(游戏结束.png"));
//设置标签大小
jla.setPreferredSize(new Dimension(500, 500));
jy.add(jla);
jy.setVisible(true);
}
case "认输":
end();//弹出面板
start = false;//不能再下棋
break;
5.判断输赢
由于判断输赢代码量较大,我们直接新建一个Win类,在该类中写判断输赢的方法。
同样需要把chessArr传入Win类
public class Win {
private int[][] chessArr;//定义chessArr数组
//构造方法初始化chessArr数组
public Win(int[][] chessArr) {
this.chessArr = chessArr;
}
}
private boolean start = false;// 定义布尔值,点击开始后start=true,判断输赢后start=false
private MyPanel chesspanel;
Win win = new Win(chessArr);//创建win对象并传入chessArr
判断输赢的思路是:分为水平、竖直、左上-右下、右上-左下四条轴写四个方法,每条轴又分正负两个方向;每条轴设定一个计数器,通过for循环遍历同方向棋子,当棋子同色,计数器+1,最后返回计数器的值,当计数器大于等于5时,决出胜负。
// 判断水平方向
public int countchessX(int x1, int y1) {
int chess = 1;// 设置计数器记录同色棋子
// 往右侧方向
for (int i = x1 + 1; i < chessArr.length; i++) {
if (chessArr[y1][x1] == chessArr[y1][i]) {
chess++;// 如果右侧棋子同色,则计数器加1
} else {// 不同色则退出循环
break;
}
}
// 往左侧方向
for (int i = x1 - 1; i >= 0; i--) {
if (chessArr[y1][x1] == chessArr[y1][i]) {
chess++;
} else {
break;
}
}
return chess;// 返回chess值用于判断输赢
}
// 判断竖直方向
public int countchessY(int x1, int y1) {
int chess = 1;
for (int i = y1 + 1; i < chessArr.length; i++) {
if (chessArr[y1][x1] == chessArr[i][x1]) {
chess++;
} else {
break;
}
}
for (int i = y1 - 1; i >= 0; i--) {
if (chessArr[y1][x1] == chessArr[i][x1]) {
chess++;
} else {
break;
}
}
return chess;
}
// 判断左上、右下方向
public int countchessM(int x1, int y1) {
int chess = 1;
// 右下方向
for (int i = x1 + 1, j = y1 + 1; i < chessArr.length && j < chessArr.length; i++, j++) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
// 左上方向
for (int i = x1 - 1, j = y1 - 1; i >= 0 && j >= 0; i--, j--) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
return chess;
}
// 判断右上、左下方向
public int countchessN(int x1, int y1) {
int chess = 1;
// 右上方向
for (int i = x1 + 1, j = y1 - 1; i < chessArr.length && j >= 0; i++, j--) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
// 左下方向
for (int i = x1 - 1, j = y1 + 1; i >= 0 && j < chessArr.length; i--, j++) {
if (chessArr[y1][x1] == chessArr[j][i]) {
chess++;
} else {
break;
}
}
return chess;
}
// 判断输赢
public int checkwin(int x1, int y1) {
if (countchessX(x1, y1) >= 5 || countchessY(x1, y1) >= 5 || countchessM(x1, y1) >= 5
|| countchessN(x1, y1) >= 5) {
// 用最后下的棋子的颜色判断谁输谁赢。
if (chessArr[y1][x1] == 1) {//最后下黑棋
return 1;//返回1
} else if (chessArr[y1][x1] == -1) {//最后下白棋
return -1;//返回-1
}
}
return 0;
}
在Mouse类中写一个判断输赢的方法,每下完一颗棋执行一次该方法。
public void checkwin() {
//如果以满足胜负条件
if(win.checkwin(x1, y1)==1||win.checkwin(x1, y1)==-1) {
end();//执行结束游戏方法
}
}
}
count++;// 每下完一颗棋,计数器加1
checkwin();//每下完一颗棋,判断一次输赢
}
6.悔棋
悔棋思路:先创建一个棋子类存入棋子对象的坐标、颜色,再创建一个一维数组按顺序存入一个个棋子对象,接着写一个悔棋方法:每点击一次悔棋,就找出数组中最末位棋子对应的坐标,取出该坐标带入chessArr并令其等于0,然后刷新面板出去该棋子。
package teachGoBang;
import java.awt.Color;
//创建棋子类
public class ChessR {
public int x1,y1;
public Color color;
//构造方法初始化参数
public ChessR(int x1,int y1,Color color) {
this.x1 = x1;
this.y1 = y1;
this.color = color;
}
}
private int[][] chessArr = new int[line][line];// 定义二维数组,用于保存棋盘坐标对应的棋子颜色
private ChessR[] chessB =new ChessR[line*line]; //定义一维数组存入棋子对象
ChessR chess = new ChessR(x1,y1,color);//创建棋子对象存入棋子数值
chessB[count] = chess;//以count为下标存入棋子对象
count++;// 每下完一颗棋,计数器加1
checkwin();//每下完一颗棋,判断一次输赢
}
// 悔棋方法
public void regret() {
if (count > 0) {//添加判断,有棋子时才能悔棋
ChessR chessR = chessB[--count];// 取出数组中最后一颗棋子
int x = chessR.x1;// 取出该棋子对应的x、y值
int y = chessR.y1;
chessArr[y][x] = 0;// 清空该棋子对应位置
chesspanel.paint(g);
}
}
7.复盘
复盘的本质是棋子的重绘,我们在复盘前先清空前,然后设置时间间隔,通过paint方法依次绘出所下的棋子。文章来源:https://www.toymoban.com/news/detail-458061.html
// 复盘方法
public void repeat() {
for (int i = 0; i < count; i++) {
ChessR chess = chessB[i];// 通过循环,正序取出棋子
// 设置棋子重绘时间间隔
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//顺序双数绘黑棋,单数绘白棋
if(i%2==0) {
chessArr[chess.y1][chess.x1] = 1;
}else {
chessArr[chess.y1][chess.x1] = -1;
}
chesspanel.paint(g);//绘制棋子
}
count = 0;//计数器清零
}
以上就是用java写一个简单的五子棋程序的全过程,下一章将在五子棋中加入人机对战的功能。文章来源地址https://www.toymoban.com/news/detail-458061.html
到了这里,关于用Java写一个简易五子棋游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!