最近学习了Java的多线程和网络编程后,利用相关知识写了一个简单的联网版五子棋小游戏,客户端和服务器就是两个玩家,实现了下棋、判断输赢和聊天的功能。
具体代码如下:
public class clientChess {
private static myFrame frame=null;
public clientChess(myFrame frame) {
this.frame=frame;
}
public void start() throws Exception{
Socket client=new Socket("192.168.43.102",10000);
final PrintWriter writer=new PrintWriter(client.getOutputStream(),true);
java.io.InputStream in=client.getInputStream();
new clientThread(client,frame).start();
//没分出胜负时,需要向服务器传棋子的坐标
Scanner sc=new Scanner(System.in);
new Thread(new Runnable() {
String line;
@Override
public void run() {
while((line=sc.nextLine())!=null) {
//frame.text.setText("我:"+line);
frame.text.append("我:"+line+"\r\n");
writer.println("chat:"+line);
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
while(!frame.isWin()) {
if(frame.backChess) {
writer.println("back:"+frame.getRow()+":"+frame.getCol());
}else {
writer.println(frame.getRow()+","+frame.getCol());
}
frame.backChess=false;
}
writer.println("win:"+frame.isWin());
}
}).start();
}
public static void main(String[] args) throws Exception {
myFrame frame=new myFrame();
clientChess client=new clientChess(frame);
client.start();
}
}
客户端线程,主要用来接收服务器发来的消息,并做出处理
class clientThread extends Thread{
Socket socket=null;
myFrame frame=null;
java.io.InputStream stream=null;
BufferedReader reader=null;
PrintWriter writer = null;
public clientThread(Socket socket,myFrame frame) {
this.socket=socket;
this.frame=frame;
try {
this.stream=this.socket.getInputStream();
this.reader=new BufferedReader(new InputStreamReader(stream));
this.writer=new PrintWriter(this.socket.getOutputStream(),true);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String line=null;
try {
while((line=this.reader.readLine())!=null) {
if(line.contains("ok")){
myFrame.occupy=false;
}
if(line.contains(",")) {
String[] data=line.split(",");
int row=Integer.parseInt(data[0]);
int col=Integer.parseInt(data[1]);
if(frame.chess[row][col]==0){
writer.println("ok");
frame.chess[row][col]=2;
frame.repaint();
//writer.println(frame.getRow()+","+frame.getCol());
}
}
if(line.contains("win:")) {
//System.out.println("你输了");
JOptionPane.showMessageDialog(null, "你输了");
frame.repaint();
}
if(line.contains("chat:")) {
String[] data=line.split(":");
//frame.text.setText("对方:"+data[1]);
frame.text.append("对方:"+data[1]+"\r\n");
}
if(line.contains("back:")) {
System.out.println(line);
String[] data=line.split(":");
int row=Integer.parseInt(data[1]);
int col=Integer.parseInt(data[2]);
frame.chess[row][col]=0;
frame.repaint();
frame.setRow(Integer.parseInt(data[1]));
frame.setCol(Integer.parseInt(data[2]));
}
}
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端界面:
class myPanel extends JPanel{
public static int[][] board=new int[16][16];
public myPanel(int[][] board){
this.board=board;
}
public myPanel() {
}
@Override
public void paint(Graphics g) {
g.setColor(new Color(165,185,75));
g.fillRect(60, 60, 360, 360);
g.setColor(Color.black);
//绘制棋盘
for(int i=0;i<15;i++) {
g.drawLine(65, 65+i*25, 415, 65+i*25);
g.drawLine(65+i*25, 65, 65+i*25, 415);
}
//绘制棋子
for(int i=1;i0 && currentCol<14 && board[--currentRow][++currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
if(currentRow<14 && currentCol>0 && board[++currentRow][--currentCol]==v) {
counter++;
}
return counter>=5;
}
//判断从左上到右下
private boolean checkX1(int row, int col, boolean isBlack) {
int counter=1;
int currentRow=row;
int currentCol=col;
int v=isBlack?1:2;
while(currentRow>0 && currentCol>0 && board[--currentRow][--currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
while(currentRow<14 && currentCol<14 && board[++currentRow][++currentCol]==v) {
counter++;
}
return counter>=5;
}
//判断竖着方向是否连成5颗棋子
private boolean checkV(int row, int col, boolean isBlack) {
int counter=1;
int currentRow=row;
int currentCol=col;
int v=isBlack?1:2;
while(currentRow>0 && board[--currentRow][currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
while(currentRow<14 && board[++currentRow][currentCol]==v) {
counter++;
}
return counter>=5;
}
private boolean checkH(int row, int col, boolean isBlack) {
int counter=1;
int currentRow=row;
int currentCol=col;
int v=isBlack?1:2;
while(currentCol>0 && board[currentRow][--currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
while(currentCol<14 && board[currentRow][++currentCol]==v) {
counter++;
}
return counter>=5;
}
}
public class myFrame extends JFrame{
public static int[][] chess=new int[16][16];
private volatile boolean isBlack = true;// 是否轮到黑棋
public static boolean occupy=false;
private boolean isWin = false;// 是否获得胜利
private boolean isStart = false;// 是否联机成功开始游戏
public static boolean backChess=false;
private int row=0;
private int col=0;
public static JTextArea text;
public boolean isWin() {
return isWin;
}
public void setWin(boolean isWin) {
this.isWin = isWin;
}
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 myFrame() {
this.setName("联机版五子棋");
this.setBounds(100, 100, 500, 580);
this.setLayout(null);
JButton start=new JButton("开始");
start.setBounds(10, 10, 60, 25);
this.add(start);
//开始按钮
JButton back=new JButton("悔棋");
back.setBounds(80, 10, 60, 25);;
this.add(back);
text=new JTextArea();
JScrollPane pane=new JScrollPane(text);
pane.setBounds(60, 430, 360, 100);
this.add(pane);
JButton end=new JButton("退出");
end.setBounds(150, 10, 60, 25);
this.add(end);
end.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
final myPanel panel=new myPanel(chess);
panel.setBounds(0, 0, 500, 500);
this.add(panel);
//JTextField innfo=new
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if(isStart && !isWin() && !occupy ) {
int x=e.getX();
int y=e.getY();
if(x>=65 && x<=415 && y>=65 &&y<=415) {
setRow(Math.round((y-65)/25f));
setCol(Math.round((x-65)/25f));
//System.out.println(getRow()+","+getCol());
repaint();
if(panel.addPiece(getRow(), getCol(), isBlack)) {
setWin(panel.isWin(getRow(), getCol(), isBlack));
if(!isWin()) {
}else {
JOptionPane.showMessageDialog(null, "你赢了。。。。");
setWin(true);
repaint();
}
}
}
}
}
});
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
isStart=true;
}
});
//悔棋按钮监听事件
back.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(getRow()+","+getCol());
chess[getRow()][getCol()]=0;
backChess=true;
// backChess=panel.reducePiece(getRow(), getCol());
repaint();
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
服务器端:
public class serverChess extends JFrame{
public static myFrame2 frame=null;
public serverChess(myFrame2 frame) {
this.frame=frame;
}
public void start() throws Exception{
ServerSocket server=new ServerSocket(10000);
System.out.println("服务器端启动");
while(true){
Socket socket=server.accept();
final PrintWriter writer=new PrintWriter(socket.getOutputStream(),true);
Scanner sc=new Scanner(System.in);
new Thread(new Runnable() {
String line;
@Override
public void run() {
while((line=sc.nextLine())!=null) {
//frame.text.setText("我:"+line);
frame.text.append("我:"+line+"\r\n");
writer.println("chat:"+line);
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
while(!frame.isWin()) {
writer.println(frame.getRow()+","+frame.getCol());
if(frame.backChess) {
writer.println("back:"+frame.getRow()+":"+frame.getCol());
}
}
writer.println("win:"+frame.isWin());
}
}).start();
new serverThread(socket,frame).start();
}
}
public static void main(String[] args) throws Exception {
myFrame2 frame=new myFrame2();
serverChess server=new serverChess(frame);
server.start();
}
}
服务器线程,接收客户端的消息并做出处理
class serverThread extends Thread{
private Socket socket=null;
private myFrame2 frame=null;
public serverThread(Socket socket,myFrame2 frame2){
this.socket=socket;
this.frame=frame2;
}
@Override
public void run() {
BufferedReader reader = null;
PrintWriter writer = null;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new PrintWriter(socket.getOutputStream(),true);
String line =reader.readLine();
while((line=reader.readLine()) != null) {
if(line.contains("ok")){
myFrame2.occupy=false;
}
if(line.contains(",")) {
String[] data=line.split(",");
int row=Integer.parseInt(data[0]);
int col=Integer.parseInt(data[1]);
if(frame.chess[row][col]==0){
writer.println("ok");
frame.chess[row][col]=1;
frame.repaint();
//writer.println(frame.getRow()+","+frame.getCol());
}
}
if(line.contains("win:")) {
//System.out.println("你输了");
JOptionPane.showMessageDialog(null, "你输了");
frame.setWin(true);
frame.repaint();
}
if(line.contains("chat:")) {
String[] data=line.split(":");
//frame.text.setText("对方:"+data[1]);
frame.text.append("对方:"+data[1]+"\r\n");
}
if(line.contains("back:")) {
System.out.println(line);
// String[] data=line.split(“:”);
// int row=Integer.parseInt(data[1]);
// int col=Integer.parseInt(data[2]);
// frame.chess[row][col]=0;
// frame.repaint();
// frame.setRow(Integer.parseInt(data[1]));
// frame.setCol(Integer.parseInt(data[2]));
// System.out.println(frame.getRow()+”,”+frame.getCol());
// frame.chess[row][col]=1;
}
}
this.socket.close(); // 连接关闭,所有的流都会随之关闭
} catch (Exception e) {
e.printStackTrace();
}
}
}
class serverPanel extends JPanel{
public static int[][] board=new int[16][16];
public serverPanel(int[][] board){
this.board=board;
}
@Override
public void paint(Graphics g) {
g.setColor(new Color(165,185,75));
g.fillRect(60, 60, 360, 360);
g.setColor(Color.black);
//绘制棋盘
for(int i=0;i<15;i++) {
g.drawLine(65, 65+i*25, 415, 65+i*25);
g.drawLine(65+i*25, 65, 65+i*25, 415);
}
//绘制棋子
for(int i=1;i0 && currentCol<14 && board[--currentRow][++currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
if(currentRow<14 && currentCol>0 && board[++currentRow][--currentCol]==v) {
counter++;
}
return counter>=5;
}
//判断从左上到右下
private boolean checkX1(int row, int col, boolean isBlack) {
int counter=1;
int currentRow=row;
int currentCol=col;
int v=isBlack?1:2;
while(currentRow>0 && currentCol>0 && board[--currentRow][--currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
while(currentRow<14 && currentCol<14 && board[++currentRow][++currentCol]==v) {
counter++;
}
return counter>=5;
}
//判断竖着方向是否连成5颗棋子
private boolean checkV(int row, int col, boolean isBlack) {
int counter=1;
int currentRow=row;
int currentCol=col;
int v=isBlack?1:2;
while(currentRow>0 && board[--currentRow][currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
while(currentRow<14 && board[++currentRow][currentCol]==v) {
counter++;
}
return counter>=5;
}
private boolean checkH(int row, int col, boolean isBlack) {
int counter=1;
int currentRow=row;
int currentCol=col;
int v=isBlack?1:2;
while(currentCol>0 && board[currentRow][--currentCol]==v) {
counter++;
}
currentRow=row;
currentCol=col;
while(currentCol<14 && board[currentRow][++currentCol]==v) {
counter++;
}
return counter>=5;
}
}
服务器界面:
public class myFrame2 extends JFrame {
public static int[][] chess=new int[16][16];
private volatile boolean isBlack = false;// 是否轮到黑棋
public static boolean occupy=false;
private boolean isWin = false;// 是否获得胜利
private boolean isStart = false;// 是否联机成功
private int row=0;
private int col=0;
public static boolean backChess=false;
public JButton back;
final serverPanel panel;
public static JTextArea text;
public myFrame2() {
this.setName("联机版五子棋");
this.setBounds(100, 100, 500, 580);
this.setLayout(null);
JButton start=new JButton("开始");
start.setBounds(10, 10, 60, 25);
this.add(start);
//开始按钮
back=new JButton("悔棋");
back.setBounds(80, 10, 60, 25);;
this.add(back);
JButton end=new JButton("退出");
end.setBounds(150, 10, 60, 25);
this.add(end);
JButton oppoBack=new JButton("对方悔棋");
oppoBack.setBounds(230, 10, 120, 25);
this.add(oppoBack);
end.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
text=new JTextArea();
JScrollPane pane=new JScrollPane(text);
pane.setBounds(60, 430, 360, 100);
this.add(pane);
panel=new serverPanel(chess);
panel.setBounds(0, 0, 430, 500);
this.add(panel);
panel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if(isStart && !isWin() && !occupy ) {
int x=e.getX();
int y=e.getY();
if(x>=65 && x<=415 && y>=65 &&y<=415) {
setRow(Math.round((y-65)/25f));
setCol(Math.round((x-65)/25f));
//System.out.println(getRow()+","+getCol());
repaint();
if(panel.addPiece(getRow(), getCol(), isBlack)) {
setWin(panel.isWin(getRow(), getCol(), isBlack));
if(!isWin()) {
}else {
JOptionPane.showMessageDialog(null, "你赢了。。。。。");
setWin(true);
repaint();
}
}
}
}
}
});
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
isStart=true;
}
});
//悔棋按钮监听事件
back.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(getRow()+","+getCol());
chess[getRow()][getCol()]=0;
backChess=true;
repaint();
}
});
oppoBack.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
panel.reducePiece(getRow(), getCol());
repaint();
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public boolean isWin() {
return isWin;
}
public void setWin(boolean isWin) {
this.isWin = isWin;
}
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;
}
}
游戏截图: