Java实训项目中国象棋设计报告.docx
《Java实训项目中国象棋设计报告.docx》由会员分享,可在线阅读,更多相关《Java实训项目中国象棋设计报告.docx(53页珍藏版)》请在冰点文库上搜索。
![Java实训项目中国象棋设计报告.docx](https://file1.bingdoc.com/fileroot1/2023-5/6/5e5145e4-da89-45df-9d55-e6a471bd0243/5e5145e4-da89-45df-9d55-e6a471bd02431.gif)
Java实训项目中国象棋设计报告
广西科技大学鹿山学院
面向对象程序设计实训报告
题目:
网络中国象棋
系别:
电气与计算机工程系
专业班级:
计软141班
姓名:
邓康言
学号:
20141409
成绩评定:
指导教师签字:
2016年1月10日
1、需求分析
1.1开发的背景
·中国象棋有着悠久的历史,象棋爱好者更是不计其数,但是由于人们的工作地点从、时间的限制,原始的那种面对面的下棋方式已经不再适应人们的生活,人们已经开始走向网络象棋博弈
·网络象棋有着很多的优点,通过网络象棋,对弈的双方是网络上任意的两个象棋爱好者,甚至是不认识。
网络让对弈的范围更加的广泛,让象棋爱好者可以与更多的象棋爱好者切磋棋艺。
1.2算法
·指定服务器端口号
·支持多人同时在线·
·显示在线用户信息
·显示当前在线所有用户
·从在线用户列表中选择玩家进行挑战
·接受或拒绝挑战
1.3要求
·用Java语言实现系统,源程序要有适当的注释,使程序容易阅读
·函数功能要划分好(结构化程序设计)
·可以增加新功能模块
2、总体分析与设计
2.1总体设计方案
·系统功能模块图:
2.2功能描述
2.2.1服务器端
·可以指定服务器端口号。
·可以支持多人同时在线。
·可以显示在线用户信息。
·不允许玩家同名
2.2.2客户端
·能够通过主机IP号及端口号登陆到服务器。
·可以显示当前在线所有用户。
·可以从在线用户列表中选择玩家进行挑战。
·可以接受或拒绝挑战。
·如果对方在和其他玩家对弈中,则应该给与相应的提示信息。
·象棋规则一定要严密。
·棋子样式采用最普通的橡胶式象棋。
棋子为黑色,字为红色和白色
2.3算法设计----
本程序功能模块根据程序设计的需要。
综合程序的实用性、智能化的考虑。
将程序划分为8个模块来写。
(1)服务器端的框架设计类
(2)服务器线程类
(3)服务器代理线程类
(4)棋子类的开发类
(5)客户端的框架设计类
(6)客户端线程类
(7)棋子的规则类
(8)棋盘的设计类
2.5系统流程图----
3、数据结构设计
3.1功能模块的设计
3.1.1服务器端框架类设计
importjava.util.*;
importjava.awt.*;//界面包
importjava.awt.event.*;//事件处理包
importjavax.swing.*;//图形化界面包
importjavax.swing.event.*;//图形化界面包事件进行处理
import.*;//网络包
importjava.io.*;//IO流
publicclassServerextendsJFrameimplementsActionListener
{
JLabeljlPort=newJLabel("端口号");//创建提示输入端口号标签
JTextFieldjtfPort=newJTextField("9457");//用于输入端口号的文本框
JButtonjbStart=newJButton("启动");//创建"启动"按钮
JButtonjbStop=newJButton("关闭");//创建"关闭"按钮
JPaneljps=newJPanel();//创建一个JPanel对象
JListjlUserOnline=newJList();//创建用于显示当前用户的JList
JScrollPanejspx=newJScrollPane(jlUserOnline);//将显示当前用户的JList放在JScrollPane中
JSplitPanejspz=newJSplitPane(JSplitPane.HORIZONTAL_SPLIT,jspx,jps);//创建JSplitPane对象
ServerSocketss;//声明ServerSocket引用
ServerThreadst;//声明ServerThread引用
VectoronlineList=newVector();//创建存放当前在线用户的Vector对象
publicServer()
{
this.initialComponent();//初始化控件
this.addListener();//为相应的控件注册事件监听器
this.initialFrame();//初始化窗体
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
publicvoidinitialComponent()
{
jps.setLayout(null);//设为空布局
jlPort.setBounds(20,20,50,20);
jps.add(jlPort);//添加用于提示输入端口号的标签
this.jtfPort.setBounds(85,20,60,20);
jps.add(this.jtfPort);//添加用于输入端口号的文本框
this.jbStart.setBounds(18,50,60,20);
jps.add(this.jbStart);//添加"开始"按钮
this.jbStop.setBounds(85,50,60,20);
jps.add(this.jbStop);//添加"关闭"按钮
this.jbStop.setEnabled(false);//将"关闭"按钮设为不可用
}
publicvoidaddListener()
{
this.jbStart.addActionListener(this);//为"开始"按钮注册事件监听器
this.jbStop.addActionListener(this);//为"关闭"按钮注册事件监听器
}
publicvoidinitialFrame()
{
this.setTitle("象棋--服务器端");//设置窗体标题
Imageimage=newImageIcon("ico.gif").getImage();
this.setIconImage(image);
this.add(jspz);//将JSplitPane添加到窗体中
jspz.setDividerLocation(250);
jspz.setDividerSize(4);//设置分割线的位置和宽度
this.setBounds(20,20,420,320);
this.setVisible(true);//设置可见性
this.addWindowListener(//为窗体关闭事件注册监听器
newWindowAdapter()
{
publicvoidwindowClosing(WindowEvente)
{
if(st==null)//当服务器线程为空时直接退出
{
System.exit(0);//退出
return;
}
try
{
Vectorv=onlineList;
intsize=v.size();
for(inti=0;i{
//当不为空时,向在线用户发送离线信息
ServerAgentThreadtempSat=(ServerAgentThread)v.get(i);
tempSat.dout.writeUTF("<#SERVER_DOWN#>");
tempSat.flag=false;//终止服务器代理线程
}
st.flag=false;//终止服务器线程
st=null;
ss.close();//关闭ServerSocket
v.clear();//将在线用户列表清空
refreshList();//刷新列表
}
catch(Exceptionee)
{
ee.printStackTrace();
}
System.exit(0);//退出
}
}
);
}
publicvoidactionPerformed(ActionEvente)
{
if(e.getSource()==this.jbStart)
{//当单击"启动"按钮时
this.jbStart_event();
}
elseif(e.getSource()==this.jbStop)
{//单击"关闭"按钮后
this.jbStop_event();
}
}
publicvoidjbStart_event()
{
//单击"启动"按钮的业务处理代码
intport=0;
try
{
//获得用户输入的端口号,并转化为整型
port=Integer.parseInt(this.jtfPort.getText().trim());
}
catch(Exceptionee)
{//端口号不是整数,给出提示信息
JOptionPane.showMessageDialog(this,"端口号只能是整数","错误",
JOptionPane.ERROR_MESSAGE);
return;
}
if(port>65535||port<0)
{//断口号不合法,给出提示信息
JOptionPane.showMessageDialog(this,"端口号只能是0-65535的整数","错误",
JOptionPane.ERROR_MESSAGE);
return;
}
try
{
this.jbStart.setEnabled(false);//将开始按钮设为不可用
this.jtfPort.setEnabled(false);//将用于输入端口号的文本框设为不可用
this.jbStop.setEnabled(true);//将停止按钮设为可用
ss=newServerSocket(port);//创建ServerSocket对象
st=newServerThread(this);//创建服务器线程
st.start();//启动服务器线程
//给出服务器启动成功的提示信息
JOptionPane.showMessageDialog(this,"服务器启动成功","提示",
JOptionPane.INFORMATION_MESSAGE);
}
catch(Exceptionee)
{
//给出服务器启动失败的提示信息
JOptionPane.showMessageDialog(this,"服务器启动失败","错误",
JOptionPane.ERROR_MESSAGE);
this.jbStart.setEnabled(true);//将开始按钮设为可用
this.jtfPort.setEnabled(true);//将用于输入端口号的文本框设为可用
this.jbStop.setEnabled(false);//将停止按钮设为不可用
}
}
publicvoidjbStop_event()
{
//单击"关闭"按钮的业务处理代码
try
{
Vectorv=onlineList;
intsize=v.size();
for(inti=0;i{//向在线用户发送离线信息
ServerAgentThreadtempSat=(ServerAgentThread)v.get(i);
tempSat.dout.writeUTF("<#SERVER_DOWN#>");
tempSat.flag=false;//关闭服务器代理线程
}
st.flag=false;//关闭服务器线程
st=null;
ss.close();//关闭ServerSocket
v.clear();//将在线用户列表清空
refreshList();//刷新列表
this.jbStart.setEnabled(true);//将开始按钮设为可用
this.jtfPort.setEnabled(true);//将用于输入端口号的文本框设为可用
this.jbStop.setEnabled(false);//将停止按钮设为不可用
}
catch(Exceptionee)
{
ee.printStackTrace();
}
}
publicvoidrefreshList()
{
//更新在线用户列表的业务处理代码
Vectorv=newVector();
intsize=this.onlineList.size();
for(inti=0;i{//遍历在线列表
ServerAgentThreadtempSat=(ServerAgentThread)this.onlineList.get(i);
Stringtemps=tempSat.sc.getInetAddress().toString();
temps=temps+"|"+tempSat.getName();//获得所需信息
v.add(temps);//添加到Vector中
}
this.jlUserOnline.setListData(v);//更新列表数据
}
publicstaticvoidmain(Stringargs[])
{
newServer();
}
}
说明:
此服务器端类既为服务器的运行类,用户通过该类进入服务器的主界面。
进行相应的操作。
3.1.2服务器线程设计
/*服务器线程*/
importjava.util.*;
importjava.awt.*;
importjava.awt.event.*;
importjavax.swing.*;
importjavax.swing.event.*;
import.*;
importjava.io.*;
publicclassServerThreadextendsThread
{
Serverfather;//声明Server的引用
ServerSocketss;//声明ServerSocket的引用
booleanflag=true;//线程存在为true
publicServerThread(Serverfather)
{//构造器
this.father=father;
ss=father.ss;//和服务器端关联
}
publicvoidrun()
{
while(flag)//定义一个死循环。
为false时跳出
{
try
{
Socketsc=ss.accept();//等待客户端连接
ServerAgentThreadsat=newServerAgentThread(father,sc);
sat.start();//创建并启动服务器代理线程
}
catch(Exceptione)//trycatch捕获异常
{
e.printStackTrace();//打印异常,可有可无
}
}
}
}
类功能说明:
服务器线程类在服务器启动后创建并启动的第一个线程,该线程主要用于接收客户端的连接,并为每一个连接分配一个服务器代理线程。
3.1.3服务器代理线程设计
【部分代码(过长不适复制完)】:
/*服务器代理线程*/
//先想到需要用什么函数
importjava.util.*;
importjava.awt.*;//界面包
importjava.awt.event.*;//事件处理包
importjavax.swing.*;//图形化界面包
importjavax.swing.event.*;//图形化界面包事件进行处理
import.*;//网络包
importjava.io.*;//IO流
publicclassServerAgentThreadextendsThread//同服务器类一样
{
Serverfather;//声明Server的引用
Socketsc;//声明Socket的引用。
用他来与客户端一一对应。
分配给它资源
DataInputStreamdin;//声明数据输入流与输出流的引用
DataOutputStreamdout;
booleanflag=true;//控制线程的标志位
publicServerAgentThread(Serverfather,Socketsc)
{
this.father=father;
this.sc=sc;
try
{
din=newDataInputStream(sc.getInputStream());//创建数据输入流
dout=newDataOutputStream(sc.getOutputStream());//创建数据输出流
}
catch(Exceptione)
{
e.printStackTrace();
}
}
publicvoidrun()
{
while(flag)//线程在存活期。
就是死循环。
{
try
{
Stringmsg=din.readUTF().trim();//接收客户端传来的信息
if(msg.startsWith("<#NICK_NAME#>"))//收到新用户的信息
{
this.nick_name(msg);
}
elseif(msg.startsWith("<#CLIENT_LEAVE#>")){//收到用户离开的信息
this.client_leave(msg);
}
elseif(msg.startsWith("<#TIAO_ZHAN#>")){//收到用户发出的挑战信息
this.tiao_zhan(msg);
}
elseif(msg.startsWith("<#TONG_YI#>")){//收到接受挑战的信息
this.tong_yi(msg);
}
elseif(msg.startsWith("<#BUTONG_YI#>")){//收到拒绝挑战的信息
this.butong_yi(msg);
}
elseif(msg.startsWith("<#BUSY#>")){//收到被挑战者忙的信息
this.busy(msg);
}
elseif(msg.startsWith("<#MOVE#>")){//收到走棋的信息
this.move(msg);
}
elseif(msg.startsWith("<#RENSHU#>")){//收到某用户认输的信息
this.renshu(msg);
}
}
catch(Exceptione)
{
e.printStackTrace();
}
}
}
publicvoidnick_name(Stringmsg)
{
try
{
Stringname=msg.substring(13);//获得用户的昵称
this.setName(name);//用该昵称给该线程取名
Vectorv=father.onlineList;//获得在线用户列表
booleanisChongMing=false;
intsize=v.size();//获得用户列表的大小
for(inti=0;i{//遍历列表,查看是否已经有该用户名
ServerAgentThreadtempSat=(ServerAgentThread)v.get(i);
if(tempSat.getName().equals(name))
{
isChongMing=true;//有重名,将标志位设为true
break;
}
}
if(isChongMing==true)//如果重名
{
dout.writeUTF("<#NAME_CHONGMING#>");//将重名信息发送给客户端
din.close();//关闭数据输入流
dout.close();//关闭数据输出流
sc.close();//关闭Socket
flag=false;//终止该服务器代理线程
}
else//如果不重名
{
v.add(this);//将该线程添加到在线列表
father.refreshList();//刷新服务器在线信息列表
StringnickListMsg="";
size=v.size();//获得在线列表大小
for(inti=0;i{
ServerAgentThreadtempSat=(ServerAgentThread)v.get(i);
nickListMsg=nickListMsg+"|"+tempSat.getName();
}//将在线列表内容住组织成字符串
nickListMsg="<#NICK_LIST#>"+nickListMsg;
Vectortempv=father.onlineList;
size=tempv.size();
for(inti=0;i{//遍历在线列表
ServerAgentThread