五子棋2.0(Java)
程序员文章站
2022-06-21 15:14:03
简介相比之前,做出了以下修改:1.新增菜单栏,将重新开始和退出的按钮移到了菜单栏;2.可以实时显示时间(多线程);3.下棋时可以显示当前是哪一方在下棋;4.可以更改背景颜色;5.可以更改先行方(默认黑子)。结果完整代码1.Frame.java(主界面)package Gobang;import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.awt.image.*;//import...
简介
相比之前,做出了以下修改:
1.新增菜单栏,将重新开始和退出的按钮移到了菜单栏;
2.可以实时显示时间(多线程);
3.下棋时可以显示当前是哪一方在下棋;
4.可以更改背景颜色;
5.可以更改先行方(默认黑子)。
结果
完整代码
1.Frame.java(主界面)
package Gobang;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
//import java.applet.*;
//import java.net.*;
//import java.io.*;
//import javax.imageio.*;
public class Frame extends JFrame implements MouseListener,ActionListener{//JFrame的扩展类
//ImageIcon image;
//JLayeredPane layeredPane;
//JPanel jp;
/*本来想用于播放背景音乐,但是没有成功,,,先暂时放弃
File f;
URI uri;
URL url;
@SuppressWarnings("deprecation")
*/
private static final long serialVersionUID = 1L;
public JButton AdmitDefeatButton,RegretButton;//两个按钮,各有其功能。
JLabel TimeLabel;//用来显示时间
JLabel jl1,jl2,jl3;//游戏信息
Graphics g;//画笔
BufferedImage buf;
int x;//鼠标的坐标
int y;
int[][] Chess = new int[20][20]; // 保存棋子,1表示黑子,2表示白子
boolean IsBlack = true; //表示当前要下的是黑子还是白子,true表示黑子,false表示白子
boolean IsFinish = false; //表示当前游戏是否结束
int xRange;
int yRange;
int[] chessX = new int[400];//用来保存从开始到当前的所有棋子,用于悔棋;
int[] chessY = new int[400];
int countX = 0;
int countY = 0;
//菜单栏
JMenuBar menubar;
JMenu menu;
JMenu setmenu;
JMenuItem RestartItem,ExitItem,IntroItem,BackgroundItem,FirstItem;
//获取屏幕的宽度和高度
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
public Frame() {
/*插入背景图片
//layeredPane=new JLayeredPane();
//image=new ImageIcon("F:\\JAVA\\eclipse-workspace\\Gobang\\src\\1.jpg");//随便找一张图就可以看到效果。
//jp=new JPanel();
//jp.setBounds(0,0,600,600);
//jl=new JLabel(image);
//jl.setBounds(0,0,image.getIconWidth(),image.getIconHeight());
//jp.add(jl);
//layeredPane.add(jp,JLayeredPane.DEFAULT_LAYER);
//this.setLayeredPane(layeredPane);
*/
/*音频播放部分
try {
f = new File("");
uri = f.toURI();
url = uri.toURL();
AudioClip aau;
aau = Applet.newAudioClip(url);
aau.loop(); //循环播放
} catch (Exception e)
{
e.printStackTrace();
}
*/
//设置标题、大小、排列方式等
this.setTitle("五子棋");
this.setSize(600,600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setLayout(null);
int height = this.getHeight();
int width = this.getWidth();
this.setLocation(screenWidth/2-width/2, screenHeight/2-height/2);
//实时显示时间,用到多线程来实时显示。
jl1 = new JLabel("北京时间");
jl1.setLocation(430, 120);
jl1.setSize(80,20);
this.add(jl1);
TimeLabel = new JLabel();
new Thread(new Time(TimeLabel)).start();//新建一个线程
TimeLabel.setLocation(510, 120);
TimeLabel.setSize(80,20);
this.add(TimeLabel);
//显示游戏信息,当前是谁执子;
jl2 = new JLabel("游戏信息");
jl2.setLocation(430, 150);
jl2.setSize(80,20);
jl3 = new JLabel("黑方先行");
jl3.setLocation(510, 150);
jl3.setSize(80,20);
this.add(jl2);
this.add(jl3);
//设置背景颜色
this.getContentPane().setBackground(new Color(255, 239 ,213));
this.getContentPane().setVisible(true);
//设置菜单栏
menubar = new JMenuBar();//菜单栏
menu = new JMenu("游戏操作");
RestartItem = new JMenuItem("重新开始");
ExitItem = new JMenuItem("退出");
menu.add(RestartItem);
menu.add(ExitItem);
menubar.add(menu);
setmenu = new JMenu("设置");
IntroItem = new JMenuItem("游戏说明");
BackgroundItem = new JMenuItem("背景颜色");
FirstItem = new JMenuItem("先行方");
setmenu.add(IntroItem);
setmenu.add(BackgroundItem);
setmenu.add(FirstItem);
menubar.add(setmenu);
menubar.setBackground(new Color(249,205,173));
menubar.setVisible(true);
this.setJMenuBar(menubar);
//两个按钮,认输和悔棋;
AdmitDefeatButton = new JButton("认输");
AdmitDefeatButton.setSize(80,40);
AdmitDefeatButton.setLocation(120, 480);
RegretButton = new JButton("悔棋" );
RegretButton.setSize(80,40);
RegretButton.setLocation(240, 480);
this.add(AdmitDefeatButton);
this.add(RegretButton);
/*
五个按钮添加到中间容器;
panel1 = new JPanel();
panel1.setBorder(BorderFactory.createLoweredBevelBorder()); //设置边框
panel1.setLayout(new GridLayout(1,5));
panel1.add(RestartButton);
panel1.add(SetButton);
panel1.add(AdmitDefeatButton);
panel1.add(RegretButton);
panel1.add(ExitButton);
this.add(panel1);
panel1.setSize(460,30);
panel1.setLocation(0, 460);
*/
this.repaint();//表示重新绘制画布,可以自动调用paint函数;
//本类作为监听类,包括鼠标监听和按钮动作监听;
this.addMouseListener(this);
IntroItem.addActionListener(this);
BackgroundItem.addActionListener(this);
FirstItem.addActionListener(this);
RestartItem.addActionListener(this);
AdmitDefeatButton.addActionListener(this);
RegretButton.addActionListener(this);
ExitItem.addActionListener(this);
}
//画布绘制
public void paint(Graphics g)
{
if(g == null)//如果第一次绘制,新建一个图片,并且创建画布。
{
buf = new BufferedImage(450, 450, BufferedImage.TYPE_INT_RGB);
g = buf.createGraphics();
}
if(g != null)//
{
super.paint(g);//表示在原来图像的基础上,再画图
g.setColor(new Color(249,205,173));//画笔颜色调成褐色;
g.fill3DRect(20, 130, 400, 400,true);//用画笔画一个边长为400的正方形;边距为20,130
for(int i = 0; i <= 20; i++)//用画笔横竖各画19条线
{
g.setColor(Color.BLACK);//画笔颜色调为黑色;
g.drawLine(20,130+i*20,420,130+i*20);
g.drawLine(20+i*20,130,20+i*20,530);
}
}
for(int i=0; i<20; i++){
for (int j = 0; j < 20; j++) {
//画实心黑子,直径16
if(Chess[i][j] == 1){
int tempX = i*20+12;
int tempY = j*20+122;
g.setColor(Color.BLACK);
g.fillOval(tempX, tempY, 16, 16);
g.setColor(Color.BLACK);
g.drawOval(tempX, tempY, 16, 16);
}
//画实心白子,直径16
if(Chess[i][j] == 2){
int tempX = i*20+12;
int tempY = j*20+122;
g.setColor(Color.WHITE);
g.fillOval(tempX, tempY, 16, 16);
g.setColor(Color.WHITE);
g.drawOval(tempX, tempY, 16, 16);
}
}
}
g.drawImage(buf, 0, 0,this);
}
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if(!IsFinish) //判断棋局是否结束
{
x = e.getX(); //获取当前鼠标点击位置
y = e.getY();
if(x >= 20 && x < 420 && y >= 130 && y<= 530)//判断鼠标是否在棋局内
{
xRange = (x-20)%20;
if(xRange > 10 && xRange < 20) //如果在交叉点的边长为10的范围内,就把棋子下在这;
{
x = (x - 20) / 20 + 1;
}
else
{
x = (x - 20) / 20;
}
yRange = (y-130)%20;
if(yRange > 10 && yRange < 20)
{
y = (y - 130) / 20 + 1;
}
else
{
y = (y - 130) / 20;
}
if(Chess[x][y] == 0) //如果该交叉点没有被下过;
{
chessX[countX++] = x; //存储当前棋子的位置;
chessY[countY++] = y;
if(jl3.getText().equals("黑方先行")) //如果是黑子
{
Chess[x][y] = 1;
IsBlack = false;
jl3.setText("白方先行");
}
else if(jl3.getText().equals("白方先行"))
{
Chess[x][y] = 2;
IsBlack = true;
jl3.setText("黑方先行");
}
this.repaint();//重新绘制画布
}
if(this.isWin())//如果下棋之后赢了,弹出对话框
{
if(Chess[x][y] == 1)
{
JOptionPane.showMessageDialog(this, "黑方胜利");
}
else
{
JOptionPane.showMessageDialog(this, "白方胜利");
}
this.IsFinish = true; //游戏结束
}
}
}
}
public boolean isWin(){
boolean flag = false;
int count = 1;
int color = Chess[x][y];
//判断横向是否有5个棋子相连
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;
}
// 检查棋盘中的五子棋是否连成五子,xChange,yChange为相对于当前棋子位置的变化量
public int checkCount(int xChange , int yChange ,int color){
int count = 1;//统计总共有几个连着的棋子;
int tempX = xChange;
int tempy = yChange;
//判断棋子右边有没有相同颜色的棋子;
while(x + xChange >=0 && x+xChange <20 && y+yChange >=0 &&
y+yChange < 20 && color == Chess[x+xChange][y+yChange])
{
count++; //如果有,棋子数加一
if(xChange != 0)
xChange++; //如果横向方向变化,x相对位置加一
if(yChange != 0 )
{
if(yChange != 0)
{
if(yChange > 0) //如果纵向方向增加,y相对位置加一
{
yChange++;
}
else //如果纵向方向减小,y相对位置减一
{
yChange--;
}
}
}
}
xChange = tempX;
yChange = tempy;
//判断棋子左边有没有相同颜色的棋子;
while(x-xChange >=0 && x-xChange <20 && y-yChange >=0 &&
y-yChange <20 && color == Chess[x-xChange][y-yChange])
{
count++;
if(xChange != 0)
{
xChange++;
}
if(yChange != 0)
{
if (yChange > 0)
{
yChange++;
}
else
{
yChange--;
}
}
}
return count;
}
//监听动作函数
//@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getActionCommand()=="重新开始")//如果点击的按钮是RestartButton,清空画板,还原设置
{
if(JOptionPane.showConfirmDialog(this, "是否重新开始游戏?") == 0)
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
Chess[i][j] = 0; //清空棋盘的棋子
}
}
//清空下棋棋子坐标的记录
for (int i = 0; i < 400; i++)
{
chessX[i] = 0;
chessY[i] = 0;
}
countX =0;
countY =0;
IsBlack = true;
jl3.setText("黑方先行");
IsFinish = false;
this.repaint();
}
}
if(e.getSource() == AdmitDefeatButton)//如果点击的按钮是AdmitDefeatButton,结束游戏,并提示
{
if(!IsFinish) //判断棋局是否结束
{
if(JOptionPane.showConfirmDialog(this, "是否确定认输?") == 0)
{
if(IsBlack == true)
{
JOptionPane.showMessageDialog(this,"白方获胜");
}
else
{
JOptionPane.showMessageDialog(this,"黑方获胜");
}
IsFinish = true;
}
}
}
if(e.getActionCommand()=="退出")//如果点击的按钮是ExitButton,退出程序
{
if(JOptionPane.showConfirmDialog(this, "是否确定退出?") == 0)
{
System.exit(0);
}
}
if(e.getSource() == RegretButton)///如果点击的按钮是RegretButton,悔棋一步
{
if(!IsFinish) //判断棋局是否结束
{
if(IsBlack == true) //如果现在是黑子要下,表示悔棋的是白子
{
if(JOptionPane.showConfirmDialog(this, "白方想要悔棋,是否同意?") == 0)
{
int tempX = chessX[--countX]; //获取上一步白子下的位置;
int tempY = chessY[--countY];
Chess[tempX][tempY] = 0; //撤回白子
IsBlack = false; //当前要下的变为白方
jl3.setText("白方先行");
}
}
else
{
if(JOptionPane.showConfirmDialog(this, "黑方想要悔棋?") == 0)
{
int tempX = chessX[--countX];
int tempY = chessY[--countY];
Chess[tempX][tempY] = 0;
IsBlack = true;
jl3.setText("黑方先行");
}
}
this.repaint(); //重新绘制画布
}
}
if(e.getActionCommand()=="游戏说明")
{
JDialog frame1 = new JDialog();//新建对话框
frame1.setSize(200,200);
int height = frame1.getHeight();
int width = frame1.getWidth();
frame1.setLocation(screenWidth/2-width/2, screenHeight/2-height/2);
JTextArea ta = new JTextArea();//新建文本框
ta.setText("双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连线者获胜。");
ta.setEditable(false);
JScrollPane jsp = new JScrollPane(ta);
frame1.setTitle("规则");
frame1.getContentPane().add(jsp); //添加文本框
frame1.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); // 设置模式类型
frame1.setVisible(true);
}
if(e.getActionCommand()=="背景颜色")
{
JDialog frame2 = new JDialog();//新建对话框
frame2.setSize(150,200);
int height = frame2.getHeight();
int width = frame2.getWidth();
frame2.setLocation(screenWidth/2-width/2, screenHeight/2-height/2);
frame2.setLayout(new GridLayout(3,2,10,10));
//三个文本框;
JLabel label1 = new JLabel("Red");
JLabel label2 = new JLabel("Green");
JLabel label3 = new JLabel("Blue");
JTextField tf1 = new JTextField("255");
//tf1.setSize(80, 20);
JTextField tf2 = new JTextField("239");
//tf2.setBounds(10, 40, 80, 20);
JTextField tf3 = new JTextField("213");
//tf3.setBounds(10, 70, 80, 20);
frame2.setTitle("设置背景颜色");
frame2.getContentPane().add(label1);
frame2.getContentPane().add(tf1); //
frame2.getContentPane().add(label2);
frame2.getContentPane().add(tf2);
frame2.getContentPane().add(label3);
frame2.getContentPane().add(tf3);
frame2.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); // 设置模式类型
frame2.setVisible(true);
//改变背景颜色
int Red =Integer.parseInt(tf1.getText());
int Green =Integer.parseInt(tf2.getText());
int Blue =Integer.parseInt(tf3.getText());
this.getContentPane().setBackground(new Color(Red,Green,Blue));
this.repaint();
}
if(e.getActionCommand() == "先行方") {
new FirstDialog(IsBlack,jl3);//新建对话框,改变先行方
}
}
public static void main(String[] args) {
new Frame();
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
//改变先行方
class FirstDialog extends JDialog implements ItemListener{
/**
*
*/
private static final long serialVersionUID = 1L;
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenWidth = screenSize.width;
int screenHeight = screenSize.height;
Boolean IsBlack;
JLabel jl = new JLabel();
JRadioButton rbWhite,rbBlack;
FirstDialog(Boolean IsBlack,JLabel jl)
{
this.IsBlack = IsBlack;
this.jl = jl;
this.setSize(150,200);
int height = this.getHeight();
int width = this.getWidth();
this.setLocation(screenWidth/2-width/2, screenHeight/2-height/2);
this.setTitle("先行方");
//一个单选组合;
rbWhite = new JRadioButton("白子");
rbBlack = new JRadioButton("黑子");
this.setLayout(new FlowLayout());
this.getContentPane().add(rbWhite);
this.getContentPane().add(rbBlack); //
ButtonGroup bgroup = new ButtonGroup();
bgroup.add(rbWhite);
bgroup.add(rbBlack);
//本类做监听类
rbWhite.addItemListener(this);
rbBlack.addItemListener(this);
this.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); // 设置模式类型
this.setVisible(true);
}
public void itemStateChanged(ItemEvent e) {
if(rbWhite.isSelected())//选中白子时,将先行方设为白子;
{
IsBlack = false;
jl.setText("白方先行");
}
else if(rbBlack.isSelected())
{
IsBlack = true;
jl.setText("黑方先行");
}
}
}
2.Time.java(实时显示时间)
package Gobang;
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.text.*;
public class Time implements Runnable{
private JLabel lab = new JLabel();
public Time(JLabel lab) {
this.lab = lab;
}
public void run() {
while(true) {
SimpleDateFormat simpleFormat = new SimpleDateFormat("HH:mm:ss");
Calendar c = Calendar.getInstance();
lab.setText(simpleFormat.format(c.getTime()));
lab.setForeground(Color.RED);
try {
Thread.sleep(1000);
}catch(Exception e)
{
e.printStackTrace();
}
}
}
}
本文地址:https://blog.csdn.net/qq_43533435/article/details/109764861