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

📄 omokclient.java

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

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

//五子棋盘类
class OmokBoard extends Canvas {

    public static final int BLACK = 1,  WHITE = -1; //黑白子常数
    private int[][] map; //map数组
    private int size,  cell;	 //棋盘大小,棋盘格大小
    private String info = "游戏终止";    //游戏状态字符串
    private int color = BLACK;	 //用户的棋子颜色
    //是否可以放置棋子
    private boolean enable = false;
    //显示游戏是否进行的变量
    private boolean running = false;
    //向对手传递消息的流
    private PrintWriter writer;
    private Graphics gboard,  gbuff;
    private Image buff;

    OmokBoard(int s, int c) {
	this.size = s;
	this.cell = c;
	map = new int[size + 2][];
	for (int i = 0; i < map.length; i++) {
	    map[i] = new int[size + 2];
	}
	//设定五子棋盘背景色
	setBackground(new Color(200, 200, 100));
	//计算棋盘大小
	setSize(size * (cell + 1) + size, size * (cell + 1) + size);
	addMouseListener(new MouseAdapter() {
	    //棋盘鼠标事件处理
	    @Override
	    public void mousePressed(MouseEvent me) {
		if (!enable) {
		    return;
		}
		//将鼠标坐标转换为map坐标
		int x = (int) Math.round(me.getX() / (double) cell);
		int y = (int) Math.round(me.getY() / (double) cell);
		//若不是放置棋子的坐标,则退出
		if (x == 0 || y == 0 || x == size + 1 || y == size + 1) {
		    return;
		}
		//若棋盘上已经放置了棋子,则退出
		if (map[x][y] == BLACK || map[x][y] == WHITE) {
		    return;
		}
		//向对手发送棋子坐标
		writer.println("[STONE]" + x + " " + y);
		map[x][y] = color;
		//检查获胜与否
		if (check(new Point(x, y), color)) {
		    info = "获胜";
		    writer.println("[WIN]");
		} else {
		    info = "等待对方落子";
		}
		//绘制棋盘
		repaint();
		//使用户不可下子
		//若对手已经下子,则enable为true,用户可以落子
		enable = false;
	    }
	});
    }
    //获取游戏的进行状态
    public boolean isRunning() {
	return running;
    }
    //开始游戏
    public void startGame(String col) {
	running = true;
	//若黑棋被选中
	if (col.equals("BLACK")) {
	    enable = true;
	    color = BLACK;
	    info = "开始游戏......请落子";
	} //若白棋被选中
	else {
	    enable = false;
	    color = WHITE;
	    info = "开始游戏......请等待";
	}
    }
    //停止游戏
    public void stopGame() {
	//初始化棋盘
	reset();
	//向对手发送消息
	writer.println("[STOPGAME]");
	enable = false;
	running = false;
    }

    public void putOpponent(int x, int y) {
	map[x][y] = -color;
	info = "对手已经落子,请落子";
	repaint();
    }

    public void setEnable(boolean enable) {
	this.enable = enable;
    }

    public void setWriter(PrintWriter writer) {
	this.writer = writer;
    }
    //调用repaint()时自动调用
    @Override
    public void update(Graphics g) {
	paint(g);
    }
    //绘制画面
    @Override
    public void paint(Graphics g) {
	if (gbuff == null) {
	    buff = createImage(getWidth(), getHeight());
	    gbuff = buff.getGraphics();
	}
	//绘制棋盘
	drawBoard(g);
    }
    //初始化棋盘
    public void reset() {
	for (int i = 0; i < map.length; i++) {
	    for (int j = 0; j < map[i].length; j++) {
		map[i][j] = 0;
	    }
	}
	info = "游戏终止";
	repaint();
    }
    //在棋盘上画线
    private void drawLine() {
	gbuff.setColor(Color.black);
	for (int i = 1; i <= size; i++) {
	    gbuff.drawLine(cell, i * cell, cell * size, i * cell);
	    gbuff.drawLine(i * cell, cell, i * cell, cell * size);
	}
    }
    //在(x,y)上绘制黑子
    private void drawBlack(int x, int y) {
	Graphics2D gbuf = (Graphics2D) this.gbuff;
	gbuf.setColor(Color.black);
	gbuf.fillOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
	gbuf.setColor(Color.white);
	gbuf.drawOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
    }
    //在(x,y)上绘制白子
    private void drawWhite(int x, int y) {
	gbuff.setColor(Color.white);
	gbuff.fillOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
	gbuff.setColor(Color.black);
	gbuff.drawOval(x * cell - cell / 2, y * cell - cell / 2, cell, cell);
    }
    //绘制map中的所有棋子
    private void drawStones() {
	for (int x = 1; x <= size; x++) {
	    for (int y = 1; y <= size; y++) {
		if (map[x][y] == BLACK) {
		    drawBlack(x, y);
		} else if (map[x][y] == WHITE) {
		    drawWhite(x, y);
		}
	    }
	}
    }
    //绘制棋盘
    synchronized private void drawBoard(Graphics g) {
	gbuff.clearRect(0, 0, getWidth(), getHeight());
	drawLine();
	drawStones();
	gbuff.setColor(Color.red);
	gbuff.drawString(info, 20, 15);
	g.drawImage(buff, 0, 0, this);
    }

    private boolean check(Point p, int col) {
	if (count(p, 1, 0, col) + count(p, -1, 0, col) == 4) {
	    return true;
	}
	if (count(p, 0, 1, col) + count(p, 0, -1, col) == 4) {
	    return true;
	}
	if (count(p, -1, -1, col) + count(p, 1, 1, col) == 4) {
	    return true;
	}
	if (count(p, 1, -1, col) + count(p, -1, 1, col) == 4) {
	    return true;
	}
	return false;
    }

    @SuppressWarnings("empty-statement")
    private int count(Point p, int dx, int dy, int col) {
	int i = 0;
	for (; map[p.x + (i + 1) * dx][p.y + (i + 1) * dy] == col; i++);
	return i;
    }
}

public class OmokClient extends Frame implements Runnable, ActionListener {
    //显示消息的多行文本框
    private TextArea msgView = new TextArea("", 1, 1, 1);
    //记录待发消息的对话框
    private TextField sendBox = new TextField("");
    //用户名对话框
    private TextField nameBox = new TextField();
    //房间号对话框
    private TextField roomBox = new TextField("0");
    //显示连接人数的标签
    private Label pInfo = new Label("待机室:   名");
    //显示用户名单的列表
    private java.awt.List pList = new java.awt.List();
    private Button startButton = new Button("开始对决");
    private Button stopButton = new Button("弃权");
    private Button enterButton = new Button("入场");
    private Button exitButton = new Button("去待机室");
    //显示各种信息的标签
    private Label infoView = new Label("< Thingking Java >", 1);
    private OmokBoard board = new OmokBoard(15, 30);//棋盘对象
    private BufferedReader reader;//输入流
    private PrintWriter writer;//输出流
    private Socket socket;//套接字
    private int roomNumber = -1;//房间号
    private String userName = null;//用户名

    public OmokClient(String title) {
	super(title);
	setLayout(null);//不使用任何布局
	msgView.setEditable(false);
	//创建并排列各种组件
	infoView.setBounds(10, 30, 480, 30);
	infoView.setBackground(new Color(200, 200, 255));
	board.setLocation(10, 70);
	add(infoView);
	add(board);
	Panel p = new Panel();
	p.setBackground(new Color(200, 255, 255));
	p.setLayout(new GridLayout(3, 3));
	p.add(new Label("名字:", 2));
	p.add(nameBox);
	p.add(new Label("房间号:", 2));
	p.add(roomBox);
	p.add(enterButton);
	p.add(exitButton);
	enterButton.setEnabled(false);
	p.setBounds(500, 30, 250, 70);

	Panel p2 = new Panel();
	p2.setBackground(new Color(255, 255, 100));
	p2.setLayout(new BorderLayout());
	Panel p2_1 = new Panel();
	p2_1.add(startButton);
	p2_1.add(stopButton);
	p2.add(pInfo, "North");
	p2.add(pList, "Center");
	p2.add(p2_1, "South");
	startButton.setEnabled(false);
	stopButton.setEnabled(false);
	p2.setBounds(500, 110, 250, 180);

	Panel p3 = new Panel();
	p3.setLayout(new BorderLayout());
	p3.add(msgView, "Center");
	p3.add(sendBox, "South");
	p3.setBounds(500, 300, 250, 250);

	add(p);
	add(p2);
	add(p3);
	//注册事件监听器
	sendBox.addActionListener(this);
	enterButton.addActionListener(this);
	exitButton.addActionListener(this);
	startButton.addActionListener(this);
	stopButton.addActionListener(this);
	addWindowListener(new WindowAdapter() {
	    //关闭窗口
	    @Override
	    public void windowClosing(WindowEvent we) {
		System.exit(0);
	    }
	});
    }
    //组件动作事件处理
    @Override
    public void actionPerformed(ActionEvent ae) {
	//若为消息输入对话框
	if (ae.getSource() == sendBox) {
	    String msg = sendBox.getText();
	    if (msg.length() == 0) {
		return;
	    }
	    if (msg.length() >= 30) {
		msg = msg.substring(0, 30);
	    }
	    try {
		writer.println("[MSG]" + msg);
		sendBox.setText("");
	    } catch (Exception ie) {
	    }
	} 
	//若为入场按钮
	else if (ae.getSource() == enterButton) {
	    try {

		if (Integer.parseInt(roomBox.getText()) < 1) {
		    infoView.setText("房间号错误,大于1");
		    return;
		}
		writer.println("[ROOM]" + Integer.parseInt(roomBox.getText()));
		msgView.setText("");
	    } catch (Exception ie) {
		infoView.setText("输入的事项发生错误");
	    }
	} else if (ae.getSource() == exitButton) {
	    try {
		goToWaitRoom();
		startButton.setEnabled(false);
		stopButton.setEnabled(false);
	    } catch (Exception e) {
	    }
	} 
	//若为对决开始按钮
	else if (ae.getSource() == startButton) {
	    try {
		writer.println("[START]");
		infoView.setText("等待对方决定");
		startButton.setEnabled(false);
	    } catch (Exception e) {
	    }
	} 
	//若为弃权按钮
	else if (ae.getSource() == stopButton) {
	    try {
		writer.println("[DROPGAME]");
		endGame("已弃权");
	    } catch (Exception e) {
	    }
	}
    }
    //点击进入待机室按钮时被调用
    void goToWaitRoom() {
	if (userName == null) {
	    String name = nameBox.getText().trim();
	    if (name.length() <= 2 || name.length() > 10) {
		infoView.setText("名字错误.3-10个字");
		nameBox.requestFocus();
		return;
	    }
	    userName = name;
	    writer.println("[NAME]" + userName);
	    nameBox.setText(userName);
	    nameBox.setEditable(false);
	}
	msgView.setText("");
	writer.println("[ROOM]0");
	infoView.setText("已经进入待机室");
	roomBox.setText("0");
	enterButton.setEnabled(true);
	exitButton.setEnabled(false);
    }

    @Override
    public void run() {
	String msg; //来自服务器的消息
	try {
	    while ((msg = reader.readLine()) != null) {
		if (msg.startsWith("[STONE]")) {
		    String temp = msg.substring(7);
		    int x = Integer.parseInt(temp.substring(0, temp.indexOf(" ")));
		    int y = Integer.parseInt(temp.substring(temp.indexOf(" ") + 1));
		    //绘制对方棋子
		    board.putOpponent(x, y);
		    board.setEnable(true);
		} 
		//进入房间
		else if (msg.startsWith("[ROOM]")) {
		    //若非待机室
		    if (!msg.equals("[ROOM]0")) {
			enterButton.setEnabled(false);
			exitButton.setEnabled(true);
			infoView.setText(msg.substring(6) + "号房间已被进入");
		    } else {
			infoView.setText("已进入待机室");
		    }
		    //指定房间号
		    roomNumber = Integer.parseInt(msg.substring(6));
		    //若游戏进行中
		    if (board.isRunning()) {
			board.stopGame();
		    }
		} 
		//若房间已满
		else if (msg.startsWith("[FULL]")) {
		    infoView.setText("房间已满,禁止入内");
		} 
		//房中用户名单
		else if (msg.startsWith("[PLAYERS]")) {
		    nameList(msg.substring(9));
		} else if (msg.startsWith("[ENTER]")) {
		    pList.add(msg.substring(7));
		    playersInfo();
		    msgView.append("[" + msg.substring(7) + "]入场.\n");
		} 
		//退出
		else if (msg.startsWith("[EXIT]")) {
		    //从列表中删除
		    pList.remove(msg.substring(6));
		    //重新计算并显示人数
		    playersInfo();
		    msgView.append("[" + msg.substring(6) + "]进入其他房间.\n");
		    if (roomNumber != 0) {
			endGame("对方离开.");
		    }
		} 
		//连接中断
		else if (msg.startsWith("[DISCONNECT]")) {
		    pList.remove(msg.substring(12));
		    playersInfo();
		    msgView.append("[" + msg.substring(12) + "]中断连接.\n");
		    if (roomNumber != 0) {
			endGame("对方离开.");
		    }
		} else if (msg.startsWith("[COLOR]")) {
		    String color = msg.substring(7);
		    board.startGame(color);
		    if (color.equals("BLACK")) {
			infoView.setText("得到黑子.");
		    } else {
			infoView.setText("得到白子.");
		    }
		    stopButton.setEnabled(true);
		} 
		//激活弃权按钮
		else if (msg.startsWith("[DROPGAME]")) {
		    endGame("对方弃权.");
		} 
		//若已获胜
		else if (msg.startsWith("[WIN]")) {
		    endGame("获胜.");
		} 
		//若失败
		else if (msg.startsWith("[LOSE]")) {
		    endGame("失败.");
		} else {
		    msgView.append(msg + "\n");
		}
	    }
	} catch (IOException ie) {
	    msgView.append(ie + "\n");
	}
	msgView.append("连接中断.");
    }
    //终止游戏
    private void endGame(String msg) {
	infoView.setText(msg);
	startButton.setEnabled(false);
	stopButton.setEnabled(false);
	try {
	    Thread.sleep(2000);
	} catch (Exception e) {
	    e.printStackTrace();
	}
	if (board.isRunning()) {
	    board.stopGame();
	}
	if (pList.getItemCount() == 2) {
	    startButton.setEnabled(true);
	}
    }
    //显示房间的连接人数
    private void playersInfo() {
	int count = pList.getItemCount();
	if (roomNumber == 0) {
	    pInfo.setText("待机室: " + count + "名");
	} else {
	    pInfo.setText(roomNumber + " 号房: " + count + "名");
	}
	if (count == 2 && roomNumber != 0) {
	    startButton.setEnabled(true);
	} else {
	    startButton.setEnabled(false);
	}
    }

    private void nameList(String msg) {
	pList.removeAll();
	StringTokenizer st = new StringTokenizer(msg, "\t");
	while (st.hasMoreElements()) {
	    pList.add(st.nextToken());
	}
	playersInfo();
    }
    //连接
    private void connect() {
	try {
	    msgView.append("请求连接服务器.\n");
	    socket = new Socket("192.168.1.119", 7777);
	    msgView.append("-- 连接成功 --.\n");
	    msgView.append("请输入大名,然后进入待机室.\n");
	    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
	    writer = new PrintWriter(socket.getOutputStream(), true);
	    new Thread(this).start();
	    board.setWriter(writer);
	} catch (Exception e) {
	    msgView.append(e + "\n\n连接失败...\n");
	}
    }

    public static void main(String[] args) {
	OmokClient client = new OmokClient("网络五子棋游戏");
	client.setSize(760, 560);
	client.setVisible(true);
	client.connect();
    }
}

⌨️ 快捷键说明

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