Java网络象棋游戏(功能版)

本文介绍了一个Java网络象棋游戏的棋谱功能实现,包括棋谱的保存和演示。通过IO流将棋子移动信息保存到文件中,并提供自动、手动演示棋谱的功能。

网络象棋目录

客户端

走棋

悔棋

认输

保存棋谱

演示棋谱(自动、手动)

服务器端

与客户端相同

象棋界面图片:
在这里插入图片描述
棋谱演示界面:
在这里插入图片描述

网络象棋游戏中基本的走棋、认输、悔棋功能,都是参考其他博主代码,在这里只写象棋的拓展——棋谱的制作和演示。

扩展一个棋谱功能,可以在列表中在增加一个棋谱类,然后在服务器端/客户端类中引用。因为博主在引用过程中不断报错,所以放弃了创建新的棋谱类,而是直接在服务器类中加入代码。

把棋子移动信息保存到Node类的动态数组ArrayList中,使用IO流把ArrayList里的棋子信息保存到文件中。注意,ArrayList中保存到信息是Node类,保存到文件前要先把数据分割。在Node类中使用get、set方法,方便别的类获取对应的信息,然后再使用append()方法一个一个添加信息,就可以把信息保存到文件中了。

服务器端类代码

package ChineseChessServer;

import java.awt.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;

import javax.swing.*;

import java.util.ArrayList;
import java.util.LinkedList;

public class GameServer extends JFrame implements ActionListener,Runnable{

	static ChessBoard gamePanel = new ChessBoard();
	static Chess[] chess = new Chess[32];
	static int[][] map = new int[10][9];
	public short LocalPlayer;
	static JButton buttonStart = new JButton("开始");
	static JButton buttonGiveIn = new JButton("认输");
	JButton buttonAskRegret = new JButton("请求悔棋");
	JTextField textIp = new JTextField("127.0.0.1");//IP
	JTextField textPort = new JTextField("3003");//对方端口
	public static final short REDPLAYER = 1;
	public static final short BLACKPLAYER = 0;
	JPanel panelBottom;
	JMenuBar bar;
	JMenu fileMenu;
	JMenuItem 保存棋谱,演示棋谱;
	JFileChooser fileChooser = null;
	Container con = null;
	JPanel panel2;
	//private boolean pause = false;
	
	public JButton replay = null,next = null,auto = null,stop = null;
	static BufferedReader bRead = null;
	
	static BufferedReader br;
	String str;
	ArrayList<int[]> list = new ArrayList<int[]>();
	static String [] arr;
	static int[] dArr;
	static int [][] array;
	
	Thread 自动演示 = null;//AutoPlay
	int index=-1;
	
	JTextArea text;
	JTextField 时间间隔 = null;//TInterval
	
	int time = 1000;
	String 演示过程="";
	JPanel panel1;
	
	public GameServer(){
		  panelBottom = new JPanel(new FlowLayout());
		 panelBottom.setPreferredSize(new Dimension(200,700));
		 panelBottom.setBorder(BorderFactory.createLoweredBevelBorder());
		 buttonStart.setPreferredSize(new Dimension(150,45));
		 buttonGiveIn.setPreferredSize(new Dimension(150,45));
		 buttonAskRegret.setPreferredSize(new Dimension(150,45));
		bar = new JMenuBar();
		fileMenu = new JMenu("中国象棋棋谱");
		fileMenu.setPreferredSize(new Dimension(150,45));
		保存棋谱 = new JMenuItem("保存棋谱");
		演示棋谱 = new JMenuItem("演示棋谱");
		fileMenu.add(保存棋谱);
		fileMenu.add(演示棋谱);
		bar.add(fileMenu);
		//list = gamePanel.list;
		
		replay = new JButton("重新演示");
		next = new JButton("下一步");
		auto = new JButton("自动演示");
		stop = new JButton("暂停演示");
		
		自动演示 = new Thread(this);
		
		replay.addActionListener(this);
		next.addActionListener(this);
		auto.addActionListener(this);
		stop.addActionListener(this);
		
		replay.setEnabled(false);
		next.setEnabled(false);
		auto.setEnabled(false);
		stop.setEnabled(false);
		
		text = new JTextArea();
		时间间隔 = new JTextField("1");
		JScrollPane pane = new JScrollPane(text);
		JPanel p = new JPanel(new GridLayout(3,2));
		p.add(replay);
		p.add(next);
		p.add(auto);
		p.add(stop);
		p.add(new JLabel("时间间隔(秒)",SwingConstants.CENTER));
		p.add(时间间隔);
		
		panel1 = new JPanel(new FlowLayout());
		panel1.setPreferredSize(new Dimension(200,300));
		pane.setPreferredSize(new Dimension(190,200));
		
		panelBottom.setBorder(BorderFactory.createLoweredBevelBorder());
		
		panel1.add(pane);
		panel1.add(p);
		//setJMenuBar(bar); 
		 
		 panelBottom.add(buttonStart);
		 panelBottom.add(buttonGiveIn);
		 panelBottom.add(buttonAskRegret);
		 panelBottom.add(new JLabel("输入对方IP:"));
		 panelBottom.add(textIp);
		 panelBottom.add(new JLabel("输入对方端口:"));
		 panelBottom.add(textPort);
		 panelBottom.add(bar);
		 panelBottom.add(panel1);
		 
		 保存棋谱.addActionListener(this);
		 演示棋谱.addActionListener(this);
		 
		 this.LocalPlayer = gamePanel.LocalPlayer;
		 
		 this.getContentPane().setLayout(new BorderLayout());
		 this.getContentPane().add(gamePanel,BorderLayout.CENTER);
		 this.getContentPane().add(panelBottom,BorderLayout.EAST);
		 this.setSize(900,700);//610,730
		 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		 this.setTitle("中国象棋服务器");
		 this.setVisible(true);
		 buttonGiveIn.setEnabled(false);
		 buttonAskRegret.setEnabled(false);
		 buttonStart.setEnabled(true);
		 setVisible(true);
		 this.addWindowListener(new WindowAdapter() {//窗口关闭事件
			 public void windowClosing(WindowEvent e){
				 try{
					 gamePanel.send("quit|");
					 System.exit(0);
				 }catch(Exception ex){
					 ex.printStackTrace();
				 }
			 }
		});
		 		 
		 buttonGiveIn.addMouseListener(new MouseAdapter() {//认输事件
			
			public void mouseClicked(MouseEvent e){
				 try{
					 gamePanel.send("lose|");//发送认输信息
				 }catch(Exception ex){
					 ex.printStackTrace();
				 }
			 }
		});
		 
		buttonAskRegret.addMouseListener(new MouseAdapter() {
			 public void mouseClicked(MouseEvent e){
				 if(gamePanel.list.size()==0){
					 JOptionPane.showMessageDialog(null, "不能悔棋");
					 return ;
				 }
				 
				 if(gamePanel.list.size()==1){
					int flag = gamePanel.LocalPlayer==REDPLAYER?REDPLAYER:BLACKPLAYER;
					if(flag==REDPLAYER){//如果我是红方,判断上一步是不是对方下的,如果是,不能悔棋
						if(gamePanel.list.get(0).index<16){
							 JOptionPane.showMessageDialog(null, "不能悔棋");
							 return ;
						}
					}else{
						if(gamePanel.list.get(0).index>=16){
							 JOptionPane.showMessageDialog(null, "不能悔棋");
							 return ;
						}
					}
					
				 }
				 
				 gamePanel.send("ask|");//发送请求悔棋请求
				 
			 }
		});
		

		 
		 buttonStart.addMouseListener(new MouseAdapter() {
			 public void mouseClicked(MouseEvent e){
				 String ip = textIp.getText();
				 int otherPort = Integer.parseInt(textPort.getText());
				 int receivePort;
				 if(otherPort == 3003){
					 receivePort = 3004;                            
				 }else{
					 receivePort = 3003;
				 }
				 gamePanel.startJoin(ip, otherPort, receivePort);
				 buttonGiveIn.setEnabled(true);
				 buttonAskRegret.setEnabled(true);
				 buttonStart.setEnabled(false);
			 }
		});
		 
		 
	}
	
	public static void getFile() throws Exception
	{
		File file = new File("棋谱2.txt");
		if(!file.exists()) throw new RuntimeException("No File!");
		br = new BufferedReader(new FileReader(file));
		String str;
		ArrayList<int[]> list = new ArrayList<int[]>();
		while((str=br.readLine())!=null)
		{
			int s = 0;
			arr = str.split(",");
			dArr = new int[arr.length];
			for(String ss : arr)
			{
				if(ss!=null){dArr[s++] = Integer.parseInt(ss);}
			}
			list.add(dArr);
		}
		
		int max=0;
		for(int i = 0;i<list.size();i++)
		{
			if(max<list.get(i).length)
				max = list.get(i).length;
		}
		
		array = new int[list.size()][max];
		
		for(int i=0;i< array.length;i++)
		{
			for(int j=0;j<list.get(i).length;j++)
			{
				array[i][j] = list.get(i)[j];
			}
		}
	}
	
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource()==保存棋谱){
		 try {
			BufferedWriter bw = new BufferedWriter(new FileWriter("棋谱2.txt"));
			for(int i=0;i<gamePanel.list.size();i++){
				Node s = gamePanel.list.get(i);
				StringBuilder nd = new StringBuilder();
				nd.append(s.getIndex()).append(",").append(s.getX()).append(",").append(s.getY()).append(",").append(s.getOldX()).append(",").append(s.getOldY()).append(",").append(s.getEatChessIndex());
				
				bw.write(nd.toString());
				bw.newLine();
				bw.flush();
				
				JOptionPane.showConfirmDialog(null, "棋谱保存成功","提示",JOptionPane.DEFAULT_OPTION);
			
		} bw.close();
		 
		}catch (IOException e1) {e1.printStackTrace();}
	}
		
		if(e.getSource()==演示棋谱)
		{
			this.LocalPlayer = gamePanel.LocalPlayer;
			gamePanel.startNewGame(LocalPlayer);
			try {
				getFile();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			replay.setEnabled(true);
			next.setEnabled(true);
			auto.setEnabled(true);
			stop.setEnabled(true);
			JOptionPane.showConfirmDialog(null, "你可以开始演示了","提示",JOptionPane.DEFAULT_OPTION);
			
		}
		
		if(e.getSource()==next)
		{
			index++;
			if(index<array.length)
			{
				演示一步(index);
			}
			else
			{
				演示结束("棋谱演示完毕");
				next.setEnabled(false);
				index = -1;
			}
		}
		
		if(e.getSource()==replay)
		{
			gamePanel.startNewGame(LocalPlayer);
			System.out.println("可以重新演示");
			next.setEnabled(true);
			text.setText("");
			index = -1;
			
		}
		
		if(e.getSource()==auto)
		{
			next.setEnabled(false);
			replay.setEnabled(false);
			
			try
			{
				time = 1000*Integer.parseInt(时间间隔.getText().trim());
			}catch(NumberFormatException ee)
			{time = 1000;}
			
			if(!(自动演示.isAlive()))  //自动演示中断
			{
				自动演示 = new Thread(this);
			    text.setText(null);
				自动演示.start();
			}
		}
		
		if(e.getSource()==stop)
		{
			if(e.getActionCommand().equals("暂停演示"))
			{
				演示过程 = "暂停演示";
				stop.setText("继续演示");
				stop.repaint();
			}
			
			if(e.getActionCommand().equals("继续演示"))
			{
				演示过程 = "继续演示";
				自动演示.interrupt();
				stop.setText("暂停演示");
				stop.repaint();
			}

		}
		
	}
	
	@Override
	public void run() {
		for(index = 0;index < array.length;index++)
		{
			try
			{
				Thread.sleep(time);
			}
			catch(InterruptedException e)
			{}
			
			while(演示过程.equals("暂停演示"))
			{
				synchronized(自动演示)
				{
					try
					{
						自动演示.wait();
					}
					catch(InterruptedException e)
					{自动演示.notify();}
				}
			}
			演示一步(index);
		}
		
		if(index>=array.length)
		{
			演示结束("棋谱演示结束");
			next.setEnabled(true);
			replay.setEnabled(true);
		}
	}
	
	public void 演示一步(int index)
	{
		map = gamePanel.map;
		chess = gamePanel.chess;
		String player,typename,m,eatChess;
		int Nindex=0;
		int x=0;
		int y=0;
		int OldX=0;
		int OldY=0;
		int eatchessindex = 0;
		
		for(int i=index;i<=index;i++)
		{
			Nindex = array[i][0];
			x = array[i][1];
			y = array[i][2];
			OldX = array[i][3];
			OldY = array[i][4];
			eatchessindex = array[i][5];
		}
		
		if(chess[Nindex].player==1)
		{
			player = "红方";
		}else{player = "黑方";}
		typename = chess[Nindex].typeName;
		
		if(eatchessindex==-1)
		{
			map[OldX][OldY] = -1;
			map[x][y] = Nindex;
			chess[Nindex].setPos(x, y);
			gamePanel.repaint();
			m = player +" " + typename + ":" +"从" + "(" + OldX + "," + OldY + ")" +"到" + "(" + x + "," + y + ")"+"没有吃子";
		}
		else
		{			
			map[OldX][OldY]=-1;
			map[x][y] = Nindex;
			eatChess = chess[eatchessindex].typeName;
			chess[Nindex].setPos(x, y);
			chess[eatchessindex]=null;
			gamePanel.repaint();
			m = player +" " + typename + ":" +"从" + "(" + OldX + "," + OldY + ")" +"到" + "(" + x + "," + y + ")"+"吃了"+eatChess;
		    if(eatchessindex==0||eatchessindex==16)
		    {
		    	m= player +" " + typename + ":" +"从" + "(" + OldX + "," + OldY + ")" +"到" + "(" + x + "," + y + ")"+"吃了"+eatChess + "\n" + "棋谱演示结束";
		    }
		}
		
		text.append(m);
		text.append("\n");
	}
	
	public void 演示结束(String message)
	{
		gamePanel.startNewGame(LocalPlayer);
		index=-1;
		System.out.println(message);
		
	}
	
	public static void main(String[] args) {
		new GameServer();
	}

}

Node部分代码

	public int getIndex(){
		return index;
	}
	
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
	
	public int getOldX(){
		return oldX;
	}
	public int getOldY(){
		return oldY;
	}
	public int getEatChessIndex(){
		return eatChessIndex;
	}

博主参考了很多网络象棋的游戏,最后在原有的代码上扩展了一下棋谱。博主使用的是IO流,存在一个Bug:文件里只能保存当前棋局的棋谱,一旦新开棋谱,再次保存。新的棋谱会覆盖之前的棋谱。所以,这个地方其他小伙伴想改进的话,可以使用数据库,或者保存时可以弹出文件保存的框,就能自由的保存很多棋谱文件。(博主失败了,大家要是有成功可以分享分享)

博主代码中没有写出走棋、悔棋、认输、联机的部分,因为博主也是参考别的博主写的。(写的真的好)
参考的是:墨染秦月 的Java游戏开发——中国象棋联机版

链接: Java游戏开发——中国象棋联机版.

棋谱部分,参考的是 民族疯 的 JAVA实践(一)————中国象棋打谱系统
链接: JAVA实践(一)————中国象棋打谱系统.

大家有什么问题可以留言。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余华细雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值