** 仿照网上的实例,自己重塑了代码,并且对其中很多内容进行了注释,更加详细,很适合初学者查看。
功能:重新开始,设置时间,显示黑白两方时间,游戏说明,退出游戏,悔棋,认输,显示游戏信息
体会:刚开始写代码就是想到什么,通过这次写五子棋,知道了写一个项目之前得先想好整体格局,需要用到什么变量,需要记录什么,都先布置好格式。**
package com.dy.lkd17;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.print.attribute.ResolutionSyntax;
import javax.swing.*;
public class FiveChessFrame extends JFrame implements MouseListener, Runnable {
// 游戏界面大小
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
// 保存鼠标的坐标
int x, y;
// 保存棋盘,0为无子,1表示黑棋,2表示白棋
int[][] allChess = new int[15][15];
// 保存当下子是白棋还是黑棋,true表示黑棋,false表示白棋
boolean isBlack = true;
// 标志当前游戏是否结束
boolean canPlay = true;
// 保存游戏信息
String message = "黑方先行";
// 保存棋谱
int[] chessX = new int[255];
int[] chessY = new int[255];
int countX, countY;
// 保存最大时间
int maxTime = 0;
// 游戏时间设定的信息
String blackMessage = "无限制";
String whiteMessage = "无限制";
// 保存黑白方所剩余时间
int blackTime = 0;
int whiteTime = 0;
// 游戏倒计时线程
Thread timer = new Thread(this);
@SuppressWarnings("deprecation")
public FiveChessFrame() {
setTitle("五子棋");
setSize(500, 500);
setLocation((width - 500) / 2, (height - 500) / 2); // 窗口居中
setResizable(false); // 窗口大小不可变
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口
setVisible(true);
repaint();
addMouseListener(this);
timer.start();
timer.suspend();
}
public void paint(Graphics g) {
// 双缓冲
BufferedImage bi = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
Graphics g2 = bi.createGraphics();
g2.setColor(new Color(0, 169, 158));
g2.fill3DRect(43, 60, 375, 375, true);
// 表格左上角坐标(43,60)
// 表格大小为25
for (int i = 0; i <= 15; i++) {
g2.setColor(Color.white);
g2.drawLine(43, i * 25 + 60, 375 + 43, 60 + i * 25);
g2.drawLine(i * 25 + 43, 60, 43 + i * 25, 375 + 60);
}
g2.setFont(new Font("楷体", Font.BOLD, 20)); // 加粗
g2.drawString("游戏信息:" + message, 50, 50);
g2.drawRect(30, 440, 180, 40); //画黑棋时间矩形框架
g2.drawRect(250, 440, 180, 40); //画白棋时间矩形框架
g2.setFont(new Font("宋体", 0, 12));
g2.drawString("黑方时间:" + blackMessage, 40, 465);
g2.drawString("白方时间:" + whiteMessage, 260, 465);
// 重新开始按钮
g2.drawRect(428, 66, 54, 20);
g2.drawString("重新开始", 432, 80);
// 游戏设置按钮
g2.drawRect(428, 106, 54, 20);
g2.drawString("游戏设置", 432, 120);
// 游戏说明按钮
g2.drawRect(428, 146, 54, 20);
g2.drawString("游戏说明", 432, 160);
// 退出游戏按钮
g2.drawRect(428, 186, 54, 20);
g2.drawString("退出游戏", 432, 200);
// 悔棋
g2.drawRect(428, 246, 54, 20);
g2.drawString("悔棋", 442, 260);
// 认输
g2.drawRect(428, 286, 54, 20);
g2.drawString("认输", 442, 300);
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
// 黑子
if (allChess[i][j] == 1) {
int tempX = i * 25 + 55;
int tempY = j * 25 + 72;
g2.setColor(Color.BLACK);
g2.fillOval(tempX - 8, tempY - 8, 16, 16);
}
// 白子
if (allChess[i][j] == 2) {
int tempX = i * 25 + 55;
int tempY = j * 25 + 72;
g2.setColor(Color.WHITE); //填充为白色圆
g2.fillOval(tempX - 8, tempY - 8, 16, 16);
g2.setColor(Color.BLACK); //白色实心圆的外边框为黑色
g2.drawOval(tempX - 8, tempY - 8, 16, 16);
}
}
}
g.drawImage(bi, 0, 0, this);
}
@Override
public void run() {
// TODO Auto-generated method stub
if (maxTime > 0) {
while (true) {
if (isBlack) {
blackTime--;
if (blackTime == 0) {
JOptionPane.showMessageDialog(this, "黑方超时,游戏结束!");
}
} else {
whiteTime--;
if (whiteTime == 0) {
JOptionPane.showMessageDialog(this, "白方超时,游戏结束!");
}
}
blackMessage = blackTime / 3600 + ":"
+ (blackTime / 60 - blackTime / 3600 * 60) + ":"
+ (blackTime - blackTime / 60 * 60); //记录秒数,例如600秒,将10分钟总秒数减去9分钟的秒数,剩余一分钟递减
whiteMessage = whiteTime / 3600 + ":"
+ (whiteTime / 60 - whiteTime / 3600 * 60) + ":"
+ (whiteTime - whiteTime / 60 * 60);
this.repaint();
try {
Thread.sleep(1000); //休眠一秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace(); //在命令行打印异常信息在程序中出错的位置及原因
}
// System.out.println(blackTime + " -- " + whiteTime);
}
}
}
@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
boolean checkWin = false;
if (canPlay) {
x = e.getX(); //获取鼠标点击坐标
y = e.getY();
if (x >= 55 && x <= 405 && y >= 72 && y <= 420) {
if ((x - 55) % 25 > 12)
x = (x - 55) / 25 + 1;
else
x = (x - 55) / 25;
if ((y - 72) % 25 > 12)
y = (y - 72) / 25 + 1;
else
y = (y - 72) / 25;
if (allChess[x][y] == 0) { // 所点击的位置无子
chessX[countX++] = x; // 记录位置信息
chessY[countY++] = y;
if (isBlack) {
allChess[x][y] = 1;
isBlack = false;
message = "白方下子";
} else {
allChess[x][y] = 2;
isBlack = true;
message = "黑方下子";
}
this.repaint();
checkWin = isWin(); //下子后检查是否胜利
if (checkWin) {
if (allChess[x][y] == 1)
JOptionPane.showMessageDialog(this, "游戏结束,黑方胜利");
else
JOptionPane.showMessageDialog(this, "游戏结束,白方胜利");
canPlay = false;
}
}
}
}
// 重新开始游戏
if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 66
&& e.getY() <= 86) {
int result = JOptionPane.showConfirmDialog(this, "是否重新开始游戏?");
if (result == 0) {
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
allChess[i][j] = 0;
for (int i = 0; i < 15; i++) {
chessX[i] = 0;
chessY[i] = 0;
}
countX = 0;
countY = 0;
message = "黑方先行";
blackMessage = "无限制";
whiteMessage = "无限制";
blackTime = maxTime;
whiteTime = maxTime;
isBlack = true;
canPlay = true;
this.repaint();
}
}
// 游戏计时器设置
if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 106
&& e.getY() <= 126) {
String input = JOptionPane
.showInputDialog("请输入游戏的最大时间(分钟),如果输入0,表示时间没有限制:");
maxTime = Integer.parseInt(input) * 60;
System.out.println(maxTime);
if (maxTime < 0) {
JOptionPane.showMessageDialog(this, "输入的时间有误,请重新设置");
} else if (maxTime == 0) {
int result = JOptionPane.showConfirmDialog(this,
"游戏时间设置成功,是否开始游戏?");
if (result == 0) {
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
allChess[i][j] = 0;
for (int i = 0; i < 15; i++) {
chessX[i] = 0;
chessY[i] = 0;
}
countX = 0;
countY = 0;
message = "黑方先行";
blackMessage = "无限制";
whiteMessage = "无限制";
blackTime = maxTime;
whiteTime = maxTime;
isBlack = true;
canPlay = true;
this.repaint();
}
} else if (maxTime > 0) {
int result = JOptionPane.showConfirmDialog(this,
"游戏时间设置成功,是否开始游戏?");
if (result == 0) {
if (result == 0) {
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
allChess[i][j] = 0;
for (int i = 0; i < 15; i++) {
chessX[i] = -1;
chessY[i] = -1;
}
countX = 0;
countY = 0;
message = "黑方先行";
isBlack = true;
blackMessage = maxTime / 3600 + ":"
+ (maxTime / 60 - maxTime / 3600 * 60) + ":"
+ (maxTime - maxTime / 60 * 60);
whiteMessage = maxTime / 3600 + ":"
+ (maxTime / 60 - maxTime / 3600 * 60) + ":"
+ (maxTime - maxTime / 60 * 60);
blackTime = maxTime;
whiteTime = maxTime;
System.out
.println(blackMessage + " - -" + whiteMessage);
timer.resume(); //开始计时
this.canPlay = true;
this.repaint();
}
}
}
}
// 游戏说明
if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 146
&& e.getY() <= 166) {
JOptionPane.showMessageDialog(this, "简单一句:横竖斜先连成五子者获胜!");
}
// 退出游戏
if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 186
&& e.getY() <= 206) {
int result = JOptionPane.showConfirmDialog(this, "是否退出游戏?");
if (result == 0) {
System.exit(0);
}
}
// 悔棋
if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 246
&& e.getY() <= 266) {
int result = JOptionPane.showConfirmDialog(this, //判断接下来为哪一方下棋,如果轮到黑方,则说悔棋的就是白方
(isBlack == true ? "白方悔棋,黑方是否同意?" : "黑方悔棋,白方是否同意?"));
if (result == 0) {
allChess[chessX[--countX]][chessY[--countY]] = 0; //将当前位置改为无子,并且将坐标返回一次
isBlack = (isBlack == true) ? false : true; //悔棋的一方重新下子,如果轮到黑方,则应该返回false,白方下棋
this.repaint();
}
}
// 认输
if (e.getX() >= 428 && e.getX() <= 482 && e.getY() >= 286
&& e.getY() <= 306) {
int result = JOptionPane.showConfirmDialog(this, "是否认输?");
if (result == 0) {
JOptionPane.showMessageDialog(this, "游戏结束,"
+ (isBlack == true ? "黑方认输,白方获胜!" : "白方认输,黑方获胜!"));
}
}
}
private boolean isWin() {
// TODO Auto-generated method stub
boolean flag = false;
// 保存共有多少种颜色的棋子相连
int count = 1;
// 判断横向是否有5个棋子相连,特点纵坐标相同,即allChess[x][y]中y值是相同
int color = allChess[x][y];
// 判断横向
count = this.checkCount(1, 0, color);
if (count >= 5) {
flag = true;
} else {
// 判断纵向
count = this.checkCount(0, 1, color);
if (count >= 5) {
flag = true;
} else {
// 判断右上,左下
count = this.checkCount(1, -1, color);
if (count >= 5) {
flag = true;
} else {
// 判断右下,左上
count = this.checkCount(1, 1, color);
if (count >= 5) {
flag = true;
}
}
}
}
return flag;
}
private int checkCount(int xChange, int yChange, int color) {
int count = 1;
int tempX = xChange; //为向另外个方向记录坐标
int tempY = yChange;
while (x + xChange >= 0 && x + xChange <= 14 && y + yChange >= 0
&& y + yChange <= 14
&& color == allChess[x + xChange][y + yChange]) {
count++;
if (xChange != 0)
xChange++;
if (yChange != 0) {
if (yChange > 0)
yChange++;
else {
yChange--;
}
}
}
xChange = tempX;
yChange = tempY;
while (x - xChange >= 0 && x - xChange <= 14 && y - yChange >= 0
&& y - yChange <= 14
&& color == allChess[x - xChange][y - yChange]) {
count++;
if (xChange != 0)
xChange++;
if (yChange != 0) {
if (yChange > 0)
yChange++;
else {
yChange--;
}
}
}
return count;
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
public static void main(String[] args) { // 主方法
new FiveChessFrame();
}
}