在学校的Java课程中,我们被分配了一项有趣的任务:开发一款能够实现人机对弈的五子棋游戏。为了更好地理解Java GUI的运用,并与大家分享学习心得,我将整个开发过程记录在这篇博客中。欢迎大家阅读并提供宝贵的意见和建议!"
python版五子棋(讲解的更详细)
1.绘制棋盘
1.定义myPanel类。
myPanel相当于画板。
myPanel要继承 JPanel类,并要覆盖父类的paint方法,在paint方法里面写负责绘画的代码
public class myPanel extends JPanel {static final int start = 6;@Overridepublic void paint(Graphics g){//调用父类的paint初始化画笔super.paint(g);//绘制背景DrawBackground(g);//绘制外边框DrawBorder(g);//绘制棋盘DrawChessBoard(g);}public void DrawBackground(Graphics g){ //绘制背景g.setColor(new Color(211, 152, 91));g.fillRect(0, 0, 620,620);}public void DrawBorder(Graphics g){//绘制外边框g.setColor(Color.BLACK);g.fillRect(5,5,610,5);g.fillRect(610,5,5,610);g.fillRect(5,610,610,5);g.fillRect(5,5,5,610);}public void DrawChessBoard(Graphics g){g.setColor(Color.BLACK);//画横线for (int i = 0; i < 19; i++) {g.drawLine(6+i*32,6,6+i*32,614);}//画竖线for (int i = 0; i < 19; i++) {g.drawLine(6,6+i*32,614,6+i*32);}}//画棋子public void DrawChess(Graphics g,int x,int y,int type){switch (type){case 1:g.setColor(Color.BLACK);break;case 2:g.setColor(Color.WHITE);}g.fillOval(x*32+start,y*32+start,30,30);}}
2.定义myFrame类。
myFrame相当于窗口,画板要放在窗口里。
myFram要继承 JFram类,在初始化函数设置窗口参数
public class MyFrame extends JFrame {myPanel mp = null;public MyFrame() {mp = new myPanel();this.setTitle("五子棋");this.setSize(620, 620);//添加画板this.add(mp);//点击窗口叉叉退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);}static public void main(String[] args) {MyFrame mf = new MyFrame();}
}
2.核心功能
1.实现下棋功能
1.定义相关变量
//偏移量static final int IndexOffset = -10;static final int ChessOffset = -10;//黑子下棋标记static boolean black = true;boolean gameIsOver = false;int chess[][]=new int[19][19];
2.添加事件监听
myPanel实现 MouseListener接口
重写mouseClicked方法
@Overridepublic void mouseClicked(MouseEvent e) {//计算棋子坐标//# 0表示空棋//# 1表示黑棋//# 2表示白棋int x = (e.getX() - IndexOffset) / 32;int y = (e.getY() - 32 - IndexOffset) / 32;System.out.println(y);chess[x][y] = 1;this.repaint();}
myFrame添加事件监听
public MyFrame() {mp = new myPanel();this.setTitle("五子棋");this.setSize(620, 620);//添加画板this.add(mp);//点击窗口叉叉退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addMouseListener(mp);this.setVisible(true);}
2.实现自动下棋
1.按照优先级从高到低枚举出所有情况
//# 0表示空棋
//# 1表示黑棋
//# 2表示白棋
//# 3表示下棋的位置private static final int[][] cdata = {{3, 1, 1, 1, 1}, {1, 3, 1, 1, 1}, {1, 1, 3, 1, 1}, {1, 1, 1, 3, 1}, {1, 1, 1, 1, 3},{2, 2, 3, 2, 2}, {2, 2, 2, 3, 2}, {2, 3, 2, 2, 2}, {3, 2, 2, 2, 2}, {2, 2, 2, 2, 3},{3, 1, 1, 1, 0}, {1, 1, 1, 3, 0}, {1, 1, 3, 1, 0}, {1, 3, 1, 1, 0},{3, 2, 2, 2, 0}, {2, 3, 2, 2, 0}, {2, 2, 3, 2, 0}, {2, 2, 2, 3, 0},{1, 1, 3, 3, 0}, {3, 1, 1, 0, 0}, {0, 1, 3, 1, 0},{3, 2, 2, 0, 0}, {2, 2, 3, 0, 0}, {1, 3, 1, 0, 0},{3, 1, 0, 0, 0}, {1, 3, 0, 0, 0}};
2.选出最佳下棋位置
public Point getBestPoint() {//记录最低分(分值越低,优先级越高)int score = 100;//最佳位置Point point = new Point(0, 0);//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int cnt = 0;for (int[] e : cdata) {int m;int x = i;int y = j;int bestX = 0;int bestY = 0;for (m = 0; m < 5; m++) {if (e[m] == 3 && chess[x][y] == 0) {bestX = x;bestY = y;} else {if (chess[x][y] != e[m]) {break;}}x += dx[k];y += dy[k];if (x < 0 || x >= 19 || y < 0 || y >= 19) {break;}}if (m == 5) {if (cnt < score) {score = cnt;point.x = bestX;point.y = bestY;}break;}cnt++;}}}}if (score < 100) {return point;} else {int x = (int) (Math.random() * 19);int y = (int) (Math.random() * 19);while (chess[x][y] != 0) {x = (int) (Math.random() * 19);y = (int) (Math.random() * 19);}return new Point(x, y);}}
3.判断游戏是否结束
遍历棋盘
public boolean check() {//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int x = i;int y = j;int m;boolean flag = true;for (m = 0; m < 4; m++) {int tx = x + dx[k];int ty = y + dy[k];if (tx < 0 || tx > 19 || ty < 0 || ty > 19) {flag = false;break;}if (chess[x][y] != chess[x + dx[k]][y + dy[k]]) {flag = false;break;} else if (chess[x][y] == 0) {flag = false;break;}x = tx;y = ty;}if (flag) {gameIsOver = true;return true;}}}}return false;}
4.事件循环
@Overridepublic void paint(Graphics g) {//调用父类的paint初始化画笔super.paint(g);//绘制背景DrawBackground(g);//绘制外边框DrawBorder(g);//绘制棋盘DrawChessBoard(g);DrawChess(g);//开始游戏if (!gameIsOver)game();//游戏结束if (check()) {gameOver(g);}}
完整代码
myPanel
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;/*** ** @author yuwei* @date 23:29 2024/4/23*/
public class myPanel extends JPanel implements MouseListener {//偏移量static final int IndexOffset = -10;static final int ChessOffset = -10;//黑子下棋标记static boolean black = true;boolean gameIsOver = false;//# 0表示空棋
//# 1表示黑棋
//# 2表示白棋
//# 3表示下棋的位置private static final int[][] cdata = {{3, 1, 1, 1, 1}, {1, 3, 1, 1, 1}, {1, 1, 3, 1, 1}, {1, 1, 1, 3, 1}, {1, 1, 1, 1, 3},{2, 2, 3, 2, 2}, {2, 2, 2, 3, 2}, {2, 3, 2, 2, 2}, {3, 2, 2, 2, 2}, {2, 2, 2, 2, 3},{3, 1, 1, 1, 0}, {1, 1, 1, 3, 0}, {1, 1, 3, 1, 0}, {1, 3, 1, 1, 0},{3, 2, 2, 2, 0}, {2, 3, 2, 2, 0}, {2, 2, 3, 2, 0}, {2, 2, 2, 3, 0},{1, 1, 3, 3, 0}, {3, 1, 1, 0, 0}, {0, 1, 3, 1, 0},{3, 2, 2, 0, 0}, {2, 2, 3, 0, 0}, {1, 3, 1, 0, 0},{3, 1, 0, 0, 0}, {1, 3, 0, 0, 0}};int chess[][] = new int[20][20];@Overridepublic void paint(Graphics g) {//调用父类的paint初始化画笔super.paint(g);//绘制背景DrawBackground(g);//绘制外边框DrawBorder(g);//绘制棋盘DrawChessBoard(g);DrawChess(g);//开始游戏if (!gameIsOver)game();//游戏结束if (check()) {gameOver(g);}}public void gameOver(Graphics g) {Font font = new Font("Arial", Font.BOLD, 24);g.setColor(Color.red);g.setFont(font);g.drawString("游戏结束", 270, 270);}public void DrawBackground(Graphics g) { //绘制背景g.setColor(new Color(211, 152, 91));g.fillRect(0, 0, 620, 620);}public void DrawBorder(Graphics g) {//绘制外边框g.setColor(Color.BLACK);g.fillRect(5, 5, 610, 5);g.fillRect(610, 5, 5, 610);g.fillRect(5, 610, 610, 5);g.fillRect(5, 5, 5, 610);}public void DrawChessBoard(Graphics g) {g.setColor(Color.BLACK);//画横线for (int i = 0; i < 19; i++) {g.drawLine(6 + i * 32, 6, 6 + i * 32, 614);}//画竖线for (int i = 0; i < 19; i++) {g.drawLine(6, 6 + i * 32, 614, 6 + i * 32);}}//画棋子public void DrawChess(Graphics g) {for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {if (chess[i][j] == 1) {g.setColor(Color.BLACK);} else if (chess[i][j] == 2) {g.setColor(Color.WHITE);} else {continue;}g.fillOval(i * 32 + ChessOffset, j * 32 + ChessOffset, 30, 30);}}}public Point getBestPoint() {//记录最低分(分值越低,优先级越高)int score = 100;//最佳位置Point point = new Point(0, 0);//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int cnt = 0;for (int[] e : cdata) {int m;int x = i;int y = j;int bestX = 0;int bestY = 0;for (m = 0; m < 5; m++) {if (e[m] == 3 && chess[x][y] == 0) {bestX = x;bestY = y;} else {if (chess[x][y] != e[m]) {break;}}x += dx[k];y += dy[k];if (x < 0 || x >= 19 || y < 0 || y >= 19) {break;}}if (m == 5) {if (cnt < score) {score = cnt;point.x = bestX;point.y = bestY;}break;}cnt++;}}}}if (score < 100) {return point;} else {int x = (int) (Math.random() * 19);int y = (int) (Math.random() * 19);while (chess[x][y] != 0) {x = (int) (Math.random() * 19);y = (int) (Math.random() * 19);}return new Point(x, y);}}public boolean check() {//每次都要遍历四个方向 左下 下 右下 右int[] dx = {-1, 0, 1, 1};int[] dy = {1, 1, 1, 0};for (int i = 0; i < 19; i++) {for (int j = 0; j < 19; j++) {for (int k = 0; k < 4; k++) {int x = i;int y = j;int m;boolean flag = true;for (m = 0; m < 4; m++) {int tx = x + dx[k];int ty = y + dy[k];if (tx < 0 || tx > 19 || ty < 0 || ty > 19) {flag = false;break;}if (chess[x][y] != chess[x + dx[k]][y + dy[k]]) {flag = false;break;} else if (chess[x][y] == 0) {flag = false;break;}x = tx;y = ty;}if (flag) {gameIsOver = true;return true;}}}}return false;}public void game() {if (check()) {return;}if (black) {Point point = getBestPoint();chess[point.x][point.y] = 1;black = false;this.repaint();}}@Overridepublic void mouseClicked(MouseEvent e) {//计算棋子坐标//# 0表示空棋//# 1表示黑棋//# 2表示白棋if (!black&&!gameIsOver) {int x = (e.getX() - IndexOffset) / 32;int y = (e.getY() - 32 - IndexOffset) / 32;chess[x][y] = 2;black = true;this.repaint();}}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}
}
myFrame
import javax.swing.*;/*** 用户服务** @author yuwei* @date 23:42 2024/4/23*/
public class MyFrame extends JFrame {myPanel mp = null;public MyFrame() {mp = new myPanel();this.setTitle("五子棋");this.setSize(620, 620);//添加画板this.add(mp);//点击窗口叉叉退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.addMouseListener(mp);this.setVisible(true);}static public void main(String[] args) {MyFrame mf = new MyFrame();}
}
感谢阅读,希望本文对你有所帮助