Java练手项目实战——五子棋游戏实现思路及源码
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();
}
}
}