欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

五子棋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.可以更改先行方(默认黑子)。

结果

五子棋2.0(Java)
五子棋2.0(Java)

五子棋2.0(Java)

完整代码

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