package netWuZiQiDemo;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class NetLTWZQDemo extends JPanel implements MouseListener, Runnable {
int x;// 落子处棋盘坐标
int y;
int[][] chess = new int[12][12];// 棋盘大小为12x12
int ex;// 传送鼠标点击坐标
int ey;
boolean me = true;// 初始化为己方先落黑子
boolean one = true;// 控制联机双方每次只能一个人下子
static boolean start = false;// 默认打开游戏不能下子,需先选择游戏模式
static InetAddress inetAddress;// 客户端确认服务端的IP地址
static String UsernameOrIp;// 联机对方主机名或IP地址
// 客户端和服务端端口号一致则为单机版五子棋
static int clientPort;// 设置客户端端口
static int serverPort;// 设置服务端端口
static boolean danJi;// 选择单机模式,则程序只判断一次胜负,防止对局结束后无法落子,若联机模式,则判断两次胜负
static Thread t;// 声明一个线程
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
JFrame jFrame = new JFrame("五子棋");
jFrame.setBounds((Toolkit.getDefaultToolkit().getScreenSize().width - 655) / 2,
(Toolkit.getDefaultToolkit().getScreenSize().height - 675) / 2, 655, 675);// 窗口屏幕正中放置
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setResizable(false);//窗体大小固定
jFrame.setVisible(true);//窗体设置可见
NetLTWZQDemo netLTWZQDemo = new NetLTWZQDemo();
jFrame.add(netLTWZQDemo);
t = new Thread(netLTWZQDemo);
//为了方便(又懒又笨..),直接把所有内容写到一个类里,且把模式选择对话框放在main方法里
int respones = JOptionPane.showConfirmDialog(null, "是否联机?", "联机联机", JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if (respones == JOptionPane.YES_OPTION) {
try {
UsernameOrIp = JOptionPane.showInputDialog(null, "输入主机名或IP", "输入", JOptionPane.WARNING_MESSAGE)
.trim();
clientPort = Integer.parseInt(JOptionPane
.showInputDialog(null, "客户端端口?", "1024~65535", JOptionPane.WARNING_MESSAGE)
.trim());
serverPort = Integer.parseInt(JOptionPane
.showInputDialog(null, "服务端端口?", "1024~65535", JOptionPane.WARNING_MESSAGE)
.trim());
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "输错了,老铁从头再来吧!", "怜悯的眼神看着你", JOptionPane.ERROR_MESSAGE);
System.exit(0);
e.printStackTrace();
}
try {
inetAddress = InetAddress.getByName(UsernameOrIp);
} catch (UnknownHostException ex) {
ex.printStackTrace();
}
if (inetAddress != null) {
JOptionPane.showMessageDialog(null, "开始", "游戏开始", JOptionPane.WARNING_MESSAGE);
start = true;//设置游戏开始
if (clientPort == serverPort) {// 若主机名或IP为自己电脑(或不填写)且两个端口一样,则为单机模式
danJi = true;//开启单机模式
} else {
danJi = false;// 联机模式,设置单机模式为false
}
t.start();
}
}
if (respones == JOptionPane.NO_OPTION || respones == JOptionPane.CLOSED_OPTION) {
JOptionPane.showMessageDialog(null, "单机", "。。。", JOptionPane.INFORMATION_MESSAGE);
try {
inetAddress = InetAddress.getLocalHost();
serverPort = clientPort = 9653;// 默认端口号为9653
start = true;//设置游戏开始
danJi = true;// 开启单机模式
t.start();//开启线程开启游戏
} catch (UnknownHostException ex) {
JOptionPane.showMessageDialog(null, "本地网络出问题", "换台电脑", JOptionPane.ERROR_MESSAGE);
System.exit(0);
ex.printStackTrace();
}
}
}
@Override
public void run() {// 使用线程,端口号一致可进行单机游戏
clearChess();//游戏开启,重绘棋盘
receive();//开启服务端接收数据
}
public NetLTWZQDemo() {
setBackground(Color.gray);
addMouseListener(this);//注册鼠标事件
setVisible(true);//设置窗体可见
}
public void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;// 使用Graphics2D使构图平滑
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(g);
drawChessBoard(g);
drawChess(g);
}
public void drawChess(Graphics g) {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
if (chess[i][j] == 1) {
g.setColor(Color.black);
g.fillOval((i + 1) * 50 - 19, (j + 1) * 50 - 19, 38, 38);
} else if (chess[i][j] == 2) {
g.setColor(Color.white);
g.fillOval((i + 1) * 50 - 19, (j + 1) * 50 - 19, 38, 38);
} else if (chess[i][j] == 11) {// 点击落黑子时外加个黑框
g.setColor(Color.black);
g.fillOval((i + 1) * 50 - 19, (j + 1) * 50 - 19, 38, 38);
g.drawRect((i + 1) * 50 - 19, (j + 1) * 50 - 19, 38, 38);
} else if (chess[i][j] == 22) {// 点击落白子时棋子外加个白框
g.setColor(Color.white);
g.fillOval((i + 1) * 50 - 19, (j + 1) * 50 - 19, 38, 38);
g.drawRect((i + 1) * 50 - 19, (j + 1) * 50 - 19, 38, 38);
}
}
}
}
public void drawChessBoard(Graphics g) {
// 画棋盘
for (int i = 50; i <= 600; i += 50) {
g.setColor(Color.WHITE);
g.drawLine(i, 50, i, 600);
g.drawLine(50, i, 600, i);
}
}
public void clearChess() {// 初始化棋盘
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
chess[i][j] = 0;
}
}
me = true;// 初始化为己方落黑子
repaint();
}
//这个判断胜负的方法是抄的网上一段代码
void checkWiner() {// 判断胜方
int black_count = 0;
int white_count = 0;
for (int i = 0; i < 12; i++) {// 横向判断
for (int j = 0; j < 12; j++) {
if (chess[i][j] == 1 || chess[i][j] == 11) {
black_count++;
if (black_count == 5) {
JOptionPane.showMessageDialog(this, "黑棋胜利");
clearChess();
return;
}
} else {
black_count = 0;
}
if (chess[i][j] == 2 || chess[i][j] == 22) {