五子棋设计文档.docx
《五子棋设计文档.docx》由会员分享,可在线阅读,更多相关《五子棋设计文档.docx(22页珍藏版)》请在冰点文库上搜索。
五子棋设计文档
1:
序言
程序简介:
随着计算机网络的迅猛发展,异地计算机之间的通信变得十分便捷。
这也为异地间的用户通过网络来进行下棋提供了可能。
网络五子棋软件利用TCP/IP协议,在异地的玩家之间建立起TCP连接,并用它来交换棋局的各种数据信息。
所以,网络五子棋软件在下棋以前必须要对相关的网络参数进行设置,才能实现玩家双方的成功连接。
连接成功后,玩家双方轮流下棋,并将每一步下棋的信息通过网络传送给对方,使得双方棋盘上的棋子保持一致。
与单机版五子棋软件相同,网络版五子棋软件也提供了倒计时器、“认输”、“和棋”和“悔棋”等功能。
但这些功能的都是通过网络来实现的,所以,实现过程较单机版要复杂。
在胜负判别方面,单机版五子棋软件与网络版五子棋软件并没有什么不同,只是网络版的玩家双方各自有一套胜负判别的程序。
当一方玩家下一步棋后,他的胜负判别程序就执行一次,然后再将落子的信息传送给对方,对方的胜负判别程序也将执行一次。
这样就完成一次胜负的判别过程。
另外,网络版五子棋的双方可能相距邀远,双方的语言交流没有单机版方便。
所以,网络版五子棋还必须提供聊天功能。
2:
需求分析
⑴功能需求
①能通过网络进行下棋
②符合五子棋的基本规则
③提供水平坐标和垂直坐标功能
④提供双方的倒计时功能
⑤能在棋子上显示的落子的顺序数
⑥提供玩家之间的聊天功能
⑵环境需求
①10/10Mbps共享式HUB一台
②装有Windows95/98/NT/XP操作系统的计算机两台
③计算机的CPU不低于PII450,存不小于64M
④10/10Mbps自适应网卡每台计算机各一块,SB兼容声卡各一块,5类双绞线若干米
⑤每台计算机都应配置有TCP/IP协议
⑶用户界面需求
①界面友好、亲切
②界面简洁、不花哨
③操作界面直观、不繁琐
3:
程序运行
4:
UML
5:
应用设计模式
轻量级模式(享元模式)
Flyweight在拳击比赛中指最轻量级,即"蝇量级",有些作者翻译为"羽量级"。
这里使用"享元模式"更能反映模式的用意。
享元模式以共享的方式高效地支持大量的细粒度对象。
享元对象能做到共享的关键是区分蕴状态(InternalState)和外蕴状态(ExternalState)。
蕴状态是存储在享元对象部并且不会随环境改变而改变。
因此蕴状态并可以共享。
外蕴状态是随环境改变而改变的、不可以共享的状态。
享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象部。
外蕴状态与蕴状态是相互独立的。
享元模式的应用
享元模式在编辑器系统量使用。
一个文本编辑器往往会提供很多种字体,而通常的做法就是将每一个字母做成一个享元对象。
享元对象的蕴状态就是这个字母,而字母在文本中的位置和字模风格等其他信息则是外蕴状态。
比如,字母a可能出现在文本的很多地方,虽然这些字母a的位置和字模风格不同,但是所有这些地方使用的都是同一个字母对象。
这样一来,字母对象就可以在整个系统中共享。
6:
经验总结和体会
网络五子棋的开发让我感受到软件的开发是十分辛苦的工作,尤其是一个人独立开发更是困难,因为一个人的知识和能力是有限的,一个好的软件需要一个好的团队,集合大家的知识和力量来共同完成。
现在把一些开发的经验总结如下:
①在工程开发中,系统的分析是整个开发的核心,只有前期进行很好的分析、规划,才能做出好的软件产品,这个阶段要进行很好的策划,精密的分析。
尤其是流程的设计,直接关系到系统功能和编码的成败。
②良好的程序设计风格很重要。
这在一个比较大的工程中,程序设计的风格非常重要,这影响到软件的测试以及后期功能扩展,在增量型的开发模型中,混乱的代码会使维护变的十分困难。
在多人合作团队开发的时候,你的代码要影响到全局,必须了解到:
你的代码是写给别人看。
③运用高效的测试手段。
测试要占开发很大的时间,软件编码以后,并非总能百分百的成功,那就要进行测试。
在大程序中,多写异常处理的代码,以及变量合法的检验等,DEBUG中混合使用断点测试以及报告函数,以提高DEBUG效率。
④善于捕捉最新的技术资料。
在每个软件开发过程中,资料是必不可少的,虽然书本上有比较系统的资料,但是真正能运用的还是不多。
在开发时,不要急于设计编码,应该学会先查找软件开发中涉及到的各种最新资料,学习他们关于本系统的一些开发经验。
学会在编码前,吸取别人的代码的一些优点,然后改进设计,使之更加的完善。
网络五子棋的开发让我体会到,要做好软件必须要学会抽象思维,要练好抽象思维,还要学会使用UML软件之类的工具,用UML建模工具建设的时候要一个一个模块设计好,搞清楚,尽可能的把所有的功能分开,如果有相似性那么就需要抽象然后继承重写来实现自己的功能。
7:
代码
Client.java
importjava.awt.BorderLayout;
importjava.awt.Color;
importjava.awt.Frame;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
publicclassClientextendsFrame{
JavaChessFivep;
Client(Strings)
{
super(s);
p=newJavaChessFive();
setLayout(newBorderLayout());
setBounds(100,100,620,418);
add(p);
setBackground(Color.WHITE);
validate();
setVisible(true);
addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
dispose();
System.exit(0);
}
});
}
publicstaticvoidmain(String[]a)
{
newClient("五子棋");
}
}
Concretenut.java
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Toolkit;
importjava.awt.image.ImageObserver;
publicclassConcreteNutextendsNut{
Toolkitt=getToolkit();
privateStringkey;
Imageimg;
publicConcreteNut(Stringstr){
key=str;
}
voiddraw(Graphicsg,intx,inty,ImageObserverobs){
if(key.equals("black")){
img=t.getImage("images/black.gif");
}else{
img=t.getImage("images/white.gif");
}
g.drawImage(img,x,y,24,24,obs);
}
}
JavaChessFive.java
importjava.awt.BorderLayout;
importjava.awt.Button;
importjava.awt.Color;
importjava.awt.FlowLayout;
importjava.awt.Frame;
importjava.awt.Graphics;
importjava.awt.GridLayout;
importjava.awt.Panel;
importjava.awt.TextArea;
importjava.awt.TextField;
importjava.awt.event.MouseAdapter;
importjava.awt.event.MouseEvent;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
importjava.awt.geom.Ellipse2D;
importjava.rmi.Naming;
importjava.util.ArrayList;
importjava.util.List;
importjavax.swing.JOptionPane;
publicclassJavaChessFiveextendsPanel{
Listpoints=newArrayList();
booleanisMy=false,win=false;
booleanflag=true;//棋子重叠判定
NutFactorynutFactory=newNutFactory();//享元类
MyRemotehello;
//
TextAreat;
TextFieldtt;
Buttonb1,b2;
JavaChessFive(){
//this.frame=frame;
setLayout(newBorderLayout());
setSize(620,450);
setBackground(Color.gray);
t=newTextArea(10,25);
tt=newTextField
(1);
b1=newButton("接收消息");
b2=newButton("发送消息");
Panelp1=newPanel();
p1.setLayout(newGridLayout(2,1));
p1.add(t);
p1.add(tt);
add("East",p1);
Panelp2=newPanel();
p2.add(b1);
p2.add(b2);
add("South",p2);
try{
hello=(MyRemote)Naming.lookup("rmi:
//localhost:
8808/RMI_Hello");
System.out.println(hello.sayHello());
System.out.println(hello.fromstr());
}catch(Exceptione){
e.printStackTrace();
}
b1.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEvente){
try{
t.append(hello.fromstr()+"\r\n");
System.out.println(hello.sayHello());
System.out.println(hello.fromstr());
}catch(Exceptionee){
System.out.println("error");
}
}
});
b2.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEvente){
try{
hello.sendTo(tt.getText());
System.out.println(hello.sayHello());
System.out.println(hello.fromstr());
}catch(Exceptionee){
System.out.println("error");
}
}
});
this.addMouseListener(newMouseAdapter(){
publicvoidmousePressed(MouseEventevent){
intx=event.getX();
inty=event.getY();
paintItem(x,y);
repaint();
}
});
}
voidpaintItem(intx,inty){
if(x>=30&&x<=300&&y>=30&&y<=300){
intX=(x+15)/30;
intY=(y+15)/30;
for(Pointpoint:
points){
if(point.getX()==X&&point.getY()==Y){
flag=false;
break;
}
}
if(flag){
points.add(newPoint(X,Y));
}
flag=true;
}
}
publicvoidpaint(Graphicsg){
for(inti=30;i<=300;i=i+30){
g.drawLine(30,i,300,i);
g.drawLine(i,30,i,300);
}
isMy=false;
for(inti=0;iisMy=!
isMy;
if(isMy){
//享元模式方法
nutFactory.getFlyWeight("black").draw(g,
points.get(i).getX()*30-12,
points.get(i).getY()*30-12,this);
if(points.size()>=9){
if(!
win){
if(win=winJudge(points.get(i))){
System.out.println("blackwin");
}
}
}
}else{
//享元模式方法
nutFactory.getFlyWeight("white").draw(g,
points.get(i).getX()*30-12,
points.get(i).getY()*30-12,this);
if(points.size()>9){
if(!
win){
if(win=winJudge(points.get(i))){
System.out.println("whitewin");
}
}
}
}
}
if(win){
if(isMy){
winDialog("黑棋");
}else{
winDialog("白棋");
}
}
}
publicbooleanwinJudge(Pointpoint){
intcount=1;
intstar=1;//白棋
if(isMy){//黑棋
star=0;
}
for(inti=1;i<5;i++){//纵向往上扫描
for(intj=star;jif(point.getY()+i==points.get(j).getY()
&&point.getX()==points.get(j).getX()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//纵向往下扫描
for(intj=star;jif(point.getY()-i==points.get(j).getY()
&&point.getX()==points.get(j).getX()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//横向往左扫描
for(intj=star;jif(point.getX()-i==points.get(j).getX()
&&point.getY()==points.get(j).getY()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//纵向往右扫描
for(intj=star;jif(point.getX()+i==points.get(j).getX()
&&point.getY()==points.get(j).getY()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//向往左上扫描
for(intj=star;jif(point.getX()-i==points.get(j).getX()
&&point.getY()-i==points.get(j).getY()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//向往右下扫描
for(intj=star;jif(point.getX()+i==points.get(j).getX()
&&point.getY()+i==points.get(j).getY()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//向往左下扫描
for(intj=star;jif(point.getX()+i==points.get(j).getX()
&&point.getY()-i==points.get(j).getY()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
for(inti=1;i<5;i++){//向往右上扫描
for(intj=star;jif(point.getX()-i==points.get(j).getX()
&&point.getY()+i==points.get(j).getY()){
count++;
break;
}
}
if(count!
=i+1){
count=1;
break;
}
}
if(count>=5){
returntrue;
}
returnfalse;
}
publicvoidinit(){
points=newArrayList();
isMy=false;
win=false;
flag=true;
}
publicvoidwinDialog(Stringp){
intconfirm=JOptionPane.showConfirmDialog(null,