本实例是一个简单的网络五子棋程序。程序由两个部分组成:一部分为服务器端,另一部分为五子棋客户端。其中服务器端以消息方式完成客户端的管理,客户端支持对弈和聊天。
实例源代码由com.fivechess.chessface、com.fivechess.client、com.fivechess.server三个包组成。
chessServer.java
package com.fivechess.server;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
/**
* 显示服务器及用户信息的Panel类
*/
class MessageServerPanel extends Panel
{
TextArea messageBoard = new TextArea("", 22, 50,
TextArea.SCROLLBARS_VERTICAL_ONLY);
Label statusLabel = new Label("当前连接数:", Label.LEFT);
Panel boardPanel = new Panel();//主显示区Panel
Panel statusPanel = new Panel();//连接状态Panel
MessageServerPanel() {
setSize(350, 300);
setBackground(new Color(204,204,204));
setLayout(new BorderLayout());
boardPanel.setLayout(new FlowLayout());
boardPanel.setSize(210, 210);
statusPanel.setLayout(new BorderLayout());
statusPanel.setSize(210, 50);
boardPanel.add(messageBoard);
statusPanel.add(statusLabel, BorderLayout.WEST);
add(boardPanel, BorderLayout.CENTER);
add(statusPanel, BorderLayout.NORTH);
}
}
/**
* 服务器线程,主要用于服务器与客户端的通信
*/
class ServerThread extends Thread {
Socket clientSocket;
Hashtable clientDataHash;//Socket与发送数据的流的映射
Hashtable clientNameHash;//Socket与用户名的映射
Hashtable chessPeerHash;//对弈的两个客户端用户名的映射
MessageServerPanel server;
boolean isClientClosed = false;
/**
* 服务器端线程的构造函数,用于初始化一些对象。
*/
ServerThread(Socket clientSocket, Hashtable clientDataHash,
Hashtable clientNameHash, Hashtable chessPeerHash,
MessageServerPanel server) {
this.clientSocket = clientSocket;
this.clientDataHash = clientDataHash;
this.clientNameHash = clientNameHash;
this.chessPeerHash = chessPeerHash;
this.server = server;
}
/**
* 对客户端发来的消息处理的函数,处理后转发回客户端。处理消息的过程比较复杂,
* 要针对很多种情况分别处理。
*/
public void messageTransfer(String message) {
String clientName, peerName;
//如果消息以“/”开头,表明是命令消息。
if (message.startsWith("/")) {
//消息以“/changename”开头的几种情况.
if (message.startsWith("/changename ")) {
//获取修改后的用户名
clientName = message.substring(12);
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]" + (String) clientNameHash
.get(clientSocket)))) {
//如果用户正在对弈中,则直接修改Socket和名字的映射Hash表。
synchronized (clientNameHash) {
clientNameHash.put((Socket) getHashKey(
clientNameHash,
("[inchess]" + clientNameHash
.get(clientSocket))),
("[inchess]" + clientName));
chessPeerTalk(("[inchess" + clientName),
("/yourname " + ("[inchess]" + clientName)));
}
}
//如果用户在对弈双方的客户端,做如下处理。
else if (chessPeerHash.containsKey(clientNameHash
.get(clientSocket))) {
//将客户端的新名字映射到clientNameHash
synchronized (clientNameHash) {
clientNameHash.put((Socket) getHashKey(
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((String) chessPeerHash.get(clientName),
("/peer " + "[inchess]" + clientName));
}
// 如果用户在对弈双方的服务端,做如下处理。
else if (chessPeerHash.containsValue(clientNameHash
.get(clientSocket))) {
synchronized (clientNameHash) {
//游戏客户端改名字
clientNameHash.put((Socket) getHashKey(
clientNameHash,
("[inchess]" + clientNameHash
.get(clientSocket))),
("[inchess]" + clientName));
}
synchronized (chessPeerHash) {
//chessPeerHash重新映射
chessPeerHash.put((String) getHashKey(
chessPeerHash, clientNameHash
.get(clientSocket)), clientName);
//向游戏客户端发送新名字
chessPeerTalk(("[inchess]" + clientName),
("/yourname " + ("[inchess]" + clientName)));
}
//向peer游戏客户端发送
chessPeerTalk((String) getHashKey(chessPeerHash,
clientName),
("/peer " + "[inchess]" + clientName));
}
//将改名消息封装好以备发送
message = clientNameHash.get(clientSocket) + "改名为:"
+ clientName;
synchronized (clientNameHash) {
clientNameHash.put(clientSocket, clientName);
}
//向所有的客户端发送消息
publicTalk(message);
//回馈到改名的客户端
Feedback("/yourname "
+ (String) clientNameHash.get(clientSocket));
//刷新用户列表
publicTalk(getUserList());
}
}
//如果消息以“/list”开头,则将其回馈到客户端以更新用户列表
else if (message.equals("/list")) {
Feedback(getUserList());
}
//如果消息以"/creatgame [inchess]"开头,则修改clientNameHash映射
//和chessPeerHash映射。
else if (message.startsWith("/creatgame [inchess]")) {
String chessServerName = 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表。
else if (message.startsWith("/joingame ")) {
StringTokenizer userToken = new StringTokenizer(message, " ");
String getUserToken, serverName, selfName;
String[] chessNameOpt = { "0", "0" };
int getOptNum = 0;
//提取服务端用户名和本地用户名
while (userToken.hasMoreTokens()) {
getUserToken = (String) userToken.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 (Exception ez) {
}
}
}
//如果消息以“/[inchess]”开头,则获取要发送消息的用户名和发送的消息
//然后发送出去。
else if (message.startsWith("/[inchess]")) {
int firstLocation = 0, lastLocation;
lastLocation = message.indexOf(" ", 0);
peerName = message.substring((firstLocation + 1), lastLocation);
message = message.substring((lastLocation + 1));
if (chessPeerTalk(peerName, message)) {
Feedback("/error");
}
}
//如果消息以“/giveup”开头,则判断是对弈双方哪方放弃了。
else if (message.startsWith("/giveup ")) {
String chessClientName = message.substring(8);
if (chessPeerHash.containsKey(chessClientName)
&& !((String) chessPeerHash.get(chessClientName))
.equals("wait")) {
//如果服务方放弃,则发送消息“/youwin”表明对方获胜
chessPeerTalk((String) chessPeerHash.get(chessClientName),
"/youwin");
synchronized (chessPeerHash) {
chessPeerHash.remove(chessClientName);
}
}
if (chessPeerHash.containsValue(chessClientName)) {
//如果客户方放弃,也发送消息“/youwin”表明对方获胜
chessPeerTalk((String) getHashKey(chessPeerHash,
chessClientName), "/youwin");
synchronized (chessPeerHash) {
chessPeerHash.remove((String) getHashKey(chessPeerHash,
chessClientName));
}
}
}
//如果找不到发送消息的用户,则输出消息说“没有这个用户”
else {
int firstLocation = 0, lastLocation;
lastLocation = message.indexOf(" ", 0);
if (lastLocation == -1) {
Feedback("无效命令");
return;
} else {
peerName = message.substring((firstLocation + 1),
lastLocation);
message = message.substring((lastLocation + 1));
message = (String) clientNameHash.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());
}
}
/**
* 发送公共消息的函数,将消息向每个客户端都发送一份
*/
public void publicTalk(String publicTalkMessage) {
synchronized (clientDataHash) {
for (Enumeration enu = clientDataHash.elements(); enu
.hasMoreElements();) {
DataOutputStream outData = (DataOutputStream) enu.nextElement();
try {
outData.writeUTF(publicTalkMessage);
} catch (IOException es) {
es.printStackTrace();
}
}
}
}
/**
* 选择对象发送消息,参数peerTalk为发送的用户名,后面的参数为发送的消息
*/
public boolean peerTalk(String peerTalk, String talkMessage) {
//
for (Enumeration enu = clientDataHash.keys(); enu.hasMoreElements();) {
Socket userClient = (Socket) enu.nextElement();
//找到发送消息的对象,获取它的输出流以发送消息
if (peerTalk.equals((String) clientNameHash.get(userClient))
&& !peerTalk.equals((String) clientNameHash
.get(clientSocket))) {
synchronized (clientDataHash) {
DataOutputStream peerOutData = (DataOutputStream) clientDataHash
.get(userClient);
try {
peerOutData.writeUTF(talkMessage);
} catch (IOException es) {
es.printStackTrace();
}
}
Feedback(talkMessage);
return (false);
}
//如果是发给自己的,直接回馈
else if (peerTalk.equals((String) clientNameHash
.get(clientSocket))) {
Feedback(talkMessage);
return (false);
}
}
return (true);
}
/**
* 此函数也用于选择发送消息,但不能发送给自己。
*/
public boolean chessPeerTalk(String chessPeerTalk, String chessTalkMessage) {
for (Enumeration enu = clientDataHash.keys(); enu.hasMoreElements();) {
Socket userClient = (Socket) enu.nextElement();
if (chessPeerTalk.equals((String) clientNameHash.get(userClient))
&& !chessPeerTalk.equals((String) clientNameHash
.get(clientSocket))) {
synchronized (clientDataHash) {
DataOutputStream peerOutData = (DataOutputStream) clientDataHash
.get(userClient);
try {
peerOutData.writeUTF(chessTalkMessage);
} catch (IOException es) {
es.printStackTrace();
}
}
return (false);
}
}
return (true);
}
/**
* 用于处理消息回馈的函数
*/
public void Feedback(String feedbackString) {
synchronized (clientDataHash) {
DataOutputStream outData = (DataOutputStream) clientDataHash
.get(clientSocket);
try {
outData.writeUTF(feedbackString);
} catch (Exception eb) {
eb.printStackTrace();
}
}
}
/**
* 获取用户列表的函数,此函数读取clientNameHash获取用户列表,
* 然后将其保存在一个字符串userList中。
*/
public String getUserList() {
String userList = "/userlist";
for (Enumeration enu = clientNameHash.elements(); enu.hasMoreElements();) {
userList = userList + " " + (String) enu.nextElement();
}
return userList;
}
/**
* 给出HashTable和值对象,获取相对应得键值的函数。
*/
public Object getHashKey(Hashtable targetHash, Object hashValue) {
Object hashKey;
for (Enumeration enu = targetHash.keys(); enu.hasMoreElements();) {
hashKey = (Object) enu.nextElement();
if (hashValue.equals((Object) targetHash.get(hashKey)))
return (hashKey);
}
return (null);
}
public void firstCome() {
publicTalk(getUserList());
Feedback("/yourname " + (String) clientNameHash.get(clientSocket));
Feedback("Java五子棋聊天客户端");
Feedback("/changename <你的名字> --更改名字");
Feedback("/list --更新用户列表");
Feedback("/<用户名> <要说的话> --私聊");
Feedback("注意:用命令的时候,先把谈话的对象定为所有人");
}
/**
* 用于和客户端断开的函数。
*/
public void clientClose() {
server.messageBoard.append("用户断开:" + clientSocket + "/n");
//如果是游戏客户端主机
synchronized (chessPeerHash) {
if (chessPeerHash.containsKey(clientNameHash.get(clientSocket))) {
chessPeerHash.remove((String) clientNameHash.get(clientSocket));
}
if (chessPeerHash.containsValue(clientNameHash.get(clientSocket))) {
chessPeerHash.put((String) getHashKey(chessPeerHash,
(String) clientNameHash.get(clientSocket)),
"tobeclosed");
}
}
//将保留的HashTable里的数据清除
synchronized (clientDataHash) {
clientDataHash.remove(clientSocket);
}
synchronized (clientNameHash) {
clientNameHash.remove(clientSocket);
}
publicTalk(getUserList());
//计算当前连接数,并显示在状态框中
server.statusLabel.setText("当前连接数:" + clientDataHash.size());
try {
clientSocket.close();
} catch (IOException exx) {
}
isClientClosed = true;
}
public void run() {
DataInputStream inData;
synchronized (clientDataHash) {
server.statusLabel.setText("当前连接数:" + clientDataHash.size());
}
try {
inData = new DataInputStream(clientSocket.getInputStream());
firstCome();
while (true) {
String message = inData.readUTF();
messageTransfer(message);
}
} catch (IOException esx) {
} finally {
if (!isClientClosed) {
clientClose();
}
}
}
}
/**
* @author wufenghanren
* 服务器端框架类
*/
public class chessServer extends Frame implements ActionListener {
Button messageClearButton = new Button("清除显示");
Button serverStatusButton = new Button("服务器状态");
Button serverOffButton = new Button("关闭服务器");
Panel buttonPanel = new Panel();
MessageServerPanel server = new MessageServerPanel();
ServerSocket serverSocket;
Hashtable clientDataHash = new Hashtable(50);
Hashtable clientNameHash = new Hashtable(50);
Hashtable chessPeerHash = new Hashtable(50);
/**
*框架类的构造函数
*/
chessServer() {
super("Java五子棋服务器");
setBackground(new Color(204,204,204));
buttonPanel.setLayout(new FlowLayout());
messageClearButton.setSize(60, 25);
buttonPanel.add(messageClearButton);
messageClearButton.addActionListener(this);
serverStatusButton.setSize(75, 25);
buttonPanel.add(serverStatusButton);
serverStatusButton.addActionListener(this);
serverOffButton.setSize(75, 25);
buttonPanel.add(serverOffButton);
serverOffButton.addActionListener(this);
add(server, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
//退出窗口的监听器
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setVisible(true);
setSize(400, 450);
setResizable(false);
validate();
try {
makeMessageServer(4331, server);
} catch (Exception e) {
System.out.println("e");
}
}
/**
* 初始化消息服务器的类
*/
public void makeMessageServer(int port, MessageServerPanel server)
throws IOException {
Socket clientSocket;
long clientAccessNumber = 1;
this.server = server;
try {
//输出服务器的启动信息
serverSocket = new ServerSocket(port);
server.messageBoard.setText("服务器开始于:"
+ serverSocket.getInetAddress().getLocalHost() + ":"
+ serverSocket.getLocalPort() + "/n");
while (true) {
clientSocket = serverSocket.accept();
server.messageBoard.append("用户连接:" + clientSocket + "/n");
DataOutputStream outData = new DataOutputStream(clientSocket
.getOutputStream());
clientDataHash.put(clientSocket, outData);
clientNameHash
.put(clientSocket, ("新来客" + clientAccessNumber++));
ServerThread thread = new ServerThread(clientSocket,
clientDataHash, clientNameHash, chessPeerHash, server);
thread.start();
}
} catch (IOException ex) {
System.out.println("已经有服务器在运行. /n");
}
}
/**
* 按钮的事件监听器,响应按钮点击事件
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == messageClearButton) {
server.messageBoard.setText("");
}
//当“服务器状态”按钮点击时,显示服务器状态
if (e.getSource() == serverStatusButton) {
try {
server.messageBoard.append("服务器信息:"
+ serverSocket.getInetAddress().getLocalHost() + ":"
+ serverSocket.getLocalPort() + "/n");
} catch (Exception ee) {
System.out
.println("serverSocket.getInetAddress().getLocalHost() error /n");
}
}
if (e.getSource() == serverOffButton) {
System.exit(0);
}
}
public static void main(String args[]) {
chessServer chessServer = new chessServer();
}
}
chessClient.java
package com.fivechess.client;
import com.fivechess.chessface.chatPad;
import com.fivechess.chessface.inputPad;
import com.fivechess.chessface.userPad;
import com.fivechess.chessface.chessPad;
import com.fivechess.chessface.controlPad;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.JColorChooser;
/**
* @author wufenghanren
* 五子棋客户端框架,实现了动作监听器和键盘监听器
*/
public class chessClient extends Frame implements ActionListener, KeyListener {
userPad userpad = new userPad();//用户列表Panel
chatPad chatpad = new chatPad();//聊天信息Panel
controlPad controlpad = new controlPad();//控制Panel
chessPad chesspad = new chessPad();//棋盘Panel
inputPad inputpad = new inputPad();//信息输入Panel
Socket chatSocket;
DataInputStream in;
DataOutputStream out;
String chessClientName = null;
String host = null;
int port = 4331;
boolean isOnChat = false; //是否在聊天
boolean isOnChess = false; //是否在下棋
boolean isGameConnected = false; //是否下棋的客户端连接
boolean isServer = false; //是否建立游戏的主机
boolean isClient = false; //是否加入游戏的客户端
Panel southPanel = new Panel();
Panel centerPanel = new Panel();
Panel westPanel = new Panel();
/*
* 五子棋客户端框架的构造函数。用来初始化一些对象、布局和为按钮添加监听器。
*/
public chessClient() {
super("五子棋客户端");
setLayout(new BorderLayout());
host = controlpad.inputIP.getText();
westPanel.setLayout(new BorderLayout());
westPanel.add(userpad, BorderLayout.NORTH);
westPanel.add(chatpad, BorderLayout.CENTER);
westPanel.setBackground(new Color(204, 204, 204));
inputpad.inputWords.addKeyListener(this);
chesspad.host = controlpad.inputIP.getText();
centerPanel.add(chesspad, BorderLayout.CENTER);
centerPanel.add(inputpad, BorderLayout.SOUTH);
centerPanel.setBackground(new Color(204, 204, 204));
controlpad.connectButton.addActionListener(this);
controlpad.creatGameButton.addActionListener(this);
controlpad.joinGameButton.addActionListener(this);
controlpad.cancelGameButton.addActionListener(this);
controlpad.colorChangeButton.addActionListener(this);
controlpad.exitGameButton.addActionListener(this);
controlpad.creatGameButton.setEnabled(false);
controlpad.joinGameButton.setEnabled(false);
controlpad.cancelGameButton.setEnabled(false);
southPanel.add(controlpad, BorderLayout.CENTER);
southPanel.setBackground(new Color(204, 204, 204));
//添加窗口监听器,当窗口关闭时,关闭用于通讯的Socket。
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isOnChat) {
try {
chatSocket.close();
} catch (Exception ed) {
}
}
if (isOnChess || isGameConnected) {
try {
chesspad.chessSocket.close();
} catch (Exception ee) {
}
}
System.exit(0);
}
});
add(westPanel, BorderLayout.WEST);
add(centerPanel, BorderLayout.CENTER);
add(southPanel, BorderLayout.SOUTH);
setSize(670, 548);
setVisible(true);
setResizable(true);
validate();
}
/**
* 和服务器建立连接并通信的函数。
*/
public boolean connectServer(String serverIP, int serverPort)
throws Exception {
try {
chatSocket = new Socket(serverIP, serverPort);
in = new DataInputStream(chatSocket.getInputStream());
out = new DataOutputStream(chatSocket.getOutputStream());
clientThread clientthread = new clientThread(this);
clientthread.start();
isOnChat = true;
return true;
} catch (IOException ex) {
chatpad.chatLineArea
.setText("chessClient:connectServer:无法连接,建议重新启动程序 /n");
}
return false;
}
/**
* 动作监听器,响应按钮点击动作。
*/
public void actionPerformed(ActionEvent e) {
//如果点击的是“连接主机”按钮,则用获取的服务器主机名连接服务器。
if (e.getSource() == controlpad.connectButton) {
host = chesspad.host = controlpad.inputIP.getText();
try {
if (connectServer(host, port)) {
chatpad.chatLineArea.setText("");
controlpad.connectButton.setEnabled(false);
controlpad.creatGameButton.setEnabled(true);
controlpad.joinGameButton.setEnabled(true);
chesspad.statusText.setText("连接成功,请创建游戏或加入游戏");
}
} catch (Exception ei) {
chatpad.chatLineArea
.setText("controlpad.connectButton:无法连接,建议重新启动程序 /n");
}
}
// 如果点击的是“关闭程序”按钮,则关闭正在进行通信的Socekt并退出游戏。
if (e.getSource() == controlpad.exitGameButton) {
if (isOnChat) {
try {
chatSocket.close();
} catch (Exception ed) {
}
}
if (isOnChess || isGameConnected) {
try {
chesspad.chessSocket.close();
} catch (Exception ee) {
}
}
System.exit(0);
}
//如果点击的是“加入游戏”按钮,则先判断选定的加入的目标是否有效。
//如果选定的目标为空或正在下棋或为其本身,则认为目标无效。
if (e.getSource() == controlpad.joinGameButton) {
String selectedUser = userpad.userList.getSelectedItem();
if (selectedUser == null || selectedUser.startsWith("[inchess]")
|| selectedUser.equals(chessClientName)) {
chesspad.statusText.setText("必须先选定一个有效用户");
} else {
try {
//如果未建立与服务器的连接,创建连接,设定用户的当前状态。
//此外还要对按钮作一些处理,将“创建连接”按钮和“加入游戏按钮”设为不可用。
if (!isGameConnected) {
if (chesspad
.connectServer(chesspad.host, chesspad.port)) {
isGameConnected = true;
isOnChess = true;
isClient = true;
controlpad.creatGameButton.setEnabled(false);
controlpad.joinGameButton.setEnabled(false);
controlpad.cancelGameButton.setEnabled(true);
chesspad.chessthread.sendMessage("/joingame "
+ userpad.userList.getSelectedItem() + " "
+ chessClientName);
}
}
//如果已建立连接,省去建立连接的操作。
else {
isOnChess = true;
isClient = true;
controlpad.creatGameButton.setEnabled(false);
controlpad.joinGameButton.setEnabled(false);
controlpad.cancelGameButton.setEnabled(true);
chesspad.chessthread.sendMessage("/joingame "
+ userpad.userList.getSelectedItem() + " "
+ chessClientName);
}
} catch (Exception ee) {
isGameConnected = false;
isOnChess = false;
isClient = false;
controlpad.creatGameButton.setEnabled(true);
controlpad.joinGameButton.setEnabled(true);
controlpad.cancelGameButton.setEnabled(false);
chatpad.chatLineArea
.setText("chesspad.connectServer无法连接 /n" + ee);
}
}
}
//如果点击的是“创建游戏”按钮,设定用户状态、按钮状态,然后与服务器通讯。
if (e.getSource() == controlpad.creatGameButton) {
try {
//未建立连接时的操作。
if (!isGameConnected) {
if (chesspad.connectServer(chesspad.host, chesspad.port)) {
isGameConnected = true;
isOnChess = true;
isServer = true;
controlpad.creatGameButton.setEnabled(false);
controlpad.joinGameButton.setEnabled(false);
controlpad.cancelGameButton.setEnabled(true);
chesspad.chessthread.sendMessage("/creatgame "
+ "[inchess]" + chessClientName);
}
}
//建立连接时的操作。
else {
isOnChess = true;
isServer = true;
controlpad.creatGameButton.setEnabled(false);
controlpad.joinGameButton.setEnabled(false);
controlpad.cancelGameButton.setEnabled(true);
chesspad.chessthread.sendMessage("/creatgame "
+ "[inchess]" + chessClientName);
}
} catch (Exception ec) {
isGameConnected = false;
isOnChess = false;
isServer = false;
controlpad.creatGameButton.setEnabled(true);
controlpad.joinGameButton.setEnabled(true);
controlpad.cancelGameButton.setEnabled(false);
ec.printStackTrace();
chatpad.chatLineArea.setText("chesspad.connectServer无法连接 /n"
+ ec);
}
}
//如果点击的是“取消游戏”按钮,同样要修改按钮状态。
if (e.getSource() == controlpad.cancelGameButton) {
//如果棋局正在进行,判定退出游戏的一方输
if (isOnChess) {
chesspad.chessthread.sendMessage("/giveup " + chessClientName);
chesspad.chessVictory(-1 * chesspad.chessColor);
controlpad.creatGameButton.setEnabled(true);
controlpad.joinGameButton.setEnabled(true);
controlpad.cancelGameButton.setEnabled(false);
chesspad.statusText.setText("请建立游戏或者加入游戏");
}
if (!isOnChess) {
controlpad.creatGameButton.setEnabled(true);
controlpad.joinGameButton.setEnabled(true);
controlpad.cancelGameButton.setEnabled(false);
chesspad.statusText.setText("请建立游戏或者加入游戏");
}
isClient = isServer = false;
}
//如果点击的是“改变颜色”按钮,则弹出“颜色选择”对话框供用户选择界面颜色。
if (e.getSource() == controlpad.colorChangeButton) {
JColorChooser nextColor = new JColorChooser();
Color selectedColor = JColorChooser.showDialog(this, "选择背景颜色",
Color.BLACK);
chesspad.setBackground(selectedColor);
inputpad.setBackground(selectedColor);
controlpad.setBackground(selectedColor);
chesspad.statusLabel.setBackground(selectedColor);
inputpad.chatLabel.setBackground(selectedColor);
controlpad.IPlabel.setBackground(selectedColor);
westPanel.setBackground(selectedColor);
centerPanel.setBackground(selectedColor);
southPanel.setBackground(selectedColor);
}
}
/**
* 键盘监听器,响应“回车按下”事件.
*/
public void keyPressed(KeyEvent e) {
TextField inputWords = (TextField) e.getSource();
//如果选择向所有人发消息,则将所发消息直接发给服务器
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
if (inputpad.userChoice.getSelectedItem().equals("所有人")) {
try {
out.writeUTF(inputWords.getText());
inputWords.setText("");
} catch (Exception ea) {
chatpad.chatLineArea
.setText("chessClient:KeyPressed无法连接,建议重新连接 /n");
userpad.userList.removeAll();
inputpad.userChoice.removeAll();
inputWords.setText("");
controlpad.connectButton.setEnabled(true);
}
}
//如果选择向一个人发消息,则将所发消息封装成一定格式发给服务器
else {
try {
out.writeUTF("/" + inputpad.userChoice.getSelectedItem()
+ " " + inputWords.getText());
inputWords.setText("");
} catch (Exception ea) {
chatpad.chatLineArea
.setText("chessClient:KeyPressed无法连接,建议重新连接 /n");
userpad.userList.removeAll();
inputpad.userChoice.removeAll();
inputWords.setText("");
controlpad.connectButton.setEnabled(true);
}
}
}
}
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public static void main(String args[]) {
chessClient chessClient = new chessClient();
}
}
/**
* 客户端线程
*/
class clientThread extends Thread {
chessClient chessclient;
clientThread(chessClient chessclient) {
this.chessclient = chessclient;
}
/**
* 客户端线程对接收到的信息进行处理的函数
*/
public void acceptMessage(String recMessage) {
if (recMessage.startsWith("/userlist ")) {
//如果接收到的信息以"/userlist "开头,将其后的用户名提取出来,添加到
//输入信息Panel左边的用户列表中。
StringTokenizer userToken = new StringTokenizer(recMessage, " ");
int userNumber = 0;
chessclient.userpad.userList.removeAll();
chessclient.inputpad.userChoice.removeAll();
chessclient.inputpad.userChoice.addItem("所有人");
while (userToken.hasMoreTokens()) {
String user = (String) userToken.nextToken(" ");
if (userNumber > 0 && !user.startsWith("[inchess]")) {
chessclient.userpad.userList.add(user);
chessclient.inputpad.userChoice.addItem(user);
}
userNumber++;
}
chessclient.inputpad.userChoice.select("所有人");
}
//如果如果接收到的信息以"/yourname "开头,将用户名显示在客户端对话框标题栏。
else if (recMessage.startsWith("/yourname ")) {
chessclient.chessClientName = recMessage.substring(10);
chessclient.setTitle("五子棋客户端 " + "当前用户名:"
+ chessclient.chessClientName);
}
//如果如果接收到的信息以"/reject"开头,在状态栏显示拒绝加入游戏。
else if (recMessage.equals("/reject")) {
try {
chessclient.chesspad.statusText.setText("不能加入游戏");
chessclient.controlpad.cancelGameButton.setEnabled(false);
chessclient.controlpad.joinGameButton.setEnabled(true);
chessclient.controlpad.creatGameButton.setEnabled(true);
} catch (Exception ef) {
chessclient.chatpad.chatLineArea
.setText("chessclient.chesspad.chessSocket.close无法关闭");
}
chessclient.controlpad.joinGameButton.setEnabled(true);
}
//如果如果接收到的信息以"/peer"开头,则记下对方的名字,然后进入等待状态
else if (recMessage.startsWith("/peer ")) {
chessclient.chesspad.chessPeerName = recMessage.substring(6);
if (chessclient.isServer) {
chessclient.chesspad.chessColor = 1;
chessclient.chesspad.isMouseEnabled = true;
chessclient.chesspad.statusText.setText("请黑棋下子");
} else if (chessclient.isClient) {
chessclient.chesspad.chessColor = -1;
chessclient.chesspad.statusText.setText("已加入游戏,等待对方下子...");
}
} else if (recMessage.equals("/youwin")) {
chessclient.isOnChess = false;
chessclient.chesspad.chessVictory(chessclient.chesspad.chessColor);
chessclient.chesspad.statusText.setText("对方退出,请点放弃游戏退出连接");
chessclient.chesspad.isMouseEnabled = false;
} else if (recMessage.equals("/OK")) {
chessclient.chesspad.statusText.setText("创建游戏成功,等待别人加入...");
} else if (recMessage.equals("/error")) {
chessclient.chatpad.chatLineArea.append("传输错误:请退出程序,重新加入 /n");
} else {
chessclient.chatpad.chatLineArea.append(recMessage + "/n");
chessclient.chatpad.chatLineArea
.setCaretPosition(chessclient.chatpad.chatLineArea
.getText().length());
}
}
public void run() {
String message = "";
try {
while (true) {
message = chessclient.in.readUTF();
acceptMessage(message);
}
} catch (IOException es) {
}
}
}
chatPad.java
package com.fivechess.chessface;
import java.awt.BorderLayout;
import java.awt.Panel;
import java.awt.TextArea;
/**
* @author wufenghanren
* 聊天信息Panel。Panel上的文本域可以显示用户聊天信息。
*/
public class chatPad extends Panel {
public TextArea chatLineArea = new TextArea("", 18, 30,
TextArea.SCROLLBARS_VERTICAL_ONLY);
public chatPad() {
setLayout(new BorderLayout());
add(chatLineArea, BorderLayout.CENTER);
}
}
chessPad.java
package com.fivechess.chessface;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
/**
* @author wufenghanren
* 显示棋盘的Panel。此Panel实现了鼠标监听器
*/
public class chessPad extends Panel implements MouseListener {
public int chessPoint_x = -1, chessPoint_y = -1, chessColor = 1;
int chessBlack_x[] = new int[200];//黑子的x坐标
int chessBlack_y[] = new int[200];//黑子的y坐标
int chessWhite_x[] = new int[200];//白子的x坐标
int chessWhite_y[] = new int[200];//白子的y坐标
int chessBlackCount = 0, chessWhiteCount = 0;
int chessBlackWin = 0, chessWhiteWin = 0;
public boolean isMouseEnabled = false, isWin = false, isInGame = false;
public Label statusLabel = new Label("客户端状态");
public TextField statusText = new TextField("请先连接服务器");//显示客户端状态的文本框
public Socket chessSocket;
DataInputStream inData;
DataOutputStream outData;
public String chessSelfName = null;//己方的名字
public String chessPeerName = null;//对方的名字
public String host = null;
public int port = 4331;
public chessThread chessthread = new chessThread(this);
/**
* 棋盘Panel的构造函数
*/
public chessPad() {
setSize(440, 440);
setLayout(null);
setBackground(new Color(204, 204, 204));
addMouseListener(this);
add(statusLabel);
statusLabel.setBounds(30, 5, 70, 24);
add(statusText);
statusText.setBounds(100, 5, 300, 24);
statusText.setEditable(false);
}
/**
* 和服务器通信的函数
*/
public boolean connectServer(String ServerIP, int ServerPort)
throws Exception {
try {
//利用参数创建一个Socket的实例来完成和服务器之间的信息交换
chessSocket = new Socket(ServerIP, ServerPort);
inData = new DataInputStream(chessSocket.getInputStream());
outData = new DataOutputStream(chessSocket.getOutputStream());
chessthread.start();
return true;
} catch (IOException ex) {
statusText.setText("chessPad:connectServer:无法连接 /n");
}
return false;
}
/**
* 一方获胜时的对棋局的处理
*/
public void chessVictory(int chessColorWin) {
//清除所有的棋子
this.removeAll();
//将保存所有黑棋和白棋的位置坐标的数组清空,为西一盘棋做准备。
for (int i = 0; i <= chessBlackCount; i++) {
chessBlack_x[i] = 0;
chessBlack_y[i] = 0;
}
for (int i = 0; i <= chessWhiteCount; i++) {
chessWhite_x[i] = 0;
chessWhite_y[i] = 0;
}
chessBlackCount = 0;
chessWhiteCount = 0;
add(statusText);
statusText.setBounds(40, 5, 360, 24);
//如果黑棋获胜,计算双方获胜盘数,将双方的战绩比在状态文本框显示出来。
if (chessColorWin == 1) {
chessBlackWin++;
statusText.setText("黑棋胜,黑:白为" + chessBlackWin + ":" + chessWhiteWin
+ ",重新开局,等待白棋下子...");
}
//白棋获胜,同上。
else if (chessColorWin == -1) {
chessWhiteWin++;
statusText.setText("白棋胜,黑:白为" + chessBlackWin + ":" + chessWhiteWin
+ ",重新开局,等待黑棋下子...");
}
}
/**
* 将各个棋子的坐标保存在数组里
*/
public void getLocation(int a, int b, int color) {
if (color == 1) {
chessBlack_x[chessBlackCount] = a * 20;
chessBlack_y[chessBlackCount] = b * 20;
chessBlackCount++;
} else if (color == -1) {
chessWhite_x[chessWhiteCount] = a * 20;
chessWhite_y[chessWhiteCount] = b * 20;
chessWhiteCount++;
}
}
/**
* 依据五子棋的行棋规则判断某方获胜
*/
public boolean checkWin(int a, int b, int checkColor) {
int step = 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))
chessLinkTest++;
else
break;
}
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))
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))
chessLinkTest++;
else
break;
}
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))
chessLinkTest++;
else
break;
}
} else if (checkColor == -1) {
chessLink = 1;
for (step = 1; step <= 4; step++) {
for (chessCompare = 0; chessCompare <= chessWhiteCount; chessCompare++) {
if (((a + step) * 20 == chessWhite_x[chessCompare])
&& (b * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if (((a - step) * 20 == chessWhite_x[chessCompare])
&& (b * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if ((a * 20 == chessWhite_x[chessCompare])
&& ((b + step) * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if ((a * 20 == chessWhite_x[chessCompare])
&& ((b - step) * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if (((a - step) * 20 == chessWhite_x[chessCompare])
&& ((b + step) * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if (((a + step) * 20 == chessWhite_x[chessCompare])
&& ((b - step) * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if (((a + step) * 20 == chessWhite_x[chessCompare])
&& ((b + step) * 20 == chessWhite_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 <= chessWhiteCount; chessCompare++) {
if (((a - step) * 20 == chessWhite_x[chessCompare])
&& ((b - step) * 20 == chessWhite_y[chessCompare])) {
chessLink++;
if (chessLink == 5) {
return (true);
}
}
}
if (chessLink == (chessLinkTest + 1))
chessLinkTest++;
else
break;
}
}
return (false);
}
/**
* 绘制棋盘,将棋盘绘制成19*19的个子并将棋盘上应有的五个点绘制上去。
*/
public void paint(Graphics g) {
for (int i = 40; i <= 380; i = i + 20) {
g.drawLine(40, i, 400, i);
}
g.drawLine(40, 400, 400, 400);
for (int j = 40; j <= 380; j = j + 20) {
g.drawLine(j, 40, j, 400);
}
g.drawLine(400, 40, 400, 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 chessPaint(int chessPoint_a, int chessPoint_b, int color) {
chessPoint_black chesspoint_black = new chessPoint_black(this);
chessPoint_white chesspoint_white = new chessPoint_white(this);
if (color == 1 && isMouseEnabled) {
//当黑子落子时,记下此子的位置
getLocation(chessPoint_a, chessPoint_b, color);
//判断是否获胜
isWin = checkWin(chessPoint_a, chessPoint_b, color);
if (isWin == false) {
//如果没有获胜,向对方发送落子信息,并绘制棋子
chessthread.sendMessage("/" + chessPeerName + " /chess "
+ chessPoint_a + " " + chessPoint_b + " " + color);
this.add(chesspoint_black);
chesspoint_black.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
//在状态文本框显示行棋信息
statusText.setText("黑(第" + chessBlackCount + "步)"
+ chessPoint_a + " " + chessPoint_b + ",请白棋下子");
isMouseEnabled = false;
} else {
//如果获胜,直接调用chessVictory完成后续工作
chessthread.sendMessage("/" + chessPeerName + " /chess "
+ chessPoint_a + " " + chessPoint_b + " " + color);
this.add(chesspoint_black);
chesspoint_black.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
chessVictory(1);
isMouseEnabled = false;
}
}
//白棋落子,同黑棋类似处理
else if (color == -1 && isMouseEnabled) {
getLocation(chessPoint_a, chessPoint_b, color);
isWin = checkWin(chessPoint_a, chessPoint_b, color);
if (isWin == false) {
chessthread.sendMessage("/" + chessPeerName + " /chess "
+ chessPoint_a + " " + chessPoint_b + " " + color);
this.add(chesspoint_white);
chesspoint_white.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
statusText.setText("白(第" + chessWhiteCount + "步)"
+ chessPoint_a + " " + chessPoint_b + ",请黑棋下子");
isMouseEnabled = false;
} else {
chessthread.sendMessage("/" + chessPeerName + " /chess "
+ chessPoint_a + " " + chessPoint_b + " " + color);
this.add(chesspoint_white);
chesspoint_white.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
chessVictory(-1);
isMouseEnabled = false;
}
}
}
/**
* 落子时在对方客户端绘制棋子。 对方接受到发送来的落子信息,调用此函数绘制棋子,显示落子状态等等
*/
public void netChessPaint(int chessPoint_a, int chessPoint_b, int color) {
chessPoint_black chesspoint_black = new chessPoint_black(this);
chessPoint_white chesspoint_white = new chessPoint_white(this);
getLocation(chessPoint_a, chessPoint_b, color);
if (color == 1) {
isWin = checkWin(chessPoint_a, chessPoint_b, color);
if (isWin == false) {
this.add(chesspoint_black);
chesspoint_black.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
statusText.setText("黑(第" + chessBlackCount + "步)"
+ chessPoint_a + " " + chessPoint_b + ",请白棋下子");
isMouseEnabled = true;
} else {
this.add(chesspoint_black);
chesspoint_black.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
chessVictory(1);
isMouseEnabled = true;
}
} else if (color == -1) {
isWin = checkWin(chessPoint_a, chessPoint_b, color);
if (isWin == false) {
this.add(chesspoint_white);
chesspoint_white.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
statusText.setText("白(第" + chessWhiteCount + "步)"
+ chessPoint_a + " " + chessPoint_b + ",请黑棋下子");
isMouseEnabled = true;
} else {
chessthread.sendMessage("/" + chessPeerName + " /victory "
+ color);
this.add(chesspoint_white);
chesspoint_white.setBounds(chessPoint_a * 20 - 7,
chessPoint_b * 20 - 7, 16, 16);
chessVictory(-1);
isMouseEnabled = true;
}
}
}
/**
* 当鼠标按下时响应的动作。记下当前鼠标点击的位置,即当前落子的位置。
*/
public void mousePressed(MouseEvent e) {
if (e.getModifiers() == InputEvent.BUTTON1_MASK) {
chessPoint_x = (int) e.getX();
chessPoint_y = (int) e.getY();
int a = (chessPoint_x + 10) / 20, b = (chessPoint_y + 10) / 20;
if (chessPoint_x / 20 < 2 || chessPoint_y / 20 < 2
|| chessPoint_x / 20 > 19 || chessPoint_y / 20 > 19) {
} else {
chessPaint(a, b, chessColor);
}
}
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
}
/**
* 表示黑子的类
*/
class chessPoint_black extends Canvas {
chessPad chesspad = null;
chessPoint_black(chessPad p) {
setSize(20, 20);
chesspad = p;
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.fillOval(0, 0, 14, 14);
}
}
/**
* 表示白子的类
*/
class chessPoint_white extends Canvas {
chessPad chesspad = null;
chessPoint_white(chessPad p) {
setSize(20, 20);
chesspad = p;
}
public void paint(Graphics g) {
g.setColor(Color.white);
g.fillOval(0, 0, 14, 14);
}
}
chessThread.java
package com.fivechess.chessface;
import java.io.IOException;
import java.util.StringTokenizer;
/**
* @author wufenghanren
*/
public class chessThread extends Thread {
chessPad chesspad;
public chessThread(chessPad chesspad) {
this.chesspad = chesspad;
}
/**
* 发送消息
*/
public void sendMessage(String sndMessage) {
try {
chesspad.outData.writeUTF(sndMessage);
} catch (Exception ea) {
System.out.println("chessThread.sendMessage:" + ea);
}
}
/**
* 接收消息
*/
public void acceptMessage(String recMessage) {
//如果收到的消息以“/chess”开头,将其中的坐标信息和颜色信息提取出来
if (recMessage.startsWith("/chess ")) {
StringTokenizer userToken = new StringTokenizer(recMessage, " ");
String chessToken;
String[] chessOpt = { "-1", "-1", "0" };
int chessOptNum = 0;
//使用Tokenizer将空格分隔的字符串分成三段
while (userToken.hasMoreTokens()) {
chessToken = (String) userToken.nextToken(" ");
if (chessOptNum >= 1 && chessOptNum <= 3) {
chessOpt[chessOptNum - 1] = chessToken;
}
chessOptNum++;
}
//将己方的走棋信息如棋子摆放的位置、棋子的颜色为参数,使用netChessPaint函数
//是对方客户端也看到己方的落子位置。
chesspad.netChessPaint(Integer.parseInt(chessOpt[0]), Integer
.parseInt(chessOpt[1]), Integer.parseInt(chessOpt[2]));
} else if (recMessage.startsWith("/yourname ")) {
chesspad.chessSelfName = recMessage.substring(10);
} else if (recMessage.equals("/error")) {
chesspad.statusText.setText("错误:没有这个用户,请退出程序,重新加入");
}
}
public void run() {
String message = "";
try {
while (true) {
message = chesspad.inData.readUTF();
acceptMessage(message);
}
} catch (IOException es) {
}
}
}
controlPad.java
package com.fivechess.chessface;
import java.awt.Button;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
/**
* @author wufenghanren
* 控制Panel。此Panel上的按钮如其名,完成相应的功能。
*/
public class controlPad extends Panel {
public Label IPlabel = new Label("服务器IP:", Label.LEFT);
public TextField inputIP = new TextField("localhost", 10);
public Button connectButton = new Button("连接主机");
public Button creatGameButton = new Button("建立游戏");
public Button joinGameButton = new Button("加入游戏");
public Button cancelGameButton = new Button("放弃游戏");
public Button colorChangeButton = new Button("选择界面颜色");
public Button exitGameButton = new Button("关闭程序");
//构造函数,负责Panel的初始布局。
public controlPad() {
setLayout(new FlowLayout(FlowLayout.LEFT));
setBackground(new Color(204,204,204));
add(IPlabel);
add(inputIP);
add(connectButton);
add(creatGameButton);
add(joinGameButton);
add(cancelGameButton);
add(colorChangeButton);
add(exitGameButton);
}
}
inputPad.java
package com.fivechess.chessface;
import java.awt.Choice;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
/**
* @author wufenghanren
* 输入信息Panel。Panel左边的下拉列表中列出了所有用户的名字。
* 右边的文本框可以输入聊天信息,点击回车信息被发送。
* 此外还可以 在文本框中输入命令如changename、list等。
*/
public class inputPad extends Panel {
public TextField inputWords = new TextField("点击回车发送信息", 20);
public Choice userChoice = new Choice();
public Label chatLabel = new Label("输入发送信息:");
public inputPad() {
setLayout(new FlowLayout(FlowLayout.LEFT));
setBackground(new Color(204, 204, 204));
for (int i = 0; i < 30; i++) {
userChoice.addItem(i + "." + "当前暂无用户");
}
userChoice.setSize(60, 24);
add(userChoice);
add(chatLabel);
add(inputWords);
}
}
userPad.java
package com.fivechess.chessface;
import java.awt.*;
/**
* @author wufenghanren
* 用户列表Panel。此Panel维护一个服务器的当前用户列表,
* 所有的用户名都将显示在列表中。
*/
public class userPad extends Panel {
public List userList = new List(10);
public userPad() {
setLayout(new BorderLayout());
for (int i = 0; i < 30; i++) {
userList.add(i + "." + "当前暂无用户");
}
add(userList, BorderLayout.CENTER);
}
}