提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
简单五子棋小游戏
提示:以下是本篇文章正文内容,下面案例可供参考
一、项目简介
连接服务器与客户端,实现两端之间的交互,实现局域网下的联机五子棋小游戏。可以实现服务器与客户端的聊天功能。
二、功能构架图
三、负责模块
团队成员 | 负责模块 |
---|---|
禹程 | 客户端窗口的搭建,鼠标监听器的添加,游戏按钮的添加和相应功能的实现,输入、聊天等功能的添加 |
梁钊 | 实现客户端与服务器的信息交流,对接收到的信息进行不同情况处理 |
孙文博 | 服务器窗口的搭建,棋盘棋子的绘制,判断输赢等游戏规则的编写 |
四、部分代码
1、窗口的搭建
public class ClientWindow extends JFrame{
public static ClientChessBoard qipan;
ClientChat talk = new ClientChat();;
public ClientWindow(){
qipan = new ClientChessBoard();
this.setSize(1150, 550);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//EXIT_ON_CLOSE(在JFrame中定义:使用System exit方法退出应用程序,仅在应用程序中使用)
this.setTitle("五子棋客户端");
this.add(qipan,BorderLayout.CENTER);
this.add(talk,BorderLayout.WEST);
this.setVisible(true);
}
}
2、游戏规则按钮功能的添加
public class ClientChessBoard extends JPanel {
public ClientChessBoard() {
sendmessage = new Send_message(message, ClientChat.socket);// 创建一个对象,并且实例化
this.setLayout(null);
JButton ks = new JButton("开始/暂停");
ks.setBounds(10, 460, 100, 25);
ks.setBackground(Color.cyan);
this.add(ks);
JButton rs = new JButton("认输");
rs.setBounds(115, 460, 80, 25);
rs.setBackground(Color.cyan);
this.add(rs);
JButton ht = new JButton("后退");
ht.setBounds(200, 460, 80, 25);
ht.setBackground(Color.cyan);
this.add(ht);
JButton cxks = new JButton("重新开始");
cxks.setBounds(290, 460, 100, 25);
cxks.setBackground(Color.cyan);
this.add(cxks);
try {
board = ImageIO.read(new File("img/board.gif"));
black = ImageIO.read(new File("img/black.gif"));
white = ImageIO.read(new File("img/white.gif"));
} catch (IOException e) {
//e.printStackTrace();
}
// 下棋位置
MouseAdapter mouse = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (ClientChat.connect) {
if (isgamestart) {
// 将鼠标点的位置赋值给全局变量
xiaqie = e;
getmouse(xiaqie);
} else {
ClientChat.chatArea.append("\n系统消息:双方至少有一方没有开始游戏");
}
} else {
JOptionPane.showMessageDialog(null, "还没连接服务器!!");
}
}
};
//开始
MouseAdapter start = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (ClientChat.connect) {
myselfok = true;
message = "ANNIU" + "-" + "CLIENT" + "-" + "START";
sendmessage.send(message, ClientChat.socket);// 发送消息给对方说自己准备好了
if (!duifangok) {
ClientChat.chatArea.append("\n系统消息:对方还没有准备好,请等待对方开始游戏");
}
else if (duifangok) {
isgamestart = true;
ClientChat.chatArea.append("\n系统消息:双方准备就绪,游戏即将开始,对方先下,请等待");
}
} else {
ClientChat.chatArea.append("\n系统消息:请先连接服务器!");
}
}
};
MouseAdapter renshu = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (ClientChat.connect) {
if (isgamestart) {
myself_list.clear();
duifang_list.clear();
message = "ANNIU" + "-" + "CLIENT" + "-" + "TOUXIANG";
sendmessage.send(message, ClientChat.socket);
repaint();
}
else {
ClientChat.chatArea.append("\n系统消息:你还没开始游戏");
}
}
else {
ClientChat.chatArea.append("\n系统消息:你还没有连接服务器");
}
}
};
this.addMouseListener(mouse);
ks.addMouseListener(start); // 开始按钮与鼠标相连
rs.addMouseListener(renshu);// 认输按钮与鼠标相连
ht.addMouseListener(houtui); // 后退按钮与鼠标相连
cxks.addMouseListener(chongxinkaishi);// 重新开始按钮与鼠标相连
}
//获取鼠标位置 保存鼠标位置到数集
public void getmouse(MouseEvent e) {
if (!ismyselfxiaqi && isduifangxiaqi) {
int x = e.getX();
int y = e.getY();
getx = (x - 18) / 25;// 减去边距,除以格子的宽度,取整,得到第几格子
gety = (y - 18) / 25;
if ((x - 18) % 25 > 12)
getx = getx + 1;
if ((y - 18) % 25 > 12)
gety = gety + 1;
if (!myself_list.contains(getx + "," + gety)&& !duifang_list.contains(getx + "," + gety)) {
myself_list.add(getx + "," + gety);// 把格子的x坐标和y坐标变成字符串用逗号连接,保存到list里面
ismyselfxiaqi = true;// 自己下完了就不能下,要等对方下了之后才能下
isduifangxiaqi = false;
message = "XIAQI" + "-" + getx + "," + gety + "-" + "CLIENT";
sendmessage.send(message, ClientChat.socket);// 将下的棋子发送给对方
}
repaint();
if (myself_list.size() > 5)
//调用判断胜负方法
baipanduan();
}
}
3.输入、聊天等功能的添加
public class ClientChat extends JPanel {
ClientChessBoard qipan;
public static boolean connect = false;
static TextArea chatArea; // 所有消息内容区域
public static Socket socket; // 连接服务器
private String message = ""; // 要发送给服务器的内容
Send_message sendmessage; // 发送的方法
private String who = "客户端说:";
private JTextField txt_message; // 将要发送给服务器的内容
private JTextField serverip; // 服务器的IP地址
public ClientChat() {
socket =new Socket();
sendmessage = new Send_message(message, socket);
chatArea = new TextArea("聊天窗口\n", 20, 40);//聊天窗口
txt_message = new JTextField("请输入要发送的信息");
serverip = new JTextField("10.186.190.14");
JButton jb_connectserver = new JButton("连接服务器");
JButton jb_send = new JButton("发送");
MouseAdapter connect = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (connectserver()) {
JOptionPane.showMessageDialog(null, "成功连接服务器");
// 客户端连接服务器后才打开线程
Recive_thred rth = new Recive_thred(socket, chatArea,ClientWindow.qipan);
rth.start();
sendmessage.send(message, socket);
}
}
};
// 给服务器发送消息按钮
MouseAdapter send = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
chatArea.append("\n客户端说:" + txt_message.getText());
message = "CHANT" + "-" + who + txt_message.getText() + "\n";
sendmessage.send(message, socket);
}
};
this.add(serverip);
this.add(jb_connectserver);
jb_connectserver.addMouseListener(connect);
this.add(chatArea);
this.add(txt_message);
this.add(jb_send);
jb_send.addMouseListener(send);
}
//连接服务器
public boolean connectserver() {
try {
// 获取输入的IP地址,并且进行连接
socket = new Socket(serverip.getText(), 7778);
chatArea.append("\n连接服务器成功!");
connect = true;
return true;
} catch (UnknownHostException e) {
//e.printStackTrace();
} catch (IOException e) {
//e.printStackTrace();
chatArea.append("\n连接失败");
}
return false;
}
}
4、信息交互
public class Recive_thred extends Thread {
private Socket socket;
TextArea chantArea;
String who;
String[] split;
int xianxing = 1;
JPanel jp = new JPanel();
public Recive_thred(Socket socket, TextArea chantArea, JPanel jp) {
this.socket = socket;
this.chantArea = chantArea;
this.jp = jp;
}
public void run() {
super.run();
InputStream is;
try {
is = socket.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
while (true) {
String m = reader.readLine();
split = m.split("-");
// 聊天控制
if (split[0].equals("CHANT")) {
//System.out.println(split[1]);
if (split[1].equals("OK")) {
chantArea.append("\n" + split[2]);
ServerWindow.clientconnect = true;
} else {
chantArea.append("\n" + split[1]);
}
} else if (split[0].equals("ANNIU")) {
anniucontrol();
}
else if (split[0].equals("XIAQI"))//
{
System.out.println("到下棋来了");
// 下棋控制
who = split[2];
xiaqicontrol();
}
}
} catch (IOException e) {
//e.printStackTrace();
}
}
//按钮控制
public void anniucontrol() {
if (split[1].equals("SERVER")) {
// 收到是从服务器发过来启动的消息,要对客户端里面进行修改
if (split[2].equals("START")) {
ClientChessBoard.duifangok = true;
if (ClientChessBoard.myselfok) {
ClientChessBoard.isgamestart = true;
ClientChat.chatArea.append("\n---系统消息:两方准备就绪,服务器先下---");
}
jp.repaint();
}
// 服务器投降
if (split[2].equals("TOUXIANG")) {
ClientChat.chatArea.append("\n---系统消息:对方已经投降,恭喜你赢了---");
JOptionPane.showMessageDialog(null, "恭喜您,对面怂得投降了!");
// 清除黑棋白棋
ClientChessBoard.myself_list.clear();
ClientChessBoard.duifang_list.clear();
ClientChessBoard.isgamestart = false;
jp.repaint();
}
// 服务器悔棋
if (split[2].equals("HUIQI")) {
ClientChessBoard.duifang_list.remove(ClientChessBoard.duifang_list.get(ClientChessBoard.duifang_list.size() - 1));// 后退
ClientChat.chatArea.append("\n---系统消息:对方毁了一步棋!---");
ClientChessBoard.isduifangxiaqi = false;
ClientChessBoard.ismyselfxiaqi = true;
jp.repaint();
}
// 服务器重新开始
if (split[2].equals("CHONGXINLAI")) {
ClientChat.chatArea.append("\n---系统消息:对方要求重新开始!---");
JOptionPane.showMessageDialog(null, "对方要求开始,确认就清除所有数据,重新开始");
ClientChessBoard.myself_list.clear();
ClientChessBoard.duifang_list.clear();
ClientChessBoard.isgamestart = false;
ClientChessBoard.myselfok = true;
ClientChessBoard.duifangok = false;
jp.repaint();
}
} else if (split[1].equals("CLIENT")) {
// 客户端开始
if (split[2].equals("START")) {
ServerChessBoard.isduifangxiaqi = true;
//System.out.println("线程里面,服务器从客户端收到按下开始按钮");
ServerChessBoard.duifangok = true;
if (ServerChessBoard.myselfok) {
ServerChessBoard.isgamestart = true;
ServerChat.chantArea.append("\n---系统提示:对方准备就绪,游戏开始了,请服务器先下");
}
jp.repaint();
}
// 客户端投降
if (split[2].equals("TOUXIANG")) {
ServerChat.chantArea.append("\n---系统消息:对方已经投降,恭喜你赢了!");
JOptionPane.showMessageDialog(null, "恭喜您,对面投降了!");
// 清除黑棋白棋
ServerChessBoard.myself_list.clear();
ServerChessBoard.duifang_list.clear();
ServerChessBoard.isgamestart = false;
jp.repaint();
}
// 客户端悔棋
if (split[2].equals("HUIQI")) {
if (ServerChessBoard.duifang_list.size() > 0)
ServerChessBoard.duifang_list.remove(ServerChessBoard.duifang_list.get(ServerChessBoard.duifang_list.size() - 1));// 后退
ServerChat.chantArea.append("---系统消息:对方毁了一步棋!---\n");
ServerChessBoard.isduifangxiaqi = false;
ServerChessBoard.ismyselfxiaqi = true;
jp.repaint();
}
// 客户端重新开始
if (split[2].equals("CHONGXINLAI")) {
ServerChat.chantArea.append("\n---系统消息:对方要求重新开始!---");
JOptionPane.showMessageDialog(null, "对方要求开始,确认就清除所有数据,重新开始");
ServerChessBoard.myself_list.clear();
ServerChessBoard.duifang_list.clear();
ServerChessBoard.isgamestart = false;
ServerChessBoard.myselfok = false;
ServerChessBoard.duifangok = true;
jp.repaint();
}
}
}
5、发送功能的实现
public class Send_message {
Socket socket;
String message;
public Send_message(String message, Socket socket) {
this.message = message;
this.socket = socket;
}
public void send(String message, Socket socket) {
OutputStream os;
try {
os= socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write(message);//输出
bw.newLine();//另起一行
bw.flush(); //清除缓存
} catch (IOException e) {
//e.printStackTrace();
}
}
}
6、服务器窗口的搭建
public class ServerWindow extends JFrame {
public static boolean isstart = false;
public static boolean clientconnect=false;
public static Socket socket;
ServerChessBoard qipan;
ServerChat talk;
public static ServerSocket server;
public ServerWindow(){
qipan = new ServerChessBoard();
talk = new ServerChat();
this.setSize(1000, 550);
this.setTitle("五子棋服务器");
this.add(qipan, BorderLayout.CENTER);
this.add(talk, BorderLayout.WEST);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu gameMenu = new JMenu("游戏"); // 创建游戏菜单
// 创建游戏菜单项
JMenuItem connect_ser = new JMenuItem("开启服务器");
connect_ser.addActionListener(new AbstractAction("开启服务器") {
public void actionPerformed(ActionEvent event) {
boolean flag = Serverstart();
if (flag == false) {
JOptionPane.showMessageDialog(null, "开启失败");
return;
} else {
// 服务器开启成功后开启线程
Recive_thred rth = new Recive_thred(socket,ServerChat.chantArea,qipan);
rth.start();
}
}
});
menuBar.add(gameMenu);
gameMenu.add(connect_ser);
this.setVisible(true);
}
五、 运行结果
总结及感想
感受:感受到了项目设计的不易,认识了自己许多学习上的不足,通过实践提高了对理论知识的理解,提高了自己的能力。感受到了合作的重要性,明白了团队力量的强大,希望以后能够学到更多东西。懂得了不要过分沉迷于书本知识,要多多实践,将书上的知识转化成自己的能力,不断提高自己,