package org.gpf.game.frame;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class FiveChessFrame extends JFrame implements MouseListener,Runnable,MouseMotionListener {
private static final long serialVersionUID = 1L;
int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width; // 获得屏幕尺寸
int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
int x = 0, y = 0; // 棋子坐标
int[][] allChess = new int[19][19]; // 保存之前下过的棋子的状态,0表示没有棋子,1黑子,2白子
String message = "黑方先行";
boolean isBlack = true; // 判断当前是黑棋还是白棋进行下一步
boolean canPlay = true; // 判断是否可以落下棋子
BufferedImage bgImage = null; // 背景图片
int maxTime = 0; // 保存最多拥有的时间(秒)
Thread thread = new Thread(this); // 倒计时的线程类
int balckTime = 0,whiteTime = 0; // 黑方和白方的剩余时间
String balckMessage = "00:00:00",whiteMessage = "00:00:00"; // 保存双方剩余时间的显示信息,默认是0表示无限制
boolean musicOn = true; // 是否开启背景音乐
Thread bgMusicThread = new Thread(new BgMusic()); // 背景音乐线程
Cursor cursor = null; // 十字光标
@SuppressWarnings("deprecation")
public FiveChessFrame(int width, int height) throws LineUnavailableException {
this.setTitle("五子棋游戏");
this.setSize(width, height);
this.setLocation((screenWidth - width) / 2, (screenHeight - height) / 2); // 游戏窗体居中显示
this.setResizable(false); // 窗体大小不可变
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addMouseListener(this); // 注册鼠标监听事件
this.addMouseMotionListener(this);
this.setVisible(true);
cursor = new Cursor();
thread.start();
thread.suspend(); // 计时线程挂起
if (musicOn) {
bgMusicThread.start();
}
this.repaint(); // 刷新屏幕,解决启动游戏时的黑屏问题
}
/**
* 渲染界面元素
*/
@Override
public void paint(Graphics g) {
/* 加载背景图片 */
try {
bgImage = ImageIO.read(new File("res/bg.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
boolean flag = g.drawImage(bgImage, 0, 0, this);
if (flag) {
System.out.println("图片加载成功!");
}
/* 文字信息的设置 */
g.setFont(new Font("黑体", Font.BOLD, 20));
g.setColor(Color.YELLOW);
g.drawString("游戏信息:" + message, 150, 60);
g.setFont(new Font("宋体", Font.PLAIN, 18));
g.setColor(Color.GREEN);
g.drawString("黑方时间:" + balckMessage, 30, 550);
g.drawString("白方时间:" + whiteMessage, 300, 550);
g.setFont(new Font("楷体", Font.BOLD, 18));
g.setColor(Color.CYAN);
g.drawRect(530, 100, 100, 30);
g.drawString("新游戏", 552, 123);
g.drawRect(530, 170, 100, 30);
g.drawString("游戏设置", 545, 193);
g.drawRect(530, 240, 100, 30);
g.drawString("游戏说明", 545, 263);
g.drawRect(530, 300, 100, 30);
g.drawString("音乐" + (musicOn?"开":"关"), 545, 320);
g.drawRect(530, 350, 100, 30);
g.drawString("认输", 555, 373);
g.drawRect(530, 420, 100, 30);
g.drawString("关于", 555, 443);
g.drawRect(530, 490, 100, 30);
g.drawString("退出", 555, 513);
g.setColor(Color.RED);
g.setFont(new Font("楷体", Font.BOLD, 28));
g.drawString("你若安好,便是晴天。", 320, 590);
g.setColor(Color.ORANGE);
/* 初始化棋盘格(18 * 18) */
for (int i = 0; i < 19; i++) {
g.drawLine(15, 70 + 25 * i, 465, 70 + 25 * i); // 绘制横线
g.drawLine(15 + 25 * i, 70, 15 + 25 * i, 520);// 绘制竖线
}
if (cursor.show) {
g.drawImage(cursor.cursorImage, cursor.point.x - cursor.width/2, cursor.point.y - cursor.width/2,null);
}
/* 标注9个特殊点位 */
g.setColor(Color.MAGENTA);
for (int i = 0; i < 3; i++) {
for(int j = 0;j < 3;j++){
g.fillOval(7 + 3 * 25 + 150 * i, 63 + 3 * 25 + 150 * j, 15, 15);
}
}
/* 绘制全部棋子 */
g.setColor(Color.BLACK);
for(int i = 0;i < 19;i++){
for(int j = 0;j < 19;j++){
int tempX = 25 * i + 15; // 得到棋子的准确坐标
int tempY = 25 * j + 70;
cursor.point.x = tempX;
cursor.point.y = tempY;
if (allChess[i][j] == 1) {
// 绘制黑子
g.fillOval(tempX - 11, tempY - 11, 22, 22);
}
if (allChess[i][j] == 2) {
// 绘制白子
g.setColor(Color.WHITE);
g.fillOval(tempX - 11, tempY - 11, 22, 22);
g.setColor(Color.BLACK);
g.drawOval(tempX - 11, tempY - 11, 22, 22);
}
}
}
}
@Override
public void mouseClicked(MouseEvent e) {
cursor.show = false;
x = e.getX(); // 得到鼠标的点击位置
y = e.getY();
System.out.println("点击坐标:(" + x + "," + y + ")");
if (canPlay) {
/* 判断点击的坐标是否在18*18的范围之内 */
if (x >= 15 && x <= 465 && y >= 70 && y <= 520) {
// x = (x - 15) / 25; // 得到最近的十字点,可以先得到0~18的整数,然后通过这个整数乘以每行的间距完成
// y = (y - 70) / 25;
/* 以上的判定存在误差,如果x坐标大于单元格的中线,棋子应该落入右侧的十字线,y坐标同理 */
if (((x - 15) % 25) >= 13) {
x = ((x - 15) / 25) + 1;
} else
x = (x - 15) / 25;
if (((y - 70) % 25) >= 13) {
y = ((y - 70) / 25) + 1;
} else
y = (y - 70) / 25;
System.out.println("x = " + x + ", y = " + y);
System.out.println("allChess[x][y] = " + allChess[x][y]);
if (allChess[x][y] == 0) {
/* 判断当前要下的是什么棋子? */
if (isBlack) {
allChess[x][y] = 1;
isBlack = false;
message = "轮到白方";
} else {
allChess[x][y] = 2;
isBlack = true;
message = "轮到黑方";
}
/* 判断当前棋子是否和其他棋子5连? */
boolean winFlag = this.checkWin();
if (winFlag) {
JOptionPane.showMessageDialog(this, "游戏结束," + (allChess[x][y] == 1 ? "黑方赢了" : "白方赢了"));
canPlay = false;
}
} else {
JOptionPane.showMessageDialog(this, "当前位置已有棋子,请重新落子!");
}
this.repaint();
}
}
// 点击开始新游戏按钮
if (x >= 530 && x <= 630 && y >= 100 && y <= 130) {
int result = JOptionPane.showConfirmDialog(this, "开始新游戏,棋盘棋子将清空,确认开始新游戏?");
if (JOptionPane.OK_OPTION == result) {
clearAllCheese();
}
}
// 点击游戏设置按钮
if (x >= 530 && x <= 630 && y >= 170 && y <= 200) {
String input = JOptionPane.showInputDialog("请输入游戏时间(单位:分钟),输入0表示没有时间限制:");
try {
maxTime = Integer.parseInt(input) * 60;
while (maxTime < 0) {
JOptionPane.showMessageDialog(this, "请输入正确信息,不允许输入负数!");
input = JOptionPane.showInputDialog("请输入游戏时间(单位:分钟),输入0表示没有时间限制:");
maxTime = Integer.parseInt(input) * 60;
}
if (maxTime == 0) {
int result = JOptionPane.showConfirmDialog(this, "设置完成,是否重新开始游戏?");
if (JOptionPane.OK_OPTION == result) {
clearAllCheese();
}
}
if (maxTime > 0) {
int result = JOptionPane.showConfirmDialog(this, "设置完成,是否重新开始游戏?");
if (JOptionPane.OK_OPTION == result) {
clearAllCheese();
}
}
} catch (NumberFormatException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(th
- 1
- 2
- 3
前往页