⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omokserver.java

📁 Java Swing开发的网络对战五子棋游戏
💻 JAVA
字号:

import java.net.*;
import java.io.*;
import java.util.*;

public class OmokServer {

    private ServerSocket server;
    private BManager bMan = new BManager();	//消息广播者
    private Random rnd = new Random();	//随机确定黑棋或白棋

    public OmokServer() {
    }

    void startServer() {	//启动服务器
	try {
	    server = new ServerSocket(7777);
	    System.out.println("服务器套接字已被创建");
	    while (true) {
		//获取与客户端连接的套接字
		Socket socket = server.accept();
		//创建并启动线程
		Omok_Thread ot = new Omok_Thread(socket);
		ot.start();
		//向bMain添加线程
		bMan.add(ot);
		System.out.println("连接数:" + bMan.size());
	    }
	} catch (Exception e) {
	    System.out.println(e);
	}
    }

    public static void main(String[] args) {
	OmokServer server = new OmokServer();
	server.startServer();
    }
    //负责与客户端通信的线程类
    class Omok_Thread extends Thread {

	private int roomNumber = -1;
	private String userName = null;	//用户名
	private Socket socket;	//套接字
	//游戏准备是否就绪
	private boolean ready = false;
	private BufferedReader reader;
	private PrintWriter writer;

	Omok_Thread(Socket socket) {
	    this.socket = socket;
	}

	Socket getSocket() {	//获取套接字
	    return socket;
	}

	int getRoomNumber() {	//获取房间号
	    return roomNumber;
	}

	String getUserName() {	//获取用户名
	    return userName;
	}

	boolean isReady() {	//获取准备状态
	    return ready;
	}

	public void run() {
	    try {
		reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		writer = new PrintWriter(socket.getOutputStream(), true);
		String msg;	//客户机消息
		while ((msg = reader.readLine()) != null) {
		    //若msg以【NAME】开始
		    if (msg.startsWith("[NAME]")) {
			userName = msg.substring(6);
		    } //若msg以【ROOM】开始,则设定房间
		    else if (msg.startsWith("[ROOM]")) {
			int roomNum = Integer.parseInt(msg.substring(6));
			if (!bMan.isFull(roomNum)) {
			    //通知本房间的其他用户一个用户退出
			    if (roomNumber != -1) {
				bMan.sendToOthers(this, "[EXIT]" + userName);
			    }
			    //指定用户的新房间号
			    roomNumber = roomNum;
			    //向用户原样发送消息,然后通知可以进入
			    writer.println(msg);
			    //向用户传送新房间中用户名列表
			    writer.println(bMan.getNamesInRoom(roomNumber));
			    //通知新房间中的其他用户某个用户入场
			    bMan.sendToOthers(this, "[ENTER]" + userName);
			} else {
			    //通知用户房间人数已满
			    writer.println("[FULL]");
			}
		    } 
		    //将【STONE】消息传递给对方
		    else if (roomNumber >= 1 && msg.startsWith("[STONE]")) {
			bMan.sendToOthers(this, msg);
		    } 
		    //向房间传送对话消息
		    else if (msg.startsWith("[MSG]")) {
			bMan.sendToRoom(roomNumber, "[" + userName + "]: " + msg.substring(5));
		    } 
		    //若msg以【START】开始
		    else if (msg.startsWith("[START]")) {
			//游戏开始准备完毕
			ready = true;
			//若其他用户也做好了游戏开始的准备
			if (bMan.isReady(roomNumber)) {
			    //确定黑子与白子并向用户及对手传送
			    int a = rnd.nextInt(2);
			    if (a == 0) {
				writer.println("[COLOR]BLACK");
				bMan.sendToOthers(this, "[COLOR]WHITE");
			    } else {
				writer.println("[COLOR]WHITE");
				bMan.sendToOthers(this, "[COLOR]BLACK");
			    }
			}
		    } 
		    //若用户发送终止游戏的消息
		    else if (msg.startsWith("[STOPGAME]")) {
			ready = false;
		    } 
		    //若用户发送弃权消息
		    else if (msg.startsWith("[DROPGAME]")) {
			ready = false;
			//通知对手用户已经弃权
			bMan.sendToOthers(this, "[DROPGAME]");
		    } 
		    //若发送用户获胜的消息
		    else if (msg.startsWith("[WIN]")) {
			ready = false;
			//向用户发送消息
			writer.println("[WIN]");
			//通知对手已输
			bMan.sendToOthers(this, "[LOSE]");
		    }
		}
	    } catch (Exception e) {
		e.printStackTrace();
	    } finally {
		try {
		    bMan.remove(this);
		    if (reader != null) {
			reader.close();
		    }
		    if (writer != null) {
			writer.close();
		    }
		    if (socket != null) {
			socket.close();
		    }
		    reader = null;
		    writer = null;
		    socket = null;
		    System.out.println(userName + "已断线");
		    System.out.println("连接人数: " + bMan.size());
		    //将用户断线的消息在同一房间发布
		    bMan.sendToRoom(roomNumber, "[DISCONNECT]" + userName);
		} catch (Exception e) {
		}
	    }
	}
    }

    //消息广播者类
    class BManager extends Vector {

	BManager() {
	}
	//添加线程
	void add(Omok_Thread ot) {
	    super.add(ot);
	}

	void remove(Omok_Thread ot) {
	    super.remove(ot);
	}
	//获取第i个线程
	Omok_Thread getOT(int i) {
	    return (Omok_Thread) elementAt(i);
	}
	//获取第i个线程的套接字
	Socket getSocket(int i) {
	    return getOT(i).getSocket();
	}
	//向与第i个线程连接的客户机发送消息
	void sendTo(int i, String msg) {
	    try {
		PrintWriter pw = new PrintWriter(getSocket(i).getOutputStream(), true);
		pw.println(msg);
	    } catch (Exception e) {
	    }
	}
	//获取第i个线程的房间号
	int getRoomNumber(int i) {
	    return getOT(i).getRoomNumber();
	}
	//判断房间是否满员
	synchronized boolean isFull(int roomNum) {
	    //待机室未满
	    if (roomNum == 0) {
		return false;
	    }
	    //其他房间不允许2名以上进入
	    int count = 0;
	    for (int i = 0; i < size(); i++) {
		if (roomNum == getRoomNumber(i)) {
		    count++;
		}
	    }
	    if (count >= 2) {
		return true;
	    }
	    return false;
	}
	//向roomNum房间发送msg
	void sendToRoom(int roomNum, String msg) {
	    for (int i = 0; i < size(); i++) {
		if (roomNum == getRoomNumber(i)) {
		    sendTo(i, msg);
		}
	    }
	}
	//向与ot在同一房间的其他用户发送msg
	void sendToOthers(Omok_Thread ot, String msg) {
	    for (int i = 0; i < size(); i++) {
		if (getRoomNumber(i) == ot.getRoomNumber() && getOT(i) != ot) {
		    sendTo(i, msg);
		}
	    }
	}
	//判断是否已经做好游戏开始的准备
	//若两名用户同时做好了游戏开始的准备,则返回true
	synchronized boolean isReady(int roomNum) {
	    int count = 0;
	    for (int i = 0; i < size(); i++) {
		if (roomNum == getRoomNumber(i) && getOT(i).isReady()) {
		    count++;
		}
	    }
	    if (count == 2) {
		return true;
	    }
	    return false;
	}
	//获取roomNum房间中用户的名字
	String getNamesInRoom(int roomNum) {
	    StringBuffer sb = new StringBuffer("[PLAYERS]");
	    for (int i = 0; i < size(); i++) {
		if (roomNum == getRoomNumber(i)) {
		    sb.append(getOT(i).getUserName() + "\t");
		}
	    }
	    return sb.toString();
	}
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -