网络象棋目录
客户端
走棋
悔棋
认输
保存棋谱
演示棋谱(自动、手动)
服务器端
与客户端相同
象棋界面图片:

棋谱演示界面:

网络象棋游戏中基本的走棋、认输、悔棋功能,都是参考其他博主代码,在这里只写象棋的拓展——棋谱的制作和演示。
扩展一个棋谱功能,可以在列表中在增加一个棋谱类,然后在服务器端/客户端类中引用。因为博主在引用过程中不断报错,所以放弃了创建新的棋谱类,而是直接在服务器类中加入代码。
把棋子移动信息保存到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实践(一)————中国象棋打谱系统.
大家有什么问题可以留言。
本文介绍了一个Java网络象棋游戏的棋谱功能实现,包括棋谱的保存和演示。通过IO流将棋子移动信息保存到文件中,并提供自动、手动演示棋谱的功能。
1767

被折叠的 条评论
为什么被折叠?



