Java练手项目实战——五子棋游戏实现思路及源码

时间:2025-05-09 08:32:03
package com.lyb.gobang.frame; import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class GobangFrame extends JFrame implements MouseListener { //获取屏幕的宽度和高度 int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width; int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height; //窗体大小 int frame_width = 1200; int frame_height = 920; Image bgImage = null; Image bgImage2 = null; Image menu1 = null; Image menu2 = null; Image black_piece = null; Image white_piece = null; // 保存棋子的坐标 int x = 0; int y = 0; /** * 保存棋子 * [0 :无] * [1 :黑子] * [2 : 白子] */ int[][] allPiece = new int[19][19]; // 记录上一个棋子位置 int[] lastPiece = new int[2]; // 下一步要下的是否是黑子 boolean isBlack = true; /** * 游戏状态 默认0 * [0:未开始] * [1: 已开始] * [2: 游戏结束] */ int game_status = 0; // 提示信息 String message = "黑方先行"; /** * 棋盘 * 1 [1号棋盘] * 2 [2号棋盘] */ int checkerBoard = 2; public void initUI() { readImages();//读取图片资源 setTitle("五子棋"); //设置标题 setIconImage(new ImageIcon("images/").getImage());//设置 setSize(frame_width,frame_height); setLocation((screen_width - frame_width) / 2, (screen_height - frame_height) / 2); //设置窗体出现位置 // (null);//居中显示 setResizable(false); //设置窗体大小不可改变 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗体关闭方式为关闭直接退出程序 addMouseListener(this); //为窗体添加监听器 //将窗体显示出来 this.setVisible(true); } //重写重绘方法,这里重写的是第一个大的JPanel的方法 public void paint(Graphics g) { // 双缓冲技术防止屏幕闪烁 BufferedImage bi = new BufferedImage(frame_width,frame_height,BufferedImage.TYPE_INT_ARGB); Graphics g2 = bi.createGraphics(); if (checkerBoard == 2) { g2.drawImage(bgImage2, 3 , 26 ,this); } else { g2.drawImage(bgImage, 3 , 26 ,this); // 绘制 18*18 的网格 g2.setColor(Color.black); for (int i = 0; i < 19 ; i++) { g2.drawLine(50+i*45,69,50+i*45,879); g2.drawLine(50,69+45*i,860,69+45*i); } // 标注点位 g2.fillOval(179,198,12,12);//左上 g2.fillOval(179,737,12,12);//左下 g2.fillOval(449,467,12,12);//中点 g2.fillOval(719,198,12,12);//右上 g2.fillOval(719,737,12,12);//右下 } if (game_status == 0) { g2.drawImage(menu1,897,26,this); } else { g2.drawImage(menu2,897,26,this); } // 绘制全部棋子 for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { int piece_x = i * 45 + 49; int piece_y = j * 45 + 67; if (allPiece[i][j] == 1) { // 棋子40像素 g2.drawImage(black_piece,piece_x - 20,piece_y - 20,this); } if (allPiece[i][j] == 2) { // 棋子40像素 g2.drawImage(white_piece,piece_x - 20,piece_y - 20,this); } } } // 游戏提示信息 if (game_status != 0) { g2.setFont(new Font("黑体",Font.BOLD,40));//设置字体 g2.setColor(Color.red);//设置红色 g2.drawString(message,960,190); } g.drawImage(bi,0,0,this); } public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { x = e.getX(); y = e.getY(); // 在棋盘范围中生效 {实际棋盘范围 49<=x<=859,67<=y<=877 ,判断范围边缘多出半格大小(23像素),这样更精确} if (game_status == 1) { if (x >= 26 && x <= 882 && y >= 44 && y <= 900) { // 每格45像素 int i = (x - 26) / 45; int j = (y - 44) / 45; // 记录棋子位置 lastPiece[0] = i; lastPiece[1] = j; if ( i < 19 && j < 19 && allPiece[i][j] == 0) { // 判断要下的是什么棋子 if (isBlack) { allPiece[i][j] = 1; isBlack = false; message = "轮到白方"; } else { allPiece[i][j] = 2; isBlack = true; message = "轮到黑方"; } // 重新执行paint()方法 this.repaint(); // 判断游戏是否结束(是否有同色棋子连成五个) boolean winFlag = checkWin(i,j); if (winFlag) { if (allPiece[i][j] == 1) { message = "黑方获胜"; } else { message = "白方获胜"; } JOptionPane.showMessageDialog(this,"游戏结束,"+(allPiece[i][j] == 1 ? "黑方":"白方") + "获胜!"); game_status = 2; } } else { // (this, "当前位置已有棋子,请重新落子!"); } System.out.println("棋盘内的坐标为[x:"+x+",y:"+y+"],对应位置为[x:"+i+",y:"+j+"]"); } else { System.out.println("棋盘外的坐标为[x:"+x+",y:"+y+"]"); } } else { System.out.println("棋盘外的坐标为[x:"+x+",y:"+y+"]"); } // 开始游戏和重新开始游戏 if (x >= 934 && x <= 1168 && y >= 374 && y <= 416) { if (game_status == 1) { int result = JOptionPane.showConfirmDialog(this,"是否重新开始游戏?"); /** * 重新开始游戏 * 1、棋盘数据清空 * 2、修改游戏状态 * 3、游戏提示信息修改为初始状态 * 4、下一步棋改为黑方 */ if (result == 0) { for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { allPiece[i][j] = 0; } } } message = "黑方先行"; isBlack = true; } game_status = 1; this.repaint(); } // 切换棋盘 if (x >= 934 && x <= 1168 && y >= 454 && y <= 506) { if (checkerBoard == 2) { checkerBoard = 1; } else { checkerBoard = 2; } this.repaint(); } // 悔棋 if (x >= 934 && x <= 1168 && y >= 540 && y <= 596) { int result = JOptionPane.showConfirmDialog(this,"是否同意对方悔棋?"); /** * 悔棋 * 1、上次落棋位置置空 * 2、调整下次落子颜色与上次一致 * 3、调整提示信息 * 4、游戏状态设置为已开始 */ if (result == 0) { int x_last = lastPiece[0]; int y_last = lastPiece[1]; int color = allPiece[x_last][y_last]; allPiece[lastPiece[0]][lastPiece[1]] = 0; if (color == 1) {//若为黑子 message = "轮到黑方"; isBlack = true; } else { message = "轮到白方"; isBlack = false; } game_status = 1; } this.repaint(); } // 认输 if (x >= 934 && x <= 1168 && y >= 625 && y <= 684) { int result = JOptionPane.showConfirmDialog(this,"确定要认输么?"); /** * 1、根据是谁的回合,判断是谁认输 * 2、设置游戏状态为结束状态 */ if (result == 0) { if (isBlack) { message = "白方获胜"; } else { message = "黑方获胜"; } } game_status = 2; this.repaint(); } // 退出游戏 if (x >= 934 && x <= 1168 && y >= 856 && y <= 898) { int result = JOptionPane.showConfirmDialog(this,"是否退出游戏"); if (result == 0) { System.exit(0); } } } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public boolean checkWin(int i, int j) { boolean flag = false; int color = allPiece[i][j]; // ①判断横向 int t = 1; int count = 1; while (i + t <19 && allPiece[i + t][j] == color) {//防止数组越界 t++; count++; } t = 1; while ( i -t >= 0 && allPiece[i - t][j] == color) { t++; count++; } if (count >= 5) { flag = true; } // ②判断纵向 int t2 = 1; int count2 = 1; while (j + t2 < 19 && allPiece[i][j + t2] == color) {//防止数组越界 t2++; count2++; } t2 = 1; while (j -t2 >= 0 && allPiece[i][j - t2] == color) { t2++; count2++; } if (count2 >= 5) { flag = true; } // ③判断斜向(右上+左下) int t3 = 1; int count3 = 1; while (i + t3 < 19 && j -t3 >= 0 && allPiece[i + t3][j - t3] == color) {//防止数组越界 t3++; count3++; } t3 = 1; while (i -t3 >= 0 && j + t3 < 19 && allPiece[i - t3][j + t3] == color) { t3++; count3++; } if (count3 >= 5) { flag = true; } // ③判断斜向(左上+右下) int t4 = 1; int count4 = 1; while (i - t4 >= 0 && j -t4 >= 0 && allPiece[i - t4][j - t4] == color) {//防止数组越界 t4++; count4++; } t4 = 1; while (i + t4 < 19 && j + t4 < 19 && allPiece[i + t4][j + t4] == color) { t4++; count4++; } if (count4 >= 5) { flag = true; } return flag; } public void readImages() { try { bgImage = ImageIO.read(new File("images/")); bgImage2 = ImageIO.read(new File("images/")); menu1 = ImageIO.read(new File("images/")); menu2 = ImageIO.read(new File("images/")); black_piece = ImageIO.read(new File("images/")); white_piece = ImageIO.read(new File("images/")); } catch ( IOException e) { e.printStackTrace(); } } }