JAVA游戏五子棋.docx
《JAVA游戏五子棋.docx》由会员分享,可在线阅读,更多相关《JAVA游戏五子棋.docx(25页珍藏版)》请在冰豆网上搜索。
JAVA游戏五子棋
游戏开发与设计大作业
网络五子棋
学院:
计算机与信息工程学院
专业年级:
2008级软件工程
课题名称:
游戏开发与设计
完成日期:
2011年10月10日
1、引言:
1.1、五子棋介绍
五子棋是起源于中国古代的传统黑白棋种之一。
现代五子棋日文称之为“連珠”,英译为“Renju”,英文称之为“Gobang”或“FIR”(FiveinaRow的缩写),亦有“连五子”、“五子连”、“串珠”、“五目”、“五目碰”、“五格”等多种称谓。
五子棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。
五子棋既有现代休闲的明显特征“短、平、快”,又有古典哲学的高深学问“阴阳易理”;它既有简单易学的特性,为人民群众所喜闻乐见,又有深奥的技巧和高水平的国际性比赛;它的棋文化源渊流长,具有东方的神秘和西方的直观;既有“场”的概念,亦有“点”的连接。
它是中西文化的交流点,是古今哲理的结晶。
1.2、开发环境及运行环境
开发环境:
Intelcore2duo1.8GHz1G内存160硬盘
Microsoft®Windows™XPProfessional
JDK1.50
Eclipse3.3.2
运行环境:
IntelPentium®2及以上处理器,32M以上内存,4G以上硬盘
Microsoft®Windows™9X/NT/XP操作系统
800*600或以上的屏幕分辨率
2、C/S模式下网络五子棋的设计
网络互连实现信息的共享成为以后计算机的发展趋势,现有的网络编程模式主要分成两类:
一种是基于C/S(Client/Server客户机/服务器)模式,另一种是B/S(Browser/Server,浏览器/服务器)模式;C/S程序具有好的交互性,功能强大,但是客户端必须安装客户端软件,限制了其应用;B/S模式下要求客户端具有浏览器,但浏览器在安全方面有一些限制,交互性与功能有一些限制。
网络五子棋系统应用于局域网,对交互性要求较高,本系统选用了C/S模式进行实现,网络内部使用TCP/IP方式利用Socket通过传输层提供的服务,使用Java进行图形用户的搭建,系统分成两个部分,分别为服务端程序以及客户端程序。
本文首先介绍系统设计思想以及相关协议的制定,以及分别阐述了服务端程序以及客户端程序的具体实现。
五子棋网络游戏主要分为两个部分,游戏服务端和游戏客户端。
五子棋游戏规则:
游戏双方各执一种颜色的棋子,轮流在棋盘下棋子,一方的棋子在横、竖、两个对角线上首先到达五子者为胜方;游戏服务端主要存储所有连线客户的相关信息及各种状态,并负责游戏客户之间信息的传递;游戏客户端则用于连接服务器,并能与联网客户进行游戏。
3.1、系统设计思想
本系统的功能能够实现一个在网络上供客户进行对战的五子棋网络游戏,客户只要登陆到服务器上,就能选择任何其它用户已创建好的游戏,进行五子棋对战游戏,是C/S模式的网络游戏。
在C/S模式游戏中,Server一般提供所有用户的全局信息,并能提供客户之间的信息转发,客户之间的通讯必须通过Server进行。
因为在多个客户能够连接到同一台Server上,所以Server必须用Thread负责每个用户的通讯和消息处理。
服务端程序通过一个Thread监听客户端的连接,一旦客户连接,为该客户建立连接并启动一个特定的客户thread,利用该连接不断从客户读取数据,实现客户和服务器或者客户与客户之间的信息的交互。
3.2、系统总体设计
系统使用Socket技术以及java多线程机制结合在进行客户与服务端之间信息的交互,但一个真正实用程序必须针对具体应用定制一套协议用于用户程序之间进行交互,而该协议的定制往往是编写程序的关键也是核心内容,该协议的完善决定程序是否能够正常运行。
所谓协议就是程序之间交互的信息的格式规定,服务端和客户端都遵循该协议才能够进行对话,通俗讲是人类之间的语言。
一、服务端接受的信息:
(1)客户端连接信息,一个客户包含两个Socket连接,一个为chatSocket,另一个为chessSocket;
(2)客户端创建游戏信息;(3)客户端加入游戏信息;(4)下棋信息;(5)用户列表信息。
二、服务端发送的信息:
服务端接受到客户端发送的各种信息,会做出不同响应,并发送相应的信息对客户端进行响应或转发相应的信息给对手,并对服务端上存储的全局信息进行更新,服务端可能发送的信息包括:
(1)所有用户列表;
(2)服务端为该客户生成的客户名;(3)用户游戏创建成功信息;(4)加入游戏成功后,分别向游戏双方发送对手信息;(5)游戏进行信息;(7)游戏胜利信息。
三、客户端接受的信息:
(1)用户列表信息;
(2)对手信息;(4)胜利信息;(5)创建成功信息;(6)错误信息。
四、客户端发送的信息:
(1)连接服务器;
(2)创建游戏信息;(3)加入游戏信息。
4、详细设计过程
4.1、首先建立chessClient端,设计客户端总体窗口,通过Frame类来设计。
定义三个类,分别为usePad、chatPad和inputPad,分别为用户信息、信息显示和聊天信息输入钮;位置分别在窗口的左上角、左边和窗口下方。
如图:
1、usePad类中用List类来显示用户,此方法可以提供一个可滚动的文本项列表;
ListuserList=newList(10);//建立一栈显示用户
userPad(){
setLayout(newBorderLayout());
for(inti=0;i<50;i++){
userList.add(i+"."+"没有用户");
}
2、chatPad类使用TextArea类构造一个将空字符串作为文本的新文本区,用来显示聊天信息;
TextAreachatLineArea=newTextArea("",18,30,TextArea.SCROLLBARS_VERTICAL_ONLY);//创建并显示垂直滚动条
chatPad(){
setLayout(newBorderLayout());
add(chatLineArea,BorderLayout.CENTER);
}
3、inputPad类使用TextField类来构造新文本字段,用来定义聊天信息输入框。
TextFieldinputwords=newTextField("",40);//对话窗口最大为40列
ChoiceuserChoice=newChoice();
inputPad(){
setLayout(newFlowLayout(FlowLayout.LEFT));
for(inti=0;i<50;i++){
userChoice.addItem(i+"."+"没有用户");
}
userChoice.setSize(60,24);
4.2、设计服务器chessServer端,并改进chessClient端,使其它能连接到服务器,如果连接上,则在chessServer端打印“aclinetconnected!
”,在chessClient端打印“connected”。
服务器端使用SreverSocket创建绑定到特定端口,端口为4331,并开启线程来运行。
代码如下:
publicvoidmakeMessageServer(){
SocketclientSocket;
try{
serverSocket=newServerSocket(4331);
while(true){
clientSocket=serverSocket.accept();
System.out.print("aclinetconnected!
");
DataInputStreaminData=newDataInputStream(clientSocket.getInputStream());
Stringstr=inData.readUTF();
System.out.print(str);
ServerThreadthread=newServerThread(clientSocket);
thread.start();
}
}catch(IOExceptione){
e.printStackTrace();
}
}
同时在chessClient端改进代码,使其能连接到chessServer端
添加代码如下:
publicbooleanconnectServer(StringserverIP,intserverPort)
throwsException{
try{
chatSocket=newSocket(serverIP,serverPort);
in=newDataInputStream(chatSocket.getInputStream());
out=newDataOutputStream(chatSocket.getOutputStream());
clientThreadclientthread=newclientThread(this);
clientthread.start();
isOnChat=true;
returntrue;
}catch(IOExceptionex){
chatpad.chatLineArea
.setText("chessClient:
connectServer:
无法连接,建议重新启动程序\n");
}
returnfalse;
}
4.3、添加聊天功能,使程序可以完成简单的聊天。
在chessClient端,使用DataOutputStream类来输出inputPad里面的数据,
out=newDataOutputStream(chatSocket.getOutputStream());
通过out.writeUTF(str)传输到chessServer端里的DataInputStream里(这里也通过线程来完成数据的传输,这样可以使并发的进行多个线程,提高系统的运行效率);
在服务器端,使用Stringstr=in.readUTF()来获取客户端传入的数据,然后调用:
DataOutputStreamoutData=(DataOutputStream)enu.nextElement();//公聊信息
outData.writeUTF(publicTalkMessage);
将数据发送到各个客户端,使大家可以看到信息,从而完成聊天!
4.4添加五子棋棋盘,这里采用19*19的围棋棋盘;并能在棋盘上完成下子的功能:
定义一chessPad类,用来完成棋盘的描绘。
这里调用Grpahics类来画线,画棋子。
画在窗口的中心空白处。
棋盘每个格是20*20的正方形。
画棋盘线的方法:
for(inti=40;i<=380;i=i+20){
g.drawLine(40,i,400,i);
}
g.drawLine(40,400,400,400);
for(intj=40;j<=380;j=j+20){
g.drawLine(j,40,j,400);
}
类chessPoint_blac含有黑棋子类的属性和方法,负责黑棋子的绘制。
类chessPoint_white含有白棋子类的属性和方法,负责黑棋子的绘制
棋盘类的实现是正把整个棋盘抽象为一个二维数组,棋子类的实现通过在paint()方法中画圆设置背景色来区别黑白棋子。
黑棋子:
g.setColor(Color.black);
g.fillOval(0,0,14,14);
白棋子:
g.setColor(Color.white);
g.fillOval(0,0,14,14);
4.5、完成棋盘类与服务器的连接,从而实现在网络上的多人游戏功能。
并添加五子棋的胜负判断,添加几个按钮以改进游戏的可玩性:
与服务器建立SOCKET连接
在chessPad类的变量chessSocket,inData,outData
chessSocket=newSocket(ServerIP,ServerPort);
inData=newDataInputStream(chessSocket.getInputStream());
outData=newDataOutputStream(chessSocket.getOutputStream());
初始化于服务器建立连接的变量
此方法publicbooleanconnectServer(StringServerIP,intServerPort)throwsException负责连接服务器。
publicbooleancheckWin(inta,intb,intcheckColor)此方法负责判断输赢结果。
能过判断在同一方向上的棋子颜色是否相同,当相同数目达到5个时则一方获胜。
类chessThread继承Thread类,方法sendMessage(StringsndMessage)主要功能实现客户端与客户端发送信息。
方法acceptMessage(StringrecMessage)主要功能实现客户端与客户端接受信息。
接受到对方的信息后,如果是接受的是棋子位置信息将调用netChessPaint()方法自动显示显示对方棋子位置,来保持与对方棋子信息的一致。
如果接受的信息是聊天信息将利用字符串分析器分析出字符显示聊天信息。
类chessThread的对象在执行线程时负责不断的收发信息,直到关闭流连接。
在此过程中可能会有多种异常导致于服务器断开连接。
类chessClient是整个客户端类的主类,主要变量和方法有:
isOnChat用于判断是聊天
isOnChess是否在下棋
isGameConnected用于判断下棋的客户端连接
isServer如果下棋的是主机
isClient如果下棋的是客户端
主类chessClient方法connectServer(StringserverIP,intserverPort)主要用于连接服务器,客户端与客户端的连接主要通过中介服务器进行连接。
类clientThread继承Thread,acceptMessage(StringrecMessage)负责受到信息并进行转换信息,该类的对象的线程在执行时不断的接收信息,并进行信息转换。
clientThread的一个重要作用为每一个客户端分配一个线程,随着客户端的数量增加,服务器的承受能力也在加重。
客户端最多不能超过100个。
添加游戏中的几个按钮:
controlPad(){
setLayout(newFlowLayout(FlowLayout.LEFT));
add(IPlabel);
add(inputIP);
add(connectButton);
add(creatGameButton);
add(joinGameButton);
add(cancelGameButton);
add(exitGameButton);
}
同时改进服务器,使其可以显示所有连接到服务器的IP和时间,所用端口号等
MessageServer类继承Panel,是面板类的子类主要来实现服务器端的界面布局,在面板类的子类里添加了一个标签和一个文本区。
标签:
statusLabel文本区:
messageBoard。
还定义了两个面板类boardPanel,statusPanel。
将整个面板类的子类的布局设为BorderLayout,将boardPanel的布局设为FlowLayout,将statusPanel的布局设为BorderLayout。
setLayout(newBorderLayout());
boardPanel.setLayout(newFlowLayout());
statusPanel.setLayout(newBorderLayout());
然后将标签:
statusLabel文本区:
messageBoard添加到statusPanel中。
最后在主类里添加了三个按钮messageClearButton,serverStatusButton,erverOffButton添加到了窗体中,在主类的构造函数中对整个服务器端的界面进行了布局。
ServerThread类继承了Thread,它集成了服务器端的所有功能,包括与各客户端之间的相互通信,转发信息。
在循环while(true){}中不断接受客户端的信息,并启动了线程ServerThread的对象,为每一个客户端启动了一个线程,减轻了服务器端的承受能力。
在方法actionPerformed(ActionEvente)实现了按钮的控制功能,
messageClearButton按钮主要功能清空文本区的服务器信息。
serverStatusButton按钮显示服务器信息在文本区。
serverOffButton按钮关闭服务器,与客户端断开连接。
4.6、添加倒计时功能(还没完成)
总结:
部分代码:
判断胜负的代码
publicbooleancheckWin(inta,intb,intcheckColor){
intstep=1,chessLink=1,chessLinkTest=1,chessCompare=0;
if(checkColor==1){
chessLink=1;
for(step=1;step<=4;step++){
for(chessCompare=0;chessCompare<=chessBlackCount;chessCompare++){
if(((a+step)*20==chessBlack_x[chessCompare])
&&((b*20)==chessBlack_y[chessCompare])){
chessLink=chessLink+1;
if(chessLink==5){
return(true);
}
}
}
if(chessLink==(chessLinkTest+1))
chessLinkTest++;
else
break;
}
for(step=1;step<=4;step++){
for(chessCompare=0;chessCompare<=chessBlackCount;chessCompare++){
if(((a-step)*20==chessBlack_x[chessCompare])
&&(b*20==chessBlack_y[chessCompare])){
chessLink++;
if(chessLink==5){
return(true);
}
}
}
if(chessLink==(chessLinkTest+1))
chessLinkTest++;
else
break;
}
chessLink=1;
chessLinkTest=1;
for(step=1;step<=4;step++){
for(chessCompare=0;chessCompare<=chessBlackCount;chessCompare++){
if((a*20==chessBlack_x[chessCompare])
&&((b+step)*20==chessBlack_y[chessCompare])){
chessLink++;
if(chessLink==5){
return(true);
}
}
}
if(chessLink==(chessLinkTest+1))
chessLinkTest++;
else
break;
}
for(step=1;step<=4;step++){
for(chessCompare=0;chessCompare<=chessBlackCount;chessCompare++){
if((a*20==chessBlack_x[chessCompare])
&&((b-step)*20==chessBlack_y[chessCompare])){
chessLink++;
if(chessLink==5){
return(true);
}
}
}
if(chessLink==(chessLinkTest+1))
chessLinkTest++;
else
break;
}
chessLink=1;
chessLinkTest=1;
for(step=1;step<=4;step++){
for(chessCompare=0;chessCompare<=chessBlackCount;chessCompare++){
if(((a-step)*20==chessBlack_x[chessCompare])
&&((b+step)*20==chessBlack_y[chessCompare])){
chessLink++;
if(chessLink==5){
return(true);
}
}
}
if(chessLink==(chessLinkTest+1))
chessL