记录java围棋小游戏心得

257 阅读9分钟

为了深入学习Java中GUI与事件处理机制,利用java中的GUI与事件处理机制等功能实现围棋小游戏。

效果图

image.png

一、概述

1、GUI是指图形用户界面也称图形用户接口,在Java中是进行人机交互的窗口,在这个窗口中用户可以实现应用程序提供的所有功能。事件处理机制在上一篇文章中有详细介绍,这里不多说明。

二、设计

(本人的设计思想是:先设计一个整体的框架,再往设计好的框架中加入组件,并一步步的进行调试,争取每步都在正确的路线上,各代码之间相互融合。)

1、逻辑设计

1)、首先创建一个顶级窗口容器类myframe,作为整体的框架。

2)、然后创建规则类Rule,加入到框架中

3)、然后创建棋盘类ChessPad,加入到框架中,再在棋盘类中添加具体的组件,比如说一个重新开始按钮和两个用于提示作用的文本框,如上效果图。

4)、再创建黑棋子类Chess_black和白棋子类Chess_white,加入到棋盘类中

5)、最后创建实现鼠标监听事件类Listen,用于实现各组件的产生的事件。

6)、最后创建一个主类mains,用于启动程序。

注意:这里其实是有三个容器,一个顶级窗口容器属于最顶级的,一个规则类容器(因为这里我是用继承JPanel面板容器实现的)和一个棋盘类容器(还是用继承JPanel面板容器实现的)。我把各种组件都是添加到棋盘类容器中的,所以当实现组件产生的事件时,其实是在棋盘类容器中进行各种操作的,而不是在顶级窗口容器中。

image.png

2、代码实现

(1)、这里通过创建一个窗口类myfame继承JFrame类来创建顶级窗口容器。注意:这里的窗口类布局管理器为空布局。

package 单机围棋;
 
import javax.swing.JFrame;
 
class myframe extends JFrame//窗口类
{
	private static final long serialVersionUID=2l;
	ChessPad chessPad=new ChessPad();
	//方法定义
	public void display()//窗口设置
	{
		setTitle("围棋");
		setLayout(null);//设置容器布局为空布局
		setSize(570,560);//窗口大小
		/***********************************************/
		Rule rule=new Rule();//规则面板类对象
		add(rule);
		rule.setBounds(60, 20, 440, 30);//设置规则面板类在窗口中的位置和大小
		/***********************************************/
		ChessPad chessPad=new ChessPad();//棋盘面板类对象
		add(chessPad);
		chessPad.setBounds(60, 60, 440, 440);//设置棋盘面板类在窗口中的位置和大小
		/***********************************************/
		setVisible(true);//窗口为可见
		setResizable(false);//不可改变窗口大小
		setLocationRelativeTo(null);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}
}

(2)、通过创建一个Rule类继承JPanel面板容器实现规则面板,再加入到顶级窗口容器中,并设置在窗口中的位置。

package 单机围棋;
 
import java.awt.Color;
 
import javax.swing.JLabel;
import javax.swing.JPanel;
 
public class Rule extends JPanel//规则面板类
{
	private static final long serialVersionUID=2l;
	
	//属性定义 
	JLabel label;//标签
	//方法定义
	public Rule() 
	{
		setBackground(Color.orange);//面板颜色
		setSize(440, 30);//面板大小
		label=new JLabel("单击左键下棋子,双击左键吃棋子,落子无悔!请慎重!");
		add(label);
	}
}

(3)、通过创建棋盘类ChessPad继承JPanel面板容器实现棋盘,并在棋盘容器中加入重新开始组件,一个标签组件,和两个文本框组件。

package 单机围棋;
 
import java.awt.Color;
import java.awt.Graphics;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
public class ChessPad extends JPanel//棋盘面板类
{
	private static final long serialVersionUID=3l;
	//属性定义
	JButton button;//按钮
	JTextField text1,text2;//文本框
	JLabel label;//标签
	Listen listen=new Listen();//创建监听器对象
	//方法定义
	ChessPad()//构造方法
	{
		setSize(440,440);//棋盘面板大小
		setLayout(null);//棋盘布局为空
		setBackground(Color.orange);//面板颜色
		button=new JButton("重新开始");
		add(button);
		button.addMouseListener(listen);//在按钮中添加监听器
		button.setBounds(3, 10, 85, 20);
		text1=new JTextField("请黑棋下子");
		add(text1);
		text1.addMouseListener(listen);//在文本框1中添加监听器
		text1.setBounds(92, 10, 100, 20);
		label=new JLabel("提示框:"); 
		add(label);
		label.setBounds(214, 10, 60, 20);
		text2=new JTextField("游戏开始,请黑棋先下子");
		add(text2);
		text2.setBounds(257, 10, 180, 20);//在文本框2中添加监听器
		listen.set1(button, this);//把按钮实例对象和棋盘实例对象传入实现监听事件类的中
		listen.set2(text1, text2,label);//把文本框实例对象和标签实例对象传入实现监听事件类的中
		addMouseListener(listen);//在棋盘类中添加监听器,注意这里是吧整个棋盘面板作为事件源
	}
	@Override
	public void paintComponent(Graphics g)//画线,棋盘行列间距为40像素,行列为19
	{
		super.paintComponent(g);
		for(int i=40;i<=400;i=i+20)
			g.drawLine(40, i, 400, i);
		for(int j=40;j<=400;j=j+20)
			g.drawLine(j, 40, j, 400);
		//在棋盘的指定位置绘制实心圆,注意左上角坐标不是圆心坐标
		g.fillOval(97, 97, 6, 6);
		g.fillOval(337, 97, 6, 6);
		g.fillOval(97, 337, 6, 6);
		g.fillOval(337, 337, 6, 6);
		g.fillOval(217, 217, 6, 6);
	}
	public void paintchess()//在棋盘上画棋子的方法
	{
		Graphics p=getGraphics();
		p.fillOval(96, 96, 10, 10);
	}
}

(4)、创建黑棋子类,并实现MouseListener接口用来在自身类中实现”双击黑棋子进行吃黑棋子“的功能。这里的黑棋是通过继承JPanel容器实现的,也就是说黑棋子其实也是个面板容器(同样白棋子也是)。

package 单机围棋;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
 
import javax.swing.JPanel;
 
public class Chess_black extends JPanel implements MouseListener//黑棋子类继承面板容器,自身实现鼠标点击事件
{
	public static final long serialVersionUID=03l;//序列号
	ChessPad chessPad;
	
	public void get(ChessPad chessPad)//传入棋盘实例对象
	{
		this.chessPad=chessPad;
	}
	
	public Chess_black()//定义黑棋子面板容器大小,并添加鼠标事件监听器 
	{
		setSize(20,20);
		addMouseListener(this);
	}
	
	@Override
	public void paint(Graphics p)//定义黑棋子颜色宽高
	{
		p.setColor(Color.black);
		p.fillOval(0, 0, 20, 20);
	}
	
	@Override
	public void mouseClicked(MouseEvent e)//实现鼠标监听事件
	{
		if (e.getClickCount()>=2)//如果鼠标连续点击了两下或以上
		{
			if(e.getSource()==this)//如果鼠标点击的是黑棋子组件
			{
				chessPad.remove(this);//在棋盘面板容器中移除被点击的黑棋子组件
				chessPad.repaint();//刷新棋盘,如果不刷新,则会显示异常
			}	
		}
	}
	public void mousePressed(MouseEvent e) {}
	public void mouseReleased(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
}

(5)、使用与创建黑棋子类相同的方法创建白棋子Chess_white。

package 单机围棋;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
 
import javax.swing.JPanel;
 
public class Chess_white extends JPanel implements MouseListener
{
	public static final long serialVersionUID=02l;//序列号
	ChessPad chessPad;
	
	public void get(ChessPad chessPad)
	{
		this.chessPad=chessPad;
	}
	
	public Chess_white()
	{
		setSize(20,20);
		addMouseListener(this);
	}
	
	@Override
	public void paint(Graphics p)//重写paint方法画好白棋子对象颜色和大小。该方法为在面板容器中使用的用来设计面板样式的方法,
								 //所以只要调用该方法所在类的容器对象,就可以显示该方法所设计的容器的样子
	{
		p.setColor(Color.white);
		p.fillOval(0, 0, 20, 20);
		
	}
	
	@Override
	public void mouseClicked(MouseEvent e)
	{
		if (e.getClickCount()>=2)
		{
			if(e.getSource()==this)
			{
				chessPad.remove(this);
				chessPad.repaint();
			}	
		}
	}
	public void mousePressed(MouseEvent e) {}
	public void mouseReleased(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
}

(6)、鼠标监听事件类Listen,用于实现各组件相应的功能。

package 单机围棋;
 
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
 
public class Listen extends MouseAdapter//实现鼠标点击事件
{
	JButton button;
	ChessPad chessPad;
	JTextField text1,text2;
	JLabel label;
	
	int x,y;
	int color=0;//让黑棋先落子
	Chess_black chessblack;
	Chess_white chesswhite;
	
	public void set1(JButton button,ChessPad chessPad)//传入组件实例对象,并初始化
	{
		this.button=button;      
		this.chessPad=chessPad;
	}
 
	public void set2(JTextField text1,JTextField text2,JLabel label)//传入组件实例对象,并初始化
	{
		this.text1=text1;
		this.text2=text2;
		this.label=label;
	}
	
	@Override
	public void mouseClicked(MouseEvent e)//鼠标在组件上单击(按下并释放)时调用该方法。
	{
		if(e.getSource()==button)//重新开始事件的实现
		{
			chessPad.removeAll();//删除容器中所有组件
			chessPad.repaint();//刷新容器显示界面
			//重新往容器中添加组件
			chessPad.add(button);
			chessPad.add(text1);
			chessPad.text1.setText("请黑棋下子");
			chessPad.add(label);
			chessPad.add(text2);
			chessPad.text2.setText("重新开始了,请黑棋先下子");
 
			color=0;//颜色重新设置为0,重新从黑棋开始下		
		}	
			//得到鼠标在容器中的坐标
			x=e.getX();
			y=e.getY();
			//得到坐标在棋盘上的行列位置
			int a=(x+9-20)/20;//行位置
			int b=(y+9-20)/20;//列位置
		if(e.getSource()==chessPad)//在棋盘上下棋事件的实现
		{
			if(x<35||y<35||x>405||y>405)//判断鼠标下棋位置,若超出棋盘位置则不落子
			{
				chessPad.text2.setText("别乱点!棋只能下在棋盘上面!");//鼠标超出棋盘位置,不落子
			}
			else//鼠标在棋盘中,开始落子
			{
				if(color==1)//若棋子颜色为1,则落白子
				{
					chesswhite=new Chess_white();//定义白棋子组件实例对象
					chesswhite.get(chessPad);
					chessPad.add(chesswhite);//往棋盘容器中添加白子
					chesswhite.setBounds(a*20+10, b*20+10, 20, 20);//白子落子位置
					chessPad.text1.setText("请黑棋下子");
					chessPad.text2.setText(null);
					color--;//棋子颜色设置0,控制下一步落子颜色为黑子
				}
				else if(color==0)//若棋子颜色为0,则落黑子
				{
					chessblack=new Chess_black();//定义黑棋子组件的实例对象
					chessblack.get(chessPad);
					chessPad.add(chessblack);//往棋盘容器中添加黑子
					chessblack.setBounds(a*20+10, b*20+10, 20, 20);//黑子落子位置
					chessPad.text1.setText("请白棋下子");	
					chessPad.text2.setText(null);
					color++;//棋子颜色设置为1,控制下一步落子为白子
				}
			}
		}
	}
}

(7)、鼠标监听事件类Listen创建

package 单机围棋;
 
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
 
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
 
public class Listen extends MouseAdapter//实现鼠标点击事件
{
	JButton button;
	ChessPad chessPad;
	JTextField text1,text2;
	JLabel label;
	
	int x,y;
	int color=0;//让黑棋先落子
	Chess_black chessblack;
	Chess_white chesswhite;
	
	public void set1(JButton button,ChessPad chessPad)//传入组件实例对象,并初始化
	{
		this.button=button;      
		this.chessPad=chessPad;
	}
 
	public void set2(JTextField text1,JTextField text2,JLabel label)//传入组件实例对象,并初始化
	{
		this.text1=text1;
		this.text2=text2;
		this.label=label;
	}
	
	@Override
	public void mouseClicked(MouseEvent e)//鼠标在组件上单击(按下并释放)时调用该方法。
	{
		if(e.getSource()==button)//重新开始事件的实现
		{
			chessPad.removeAll();//删除容器中所有组件
			chessPad.repaint();//刷新容器显示界面
			//重新往容器中添加组件
			chessPad.add(button);
			chessPad.add(text1);
			chessPad.text1.setText("请黑棋下子");
			chessPad.add(label);
			chessPad.add(text2);
			chessPad.text2.setText("重新开始了,请黑棋先下子");
 
			color=0;//颜色重新设置为0,重新从黑棋开始下		
		}	
			//得到鼠标在容器中的坐标
			x=e.getX();
			y=e.getY();
			//得到坐标在棋盘上的行列位置
			int a=(x+9-20)/20;//行位置
			int b=(y+9-20)/20;//列位置
		if(e.getSource()==chessPad)//在棋盘上下棋事件的实现
		{
			if(x<35||y<35||x>405||y>405)//判断鼠标下棋位置,若超出棋盘位置则不落子
			{
				chessPad.text2.setText("别乱点!棋只能下在棋盘上面!");//鼠标超出棋盘位置,不落子
			}
			else//鼠标在棋盘中,开始落子
			{
				if(color==1)//若棋子颜色为1,则落白子
				{
					chesswhite=new Chess_white();//定义白棋子组件实例对象
					chesswhite.get(chessPad);
					chessPad.add(chesswhite);//往棋盘容器中添加白子
					chesswhite.setBounds(a*20+10, b*20+10, 20, 20);//白子落子位置
					chessPad.text1.setText("请黑棋下子");
					chessPad.text2.setText(null);
					color--;//棋子颜色设置0,控制下一步落子颜色为黑子
				}
				else if(color==0)//若棋子颜色为0,则落黑子
				{
					chessblack=new Chess_black();//定义黑棋子组件的实例对象
					chessblack.get(chessPad);
					chessPad.add(chessblack);//往棋盘容器中添加黑子
					chessblack.setBounds(a*20+10, b*20+10, 20, 20);//黑子落子位置
					chessPad.text1.setText("请白棋下子");	
					chessPad.text2.setText(null);
					color++;//棋子颜色设置为1,控制下一步落子为白子
				}
			}
		}
	}
}

(8)、主类mains创建,最后启动主类既可启动程序,进行围棋网络游戏啦!!

package 单机围棋;
 
public class mains
{
	public static void main (String []args)
	{
		new myframe().display();
	}
}

三、总结

  通过这次小游戏的实现,了解掌握GUI图形界面的设计,并学习界面中各组件与事件处理机制的功能交互实现。这里主要是运用到了JPanel容器(JPanel又称面板,是Java中最常用的轻量级容器之一,其默认布局管理器是FlowLayout(流式布局管理器)。JPanel可以容纳其他组件,但其本身不可见,需要加入到顶级容器中才能存在,因此也称为中间容器,JPanel之间可以嵌套,对组件进行组合。)来实现界面的设计。当然也可以使用其他的组件或者容器来进行界面的设计,并且也可以添加其他组件来实现相应更复杂的功能,但由于图形界面的设计并不是Java的强项,也由于GUI发展的停滞,这里不对GUI作深入的了解。本文旨在学习Java事件处理机制以及事件处理机制实现功能的过程,并对设计模式有一定的学习和了解,并规范代码的实现,给本人自己找准一种学习的思路,也希望能给读者带来帮助。

Java路漫漫,唯有君作伴~