网络版五子棋的Java源代码.docx
《网络版五子棋的Java源代码.docx》由会员分享,可在线阅读,更多相关《网络版五子棋的Java源代码.docx(68页珍藏版)》请在冰豆网上搜索。
网络版五子棋的Java源代码
服务器端源代码:
packageorg.shan.server;
importjava.awt.BorderLayout;
importjava.awt.Color;
importjava.awt.FlowLayout;
importjava.awt.Frame;
importjava.awt.Label;
importjava.awt.Panel;
importjava.awt.TextArea;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
import.ServerSocket;
import.Socket;
importjava.util.Enumeration;
importjava.util.Hashtable;
importjava.util.StringTokenizer;
importjavax.swing.JButton;
importjavax.swing.JLabel;
importjavax.swing.JPanel;
importjavax.swing.UIManager;
importorg.jvnet.substance.SubstanceLookAndFeel;
importorg.jvnet.substance.skin.SubstanceOfficeBlue2007LookAndFeel;
/**
*显示服务器及用户信息的Panel类
*/
classMessageServerPanelextendsPanel{
TextAreamessageBoard=newTextArea("",22,50,
TextArea.SCROLLBARS_VERTICAL_ONLY;
JLabelstatusLabel=newJLabel("当前连接数:
",Label.LEFT;
JPanelboardPanel=newJPanel(;//主显示区Panel
JPanelstatusPanel=newJPanel(;//连接状态Panel
MessageServerPanel({
setSize(350,300;
setBackground(newColor(204,204,204;
setLayout(newBorderLayout(;
boardPanel.setLayout(newFlowLayout(;
boardPanel.setSize(210,210;
statusPanel.setLayout(newBorderLayout(;
statusPanel.setSize(210,50;
boardPanel.add(messageBoard;
statusPanel.add(statusLabel,BorderLayout.WEST;
add(boardPanel,BorderLayout.CENTER;
add(statusPanel,BorderLayout.NORTH;
}
}
/**
*服务器线程,主要用于服务器与客户端的通信
*/
classServerThreadextendsThread{
SocketclientSocket;
HashtableclientDataHash;//Socket与发送数据的流的映射
HashtableclientNameHash;//Socket与用户名的映射
HashtablechessPeerHash;//对弈的两个客户端用户名的映射MessageServerPanelserver;
booleanisClientClosed=false;
/**
*服务器端线程的构造函数,用于初始化一些对象。
*/
ServerThread(SocketclientSocket,HashtableclientDataHash,
HashtableclientNameHash,HashtablechessPeerHash,
MessageServerPanelserver{
this.clientSocket=clientSocket;
this.clientDataHash=clientDataHash;
this.clientNameHash=clientNameHash;
this.chessPeerHash=chessPeerHash;
this.server=server;
}
/**
*对客户端发来的消息处理的函数,处理后转发回客户端。
处理消息的过程比较复杂,要针对很多种情况分别处理。
*/
publicvoidmessageTransfer(Stringmessage{
StringclientName,peerName;
//如果消息以“/”开头,表明是命令消息。
if(message.startsWith("/"{
//消息以“/changename”开头的几种情况.
if(message.startsWith("/r"{
//获取修改后的用户名
clientName=message.substring(2;
if(clientName.length(<=0||clientName.length(>20
||clientName.startsWith("/"
||clientNameHash.containsValue(clientName
||clientName.startsWith("changename"
||clientName.startsWith("list"
||clientName.startsWith("[inchess]"
||clientName.startsWith("creatgame"
||clientName.startsWith("joingame"
||clientName.startsWith("yourname"
||clientName.startsWith("userlist"
||clientName.startsWith("chess"
||clientName.startsWith("OK"
||clientName.startsWith("reject"
||clientName.startsWith("peer"
||clientName.startsWith("peername"
||clientName.startsWith("giveup"
||clientName.startsWith("youwin"
||clientName.startsWith("所有人"{
//如果名字不合规则,则向客户端发送信息“无效命令”。
message="无效命令";
Feedback(message;
}else{
if(clientNameHash
.containsValue(("[inchess]"+(StringclientNameHash
.get(clientSocket{
//如果用户正在对弈中,则直接修改Socket和名字的映射Hash表。
synchronized(clientNameHash{
clientNameHash.put((SocketgetHashKey(
clientNameHash,
("[inchess]"+clientNameHash
.get(clientSocket,
("[inchess]"+clientName;
chessPeerTalk(("[inchess"+clientName,
("/yourname"+("[inchess]"+clientName;
}
}
//如果用户在对弈双方的客户端,做如下处理。
elseif(chessPeerHash.containsKey(clientNameHash
.get(clientSocket{
//将客户端的新名字映射到clientNameHash
synchronized(clientNameHash{
clientNameHash.put((SocketgetHashKey(
clientNameHash,
("[inchess]"+clientNameHash
.get(clientSocket,
("[inchess]"+clientName;
}
synchronized(chessPeerHash{
//chessPeerHash添加新名字映射
chessPeerHash.put(clientName,chessPeerHash
.get(clientNameHash.get(clientSocket;
//chessPeerHash删除旧映射
chessPeerHash.remove(clientNameHash
.get(clientSocket;
}
//向游戏客户端发送新名字
chessPeerTalk(("[inchess]"+clientName,
("/yourname"+("[inchess]"+clientName;
//向peer游戏客户端发送
chessPeerTalk((StringchessPeerHash.get(clientName,
("/peer"+"[inchess]"+clientName;
}
//如果用户在对弈双方的服务端,做如下处理。
elseif(chessPeerHash.containsValue(clientNameHash
.get(clientSocket{
synchronized(clientNameHash{
//游戏客户端改名字
clientNameHash.put((SocketgetHashKey(
clientNameHash,
("[inchess]"+clientNameHash
.get(clientSocket,
("[inchess]"+clientName;
}
synchronized(chessPeerHash{
//chessPeerHash重新映射
chessPeerHash.put((StringgetHashKey(
chessPeerHash,clientNameHash
.get(clientSocket,clientName;
//向游戏客户端发送新名字
chessPeerTalk(("[inchess]"+clientName,
("/yourname"+("[inchess]"+clientName;
}
//向peer游戏客户端发送
chessPeerTalk((StringgetHashKey(chessPeerHash,
clientName,
("/peer"+"[inchess]"+clientName;
}
//将改名消息封装好以备发送
message=clientNameHash.get(clientSocket+"改名为:
"
+clientName;
synchronized(clientNameHash{
clientNameHash.put(clientSocket,clientName;
}
//向所有的客户端发送消息
publicTalk(message;
//回馈到改名的客户端
Feedback("/yourname"
+(StringclientNameHash.get(clientSocket;
//刷新用户列表
publicTalk(getUserList(;
}
}
//如果消息以“/list”开头,则将其回馈到客户端以更新用户列表elseif(message.equals("/list"{
Feedback(getUserList(;
}
//如果消息以"/creatgame[inchess]"开头,则修改clientNameHash映射//和chessPeerHash映射。
elseif(message.startsWith("/creatgame[inchess]"{
StringchessServerName=message.substring(20;
synchronized(clientNameHash{
clientNameHash.put(clientSocket,message.substring(11;
}
synchronized(chessPeerHash{
chessPeerHash.put(chessServerName,"wait";
}
Feedback("/yourname"+clientNameHash.get(clientSocket;
chessPeerTalk(chessServerName,"/OK";
publicTalk(getUserList(;
}
//如果消息以“/joingame”开头,则将消息的服务端名字和本地用户名提取出来,
//然后修改clientNameHash表和chessPeerHash表。
elseif(message.startsWith("/joingame"{
StringTokenizeruserToken=newStringTokenizer(message,"";
StringgetUserToken,serverName,selfName;
String[]chessNameOpt={"0","0"};
intgetOptNum=0;
//提取服务端用户名和本地用户名
while(userToken.hasMoreTokens({
getUserToken=(StringuserToken.nextToken("";
if(getOptNum>=1&&getOptNum<=2{
chessNameOpt[getOptNum-1]=getUserToken;
}
getOptNum++;
}
serverName=chessNameOpt[0];
selfName=chessNameOpt[1];
//如果有服务端在等待开始棋局
if(chessPeerHash.containsKey(serverName
&&chessPeerHash.get(serverName.equals("wait"{
//修改Socket和名字映射
synchronized(clientNameHash{
clientNameHash.put(clientSocket,
("[inchess]"+selfName;
}
//修改chessPeerHash映射
synchronized(chessPeerHash{
chessPeerHash.put(serverName,selfName;
}
publicTalk(getUserList(;
chessPeerTalk(selfName,
("/peer"+"[inchess]"+serverName;
chessPeerTalk(serverName,
("/peer"+"[inchess]"+selfName;
}else{
chessPeerTalk(selfName,"/reject";
try{
clientClose(;
}catch(Exceptionez{
}
}
}
//如果消息以“/[inchess]”开头,则获取要发送消息的用户名和发送的消息//然后发送出去。
elseif(message.startsWith("/[inchess]"{
intfirstLocation=0,lastLocation;
lastLocation=message.indexOf("",0;
peerName=message.substring((firstLocation+1,lastLocation;
message=message.substring((lastLocation+1;
if(chessPeerTalk(peerName,message{
Feedback("/error";
}
}
//如果消息以“/giveup”开头,则判断是对弈双方哪方放弃了。
elseif(message.startsWith("/giveup"{
StringchessClientName=message.substring(8;
if(chessPeerHash.containsKey(chessClientName
&&!
((StringchessPeerHash.get(chessClientName
.equals("wait"{
//如果服务方放弃,则发送消息“/youwin”表明对方获胜
chessPeerTalk((StringchessPeerHash.get(chessClientName,
"/youwin";
synchronized(chessPeerHash{
chessPeerHash.remove(chessClientName;
}
}
if(chessPeerHash.containsValue(chessClientName{
//如果客户方放弃,也发送消息“/youwin”表明对方获胜
chessPeerTalk((StringgetHashKey(chessPeerHash,
chessClientName,"/youwin";
synchronized(chessPeerHash{
chessPeerHash.remove((StringgetHashKey(chessPeerHash,
chessClientName;
}
}
}
//如果找不到发送消息的用户,则输出消息说“没有这个用户”
else{
intfirstLocation=0,lastLocation;
lastLocation=message.indexOf("",0;
if(lastLocation==-1{
Feedback("无效命令";
return;
}else{
peerName=message.substring((firstLocation+1,
lastLocation;
message=message.substring((lastLocation+1;
message=(StringclientNameHash.get(clientSocket+">"
+message;
if(peerTalk(peerName,message{
Feedback("没有这个用户:
"+peerName+"\n";
}
}
}
}
//如果不以“/”开头,表明是普通消息,直接发送
else{
message=clientNameHash.get(clientSocket+">"+message;
server.messageBoard.append(message+"\n";
publicTalk(message;
server.messageBoard.setCaretPosition(server.messageBoard.getText(
.length(;
}
}
/**
*发送公共消息的函数,将消息向每个客户端都发送一份
*/
publicvoidpublicTalk(StringpublicTalkMessage{
synchronized(clientDataHash{
for(Enumerationenu=clientDataHash.elements(;enu
.hasMoreElements(;{
DataOutputStreamoutData=(DataOutputStreamenu.nextElement(;
try{
outData.writeUTF(publicTalkMessage;
}catch(IOExceptiones{
es.printStackTrace(;
}
}
}
}
/**
*选择对象发送消息,参数peerTalk为发送的用户名,后面的参数为发送的消息*/
publicbooleanpeerTalk(StringpeerTalk,StringtalkMessage{
//
for(Enumerationenu=clientDataHash.keys(;enu.hasMoreElements(;{SocketuserClient=(Socketenu.nextElement(;
//找到发送消息的对象,获取它的输出流以发送消息
if(peerTalk.equals((StringclientNameHash.get(userClient
&&!
peerTalk.equals((StringclientNameHash
.get(clientSocket{
synchronized(clientDataHash{
DataOutputStreampeerOutData=(DataOutputStreamclientDataHash
.get(userClient;
try{
peerOutData.writeUTF(talkMessage;
}catch(IOExceptiones{
es.printStackTrace(;
}
}
Feedback(talkMessage;
return(false;
}
//如果是发给自己的,直接回馈
elseif(peerTalk.equals((StringclientNameHash.get(clientSocket{
Feedback(talkMessage;
return(false;
}
}
return(true;
}
/**
*此函数也用于选择发送消息,但