五子棋(二)联网版

本文介绍了一个简单的五子棋游戏实现方案,包括棋盘绘制、走棋逻辑、胜负判断等功能,并实现了双人在线对战模式。
package com.lovo;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;

/**
 * 棋盘类
 */
public class Board {
	private int[][] b = new int[15][15];

	/**
	 * 绘制棋盘
	 * @param g 画笔
	 */
	public void draw(Graphics g) {
		g.setColor(Color.BLACK);
		
		Graphics2D g2d = (Graphics2D) g; 	// 画笔加粗需要引用的处理;
		Stroke oldStroke = g2d.getStroke(); // 记录画笔原来的粗细(保存现场)
		g2d.setStroke(new BasicStroke(5)); 	// 修改画笔的粗细
		g.drawRect(50, 50, 700, 700); 		// 绘制边框
		g2d.setStroke(oldStroke); 			// 将画笔还远为原来的粗细(恢复现场)

		for (int i = 0; i < 13; i++) {
			g.drawLine(50, 100 + 50 * i, 750, 100 + 50 * i);
			g.drawLine(100 + 50 * i, 50, 100 + 50 * i, 750);
		}
		
		// 绘制天元
		g.fillOval(390, 390, 20, 20);

		// 绘制四颗星
		g.fillOval(195, 195, 10, 10);
		g.fillOval(595, 595, 10, 10);
		g.fillOval(195, 595, 10, 10);
		g.fillOval(595, 195, 10, 10);
		
		for(int i =0; i < b.length; i++){            // 行控制纵坐标
			for(int j =0; j < b[i].length; j++){     // 列控制横坐标
				if(b[i][j] != 0) {
					g.setColor(b[i][j] == 1? Color.BLACK : Color.WHITE);	// 设置画笔颜色
					g.fillOval(25 + 50 * j, 25 + 50 * i, 50, 50);			// 绘制棋子
				}
			}
		}

	}
	
	/**
	 * 走棋(落子)
	 * @param row 落子的行
	 * @param col 落子的列
	 * @param isBlack 是否为黑棋
	 * @return 落子成功返回true否则返回false
	 */
	public boolean move(int row, int col, boolean isBlack) {
		if(b[row][col] == 0) {
			b[row][col] = isBlack ? 1 : 2;
			return true;
		}
		return false;
	}
	
	/**
	 * 判断胜负
	 * @return 有任意一方获胜返回true, 否则返回false
	 */
	public boolean judge(int row, int col, boolean isBlack) {
		int currentColor = isBlack ? 1 : 2;
		return countV(row, col, currentColor) >= 5 || countH(row, col, currentColor) >= 5 ||
				countX1(row, col, currentColor) >= 5 || countX2(row, col, currentColor) >= 5;
	}
	
	// 计算垂直方向连续同色棋子的数量
	private int countV(int row, int col, int currentColor) {
		int counter = 1;
		
		int tempRow = row;
		while(tempRow - 1 >= 0 && b[tempRow - 1][col] == currentColor) {
			tempRow -= 1;
			counter++;
		}
		
		tempRow = row;
		while(tempRow + 1 < b.length && b[tempRow + 1][col] == currentColor) {
			tempRow += 1;
			counter++;
		}
		
		return counter;
	}
	
	// 计算水平方向连续同色棋子的数量
	private int countH(int row, int col, int currentColor) {
		int counter = 1;
		
		int tempCol = col;
		while(tempCol - 1 >= 0 && b[row][tempCol - 1] == currentColor) {
			tempCol -= 1;
			counter++;
		}
		
		tempCol = col;
		while(tempCol + 1 < b.length && b[row][tempCol + 1] == currentColor) {
			tempCol += 1;
			counter++;
		}
		
		return counter;
	}
	
	// 计算反对角线方向连续同色棋子的数量
	private int countX1(int row, int col, int currentColor) {
		int counter = 1;
		
		int tempRow = row;
		int tempCol = col;
		while(tempRow - 1 >= 0 && tempCol - 1 >= 0 && b[tempRow - 1][tempCol - 1] == currentColor) {
			tempRow -= 1;
			tempCol -= 1;
			counter++;
		}
		
		tempRow = row;
		tempCol = col;
		while(tempRow + 1 < b.length && tempCol + 1 < b.length && b[tempRow + 1][tempCol + 1] == currentColor) {
			tempRow += 1;
			tempCol += 1;
			counter++;
		}
		
		return counter;
	}
	
	// 计算正对角线方向连续同色棋子的数量
	private int countX2(int row, int col, int currentColor) {
		int counter = 1;
		
		int tempRow = row;
		int tempCol = col;
		while(tempRow - 1 >= 0 && tempCol + 1 < b.length && b[tempRow - 1][tempCol + 1] == currentColor) {
			tempRow -= 1;
			tempCol += 1;
			counter++;
		}
		
		tempRow = row;
		tempCol = col;
		while(tempRow + 1 < b.length && tempCol - 1 >= 0 && b[tempRow + 1][tempCol - 1] == currentColor) {
			tempRow += 1;
			tempCol -= 1;
			counter++;
		}
			
		return counter;
	}
	
	public void reset() {
		for(int i = 0; i < b.length; i++) {
			for(int j = 0; j < b[i].length; j++) {
				b[i][j] = 0;
			}
		}
	}

//	public void makeAMove() {
//		int row = (int) (Math.random() * 15);
//		int col = (int) (Math.random() * 15);
//		if (b[row][col] == 0) {
//			b[row][col] = blackTurn ? 1 : 2;
//			blackTurn = !blackTurn; // 交换走棋方
//		}
//	}

}
package com.lovo;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

@SuppressWarnings("serial")
public class GameFrame extends JFrame {
	private GameServer server = null;
	private GameClient client = null;
	
	private Board board = new Board(); // 创建棋盘类的对象;
	private Image offImage = new BufferedImage(800, 800,
			BufferedImage.TYPE_INT_RGB);
	
	private boolean isMyTurn = true;	// 是否轮到黑方走棋(true-黑方,false-白方)
	private boolean isGameOver = false;
	private boolean isBlack = true;
	private boolean isGameServerOn = false;

	public GameFrame() {
		this.setTitle("五子棋");
		this.setSize(800, 800);
		this.setResizable(false);
		this.setLocationRelativeTo(null);
		this.getContentPane().setBackground(new Color(0xCF9D0A));
		
		this.addWindowListener(new WindowAdapter() {
			
			@Override
			public void windowClosing(java.awt.event.WindowEvent e) {
				if(server != null) {
					server.close();
				}
				if(client != null) {
					client.close();
				}
				System.exit(0);
			}
		});

		this.addMouseListener(new MouseAdapter() {

			@Override
			public void mousePressed(MouseEvent e) {
				if(isMyTurn && !isGameOver && isGameServerOn) {
					int x = e.getX();
					int y = e.getY();
					if(x >= 50 && x <= 750 && y >= 50 && y <= 750) {
						int row = Math.round((y - 50) / 50.0F);
						int col = Math.round((x - 50) / 50.0F);
						if(board.move(row, col, isBlack)) {
							repaint();
							if(server != null) {
								try {
									server.sendMove(row, col, isBlack);
									new Thread(new Runnable() {

										@Override
										public void run() {
											try {
												MoveInfo mi = server.receiveMove();
												board.move(mi.getRow(), mi.getCol(), mi.isBlack());
												if(board.judge(mi.getRow(), mi.getCol(), mi.isBlack())) {
													isGameOver = true;
													isMyTurn = false;
												}
												else {
													isMyTurn = true;
												}
												repaint();
											}
											catch (IOException e) {
												e.printStackTrace();
											}
										}
									}).start();
								}
								catch (IOException ex) {
									ex.printStackTrace();
								}
							}
							else if(client != null) {
								try {
									client.sendMove(row, col, isBlack);
									new Thread(new Runnable() {
										
										@Override
										public void run() {
											try {
												MoveInfo mi = client.receiveMove();
												board.move(mi.getRow(), mi.getCol(), mi.isBlack());
												if(board.judge(mi.getRow(), mi.getCol(), mi.isBlack())) {
													isGameOver = true;
													isMyTurn = true;
												}
												else {
													isMyTurn = true;
												}
												repaint();
											}
											catch (IOException e) {
												// TODO Auto-generated catch block
												e.printStackTrace();
											}	
										}
									}).start();
								}
								catch (IOException ex) {
									ex.printStackTrace();
								}
							}
							if(board.judge(row, col, isMyTurn)) {
								isGameOver = true;
							}
							else {
								isMyTurn = !isMyTurn;
							}
						}
					}
				}
			}

		});
		
		this.addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				if(isGameOver && e.getKeyCode() == KeyEvent.VK_F2) {
					resetGame();
					repaint();
				}
				else if(!isGameServerOn && e.getKeyCode() == KeyEvent.VK_F3) {
					server = new GameServer();
					new Thread(new Runnable() {
						@Override
						public void run() {
							try {
								server.start();
								isGameServerOn = true;	// 主机启动成功
								isMyTurn = true;		// 轮到自己走棋
								isBlack = true;
							}
							catch (Exception ex) {
								JOptionPane.showMessageDialog(null, "建立主机失败!!!", "错误", JOptionPane.ERROR_MESSAGE);
							}
						}
					}).start();
					
				}
				else if(!isGameServerOn && e.getKeyCode() == KeyEvent.VK_F4) {
					String ip = JOptionPane.showInputDialog("请输入要连接的主机(IP地址或机器名): ");
					client = new GameClient();
					try {
						client.start(ip);
						isGameServerOn = true;
						isMyTurn = false;
						isBlack = false;
						new Thread(
							new Runnable() {
								@Override
								public void run() {
									try {
										MoveInfo mi = client.receiveMove();
										board.move(mi.getRow(), mi.getCol(), mi.isBlack());
										isMyTurn = true;
										repaint();
									}
									catch (IOException e) {
										e.printStackTrace();
									}
								}
							}
						).start();
					}
					catch (Exception ex) {
						JOptionPane.showMessageDialog(null, "连接主机失败!!!", "错误", JOptionPane.ERROR_MESSAGE);
					}
				}
			}
			
			// 重置游戏
			private void resetGame() {
				board.reset();
				isMyTurn = true;
				isGameOver = false;
			}
			
		});
	}

	@Override
	public void paint(Graphics g) { 	// 重写此方法的目的是在窗口上绘制自己想要的东西
		Graphics newG = offImage.getGraphics();
		super.paint(newG); 				// 消除窗口残影
		board.draw(newG); 				// 棋盘对象调用draw方法
		if(isGameOver) {
			newG.setColor(isMyTurn ? Color.BLACK : Color.WHITE);
			newG.setFont(new Font("微软雅黑", Font.PLAIN, 72));
			newG.drawString(isMyTurn? "黑棋胜" : "白棋胜", 293, 150);
		}
		g.drawImage(offImage, 0, 0, 800, 800, null);	// 将内存中的图直接绘制到窗口上
		
	}

}

package com.lovo;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class GameServer {
	private ServerSocket server;
	private Socket client;
	
	private InputStream in;
	private OutputStream out;
	
	private boolean connected;

	public void start() throws Exception {
		server = new ServerSocket(5566);
		client = server.accept();
		in = client.getInputStream();
		out = client.getOutputStream();
		connected = true;
	}
	
	public void sendMove(int row, int col, boolean isBlack) throws IOException {
		DataOutputStream dout = new DataOutputStream(out);
		dout.writeInt(row);
		dout.writeInt(col);
		dout.writeBoolean(isBlack);
	}
	
	public MoveInfo receiveMove() throws IOException {
		MoveInfo mi = new MoveInfo();
		DataInputStream din = new DataInputStream(in);
		mi.setRow(din.readInt());
		mi.setCol(din.readInt());
		mi.setBlack(din.readBoolean());
		return mi;
	}
	
	public void close() {
		if(client != null) {
			try {
				client.close();
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(server != null) {
			try {
				server.close();
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public boolean isConnected() {
		return connected;
	}
	
}

package com.lovo;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class GameClient {
	private Socket client;
	private InputStream in;
	private OutputStream out;
	
	public void start(String ip) throws Exception {
		client = new Socket(ip, 5566);
		in = client.getInputStream();
		out = client.getOutputStream();
	}
	
	public void sendMove(int row, int col, boolean isBlack) throws IOException {
		DataOutputStream dout = new DataOutputStream(out);
		dout.writeInt(row);
		dout.writeInt(col);
		dout.writeBoolean(isBlack);
	}
	
	public MoveInfo receiveMove() throws IOException {
		MoveInfo mi = new MoveInfo();
		DataInputStream din = new DataInputStream(in);
		mi.setRow(din.readInt());
		mi.setCol(din.readInt());
		mi.setBlack(din.readBoolean());
		return mi;
	}
	
	public void close() {
		if(client != null) {
			try {
				client.close();
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

package com.lovo;

public class MoveInfo {
	private int row;
	private int col;
	private boolean isBlack;

	public int getRow() {
		return row;
	}

	public void setRow(int row) {
		this.row = row;
	}

	public int getCol() {
		return col;
	}

	public void setCol(int col) {
		this.col = col;
	}

	public boolean isBlack() {
		return isBlack;
	}

	public void setBlack(boolean isBlack) {
		this.isBlack = isBlack;
	}

}

package com.lovo;

public class GameRunner {
	public static void main(String[] args) {
		new GameFrame().setVisible(true);
	}

}


评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值