前言
因为我的拼图游戏是跟着视频慢慢做的,所以我想自己独立完成一个小游戏的制作。五子棋是一个可以验证我这段时间的学习成果以及巩固知识的小项目,所以今天我打算做一个简单双人五子棋对战游戏。
难点
1,JPanel的使用:
因为我以前没用过哈哈哈,所以在开始前我先学习了一下JPanel的使用,那我为什么学习JPanel呢?在查阅资料的时候,发现JFrame其实是主要容器,画图在JPanel上会分工更加明确,规划更加合理,效率更高,减少卡顿。)
2,判断是否结束游戏:
游戏的胜利即相同颜色五个棋子连在一起,那我应该怎么去判断呢?首先你要知道现在下的是哪个棋子,也就是判断正在下完这一手是否能够触发胜利条件。如刚刚所说,五个棋子连在一起(水平方向,竖直方向,左上右下,右下左上)就算成功,那么我们只要对这四种情况进行相连数量判断就可以了,如果撞到边界或者碰到其他颜色棋子就break,若棋子颜色相同就count++,一旦有任何一个方向count==5,那则可结束游戏。
实现效果
可以看见这个棋盘是由:主棋盘,棋子(黑白),计数器,下棋方提醒,重新游戏按钮以及结束弹窗组成。
源码
废话不多说,因为是第二个项目所用知识点与上一个拼图小游戏相似我就不多描述了,直接上代码!
·APP
package GobangGame;
public class APP {
public static void main(String[] args) {
new GameJFrame();
}
}
·Chessboard(最主要的)
package GobangGame;
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;
public class Chessboard extends JPanel implements MouseListener, ActionListener {
private static final int HEIGHT = 660;
private static final int WIDTH = 620;
private static final int SIZE = 15;//棋盘15*15
private static final int CELL_SIZE = 40;//格子长宽
private static final int MARGIN = 30;//边距
private JLabel countJL;
private JLabel playerJL;
private JButton ReGameBT;
private int x;
private int y;
private int step = 0;
private String player = "黑方";
private int[][] arr = new int[SIZE][SIZE];//0空,1白,2黑
public Chessboard() {
this.setBackground(Color.yellow);
relatedmod();
this.addMouseListener(this);
}
private void relatedmod() {
countJL = new JLabel("计步器:" + step);
playerJL = new JLabel("下棋方:" + player);
ReGameBT=new JButton();
ReGameBT.setText("重新开始");
ReGameBT.setPreferredSize(new Dimension(100,20));
ReGameBT.addActionListener(this);
this.add(ReGameBT);
this.add(countJL);
this.add(playerJL);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
drawboard(g);
if (step == 0) {
return;
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
if (arr[i][j] == 1) {
DrawWhite(g, i, j);
} else if (arr[i][j] == 2) {
DrawBlcak(g, i, j);
}
}
}
}
private void DrawBlcak(Graphics g, int x, int y) {
g.setColor(Color.BLACK);
int BlackOvalx = MARGIN + x * CELL_SIZE - CELL_SIZE / 4;
int BlackOvaly = MARGIN + y * CELL_SIZE - CELL_SIZE / 4;
g.fillOval(BlackOvalx, BlackOvaly, CELL_SIZE / 2, CELL_SIZE / 2);
}
private void DrawWhite(Graphics g, int x, int y) {
g.setColor(Color.WHITE);
int WhiteOvalx = MARGIN + x * CELL_SIZE - CELL_SIZE / 4;
int WhiteOvaly = MARGIN + y * CELL_SIZE - CELL_SIZE / 4;
g.fillOval(WhiteOvalx, WhiteOvaly, CELL_SIZE / 2, CELL_SIZE / 2);
}
private static void drawboard(Graphics g) {
for (int i = 0; i < SIZE; i++) {
g.drawLine(MARGIN, MARGIN + i * CELL_SIZE, WIDTH - MARGIN, MARGIN + i * CELL_SIZE);
}
for (int i = 0; i < SIZE; i++) {
g.drawLine(MARGIN + i * CELL_SIZE, MARGIN, MARGIN + i * CELL_SIZE, WIDTH - MARGIN);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
@Override
public void mouseClicked(MouseEvent e) {
int mousex = e.getX();
int mousey = e.getY();
System.out.println("mousex=" + mousex + " " + "mousey=" + mousey);
//判断落子位置
x = (mousex - MARGIN + CELL_SIZE / 2) / CELL_SIZE;
y = (mousey - MARGIN + CELL_SIZE / 2) / CELL_SIZE;
System.out.println("x=" + x + " " + "y=" + y);
//边缘判断
if (x > 14 || x < 0 || y > 14 || y < 0) {
return;
}
//是否重复下棋判断
if (arr[x][y] != 0) {
return;
}
//录入位置信息
if (step % 2 == 0) {
arr[x][y] = 1;
//切换玩家
player = "黑方";
} else if (step % 2 == 1) {
arr[x][y] = 2;
//切换玩家
player = "白方";
}
System.out.println("成功下棋");
step++;
//重绘,重新调用paintComponent,更新画面
repaint();
updateLabels();
//传入当前坐标,确定棋子颜色以及通过坐标判断是否结束游戏
boolean flag = judgewin(x, y);
if (flag){
showJDialog("游戏结束!");
}
}
private void ReGame() {
//重置数据
arr=new int[SIZE][SIZE];
step=0;
player="黑方";
//重新加载
updateLabels();
repaint();
}
public void showJDialog(String content) {
//创建一个弹框对象
JDialog jDialog = new JDialog();
//给弹框设置大小
jDialog.setSize(200, 150);
//让弹框置顶
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭永远无法操作下面的界面
jDialog.setModal(true);
//创建Jlabel对象管理文字并添加到弹框当中
JLabel warning = new JLabel(content);
warning.setBounds(0, 0, 200, 150);
jDialog.getContentPane().add(warning);
//让弹框展示出来
jDialog.setVisible(true);
}
private boolean judgewin(int x, int y) {
//判断当前玩家
int currentpalyer = arr[x][y];
//横向判断
boolean flag1 = level(x, y, currentpalyer);
//纵向判断
boolean flag2 = vertical(x, y, currentpalyer);
//右上左下判断
boolean flag3 = topright(x, y, currentpalyer);
//左上右下判断
boolean flag4 = topleft(x, y, currentpalyer);
if (flag1 || flag2 || flag3 || flag4) {
return true;
} else {
return false;
}
}
private boolean topleft(int x, int y, int currentpalyer) {
int count = 1;
//向左上检查
for (int i = 1; i < SIZE; i++) {
if ((x-i<0)||(x-i>=SIZE)||(y-i<0)||(y-i>=SIZE))break;
if (arr[x -i][y - i] != currentpalyer) {
break;
} else {
count++;
}
}
//向右下检查
for (int i = 1; i < SIZE; i++) {
if ((x+i<0)||(x+i>=SIZE)||(y+i<0)||(y+i>=SIZE))break;
if (arr[x + i][y + i] != currentpalyer) {
break;
} else {
count++;
}
}
if (count >= 5) {
return true;
} else {
return false;
}
}
private boolean topright(int x, int y, int currentpalyer) {
int count = 1;
//向右上检查
for (int i = 1; i < SIZE; i++) {
if ((x+i<0)||(x+i>=SIZE)||(y-i<0)||(y-i>=SIZE))break;
if (arr[x + i][y - i] != currentpalyer) {
break;
} else {
count++;
}
}
//向左下检查
for (int i = 1; i <SIZE; i++) {
if ((x-i<0)||(x-i>=SIZE)||(y+i<0)||(y+i>=SIZE))break;
if (arr[x - i][y + i] != currentpalyer) {
break;
} else {
count++;
}
}
if (count >= 5) {
return true;
} else {
return false;
}
}
private boolean level(int x, int y, int currentpalyer) {
int count = 1;
//向右检查
for (int i = 1; i < SIZE; i++) {
if ((x+i<0)||(x+i>=SIZE)||(y<0)||(y>=SIZE))break;
if (arr[x + i][y] != currentpalyer) {
break;
} else {
count++;
}
}
//向左检查
for (int i = 1; i <SIZE; i++) {
if ((x-i<0)||(x-i>=SIZE)||(y<0)||(y>=SIZE))break;
if (arr[x - i][y] != currentpalyer) {
break;
} else {
count++;
}
}
//判断是否结束
if (count >= 5) {
return true;
} else {
return false;
}
}
private boolean vertical(int x, int y, int currentpalyer) {
int count = 1;
//向下检查
for (int i = 1; i < SIZE; i++) {
if ((x<0)||(x>=SIZE)||(y+i<0)||(y+i>=SIZE))break;
if (arr[x][y + i] != currentpalyer) {
break;
} else {
count++;
}
}
//向上检查
for (int i = 1; i <SIZE; i++) {
if ((x<0)||(x>=SIZE)||(y-i<0)||(y-i>=SIZE))break;
if (arr[x][y - i] != currentpalyer) {
break;
} else {
count++;
}
}
//判断是否结束
if (count >= 5) {
return true;
} else {
return false;
}
}
private void updateLabels() {
countJL.setText("计步器:" + step);
playerJL.setText("下棋方:" + player);
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
ReGame();
}
}
·GameJFrame
package GobangGame;
import javax.swing.*;
import java.awt.*;
import java.awt.image.ImageObserver;
import java.text.AttributedCharacterIterator;
public class GameJFrame extends JFrame{
//空参构造,main函数new出GameJFrame的时候即执行
public GameJFrame(){
//初始窗体
initjframe();
this.add(new Chessboard());
}
private void initjframe() {
this.setSize(620,660);
this.setTitle("双人五子棋对战小游戏");
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
FlowLayout flowLayout=new FlowLayout();
this.setLayout(flowLayout);
this.setVisible(true);
}
}
·Test
test没啥好说的就是测试类,我来测试代码运行的,嘻嘻
写在最后
因为是自己写的代码,测试了几十次和用ai测试了没显示太大问题,但可能存在隐性问题。
如果发现我代码存在的问题请在评论区告诉我,十分感谢!