象棋的代码实现有点复杂,尤其是计算机的AI算法,在网上找了很多资料,费了好半天劲才弄明白其实现的原理,真的挺开阔思路的,很有意思!
思路:
1、创建主窗口,加载菜单及游戏面板。
2、在游戏面板中初始化各种参数,并建立各种功能组件。
3、利用标签图像做棋子,并结合paint()函数。
4、利用mouseMoved()鼠标移动函数设置落子指示器的位置。
5、利用mouseClicked()鼠标单击函数来判断是否可以下棋,由哪方来下,判断是否平局或胜利。如果是人机对战要计算电脑要下棋的最佳位置。
6、游戏结束,收尾,准备下一局。
图片位置与包位置平齐,因为我装载图片时是从类路径开始取,取绝对路径是不认可的。
本游戏用的是JDK1.8,编码UTF-8;
共有4个类,Chess.java是游戏入口类。GameFrame.java是主窗口类。GamePanel.java是游戏面板类。GameLogic.java是游戏逻辑类。先一口气把所有的代码贴上来再说。
1、Chess.java 游戏入口类
package com.game.chess;
/**
* 功能:中国象棋
* 作者:我是小木鱼(Lag)
*/
public class Chess
{
public static void main(String[] args)
{
new GameFrame();
}
}
2、GameFrame.java 主窗口类。
package com.game.chess;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
/**
* 功能:游戏窗口
* 作者:我是小木鱼(Lag)
*/
public class GameFrame extends JFrame implements ActionListener
{
private static final long serialVersionUID = -3812892829859080331L;
/** 游戏面板 */
private GamePanel gamePanel;
/**
* 功能:构造函数
*/
public GameFrame()
{
try
{
//菜单
JMenuBar jmb_gobang = new JMenuBar();
JMenu jm_game = new JMenu("游戏");
jm_game.setFont(new Font("微软雅黑",Font.PLAIN,12));
JMenuItem jmi_game_new = jm_game.add("新游戏");
jmi_game_new.setFont(new Font("微软雅黑",Font.PLAIN,12));
jmi_game_new.addActionListener(this);
jmi_game_new.setActionCommand("new");
JMenuItem jmi_game_undo = jm_game.add("悔棋");
jmi_game_undo.setFont(new Font("微软雅黑",Font.PLAIN,12));
jmi_game_undo.addActionListener(this);
jmi_game_undo.setActionCommand("undo");
JMenuItem jmi_surrender = jm_game.add("认输");
jmi_surrender.setFont(new Font("微软雅黑",Font.PLAIN,12));
jmi_surrender.addActionListener(this);
jmi_surrender.setActionCommand("surrender");
jm_game.addSeparator();
JMenuItem jmi_game_exit = jm_game.add("退出");
jmi_game_exit.setFont(new Font("微软雅黑",Font.PLAIN,12));
jmi_game_exit.addActionListener(this);
jmi_game_exit.setActionCommand("exit");
jmb_gobang.add(jm_game);
JMenu jm_help = new JMenu("帮助");
jm_help.setFont(new Font("微软雅黑",Font.PLAIN,12));
JMenuItem jmi_help_about = jm_help.add("关于");
jmi_help_about.setFont(new Font("微软雅黑",Font.PLAIN,12));
jmi_help_about.addActionListener(this);
jmi_help_about.setActionCommand("about");
jmb_gobang.add(jm_help);
this.setJMenuBar(jmb_gobang);
//面板
this.gamePanel = new GamePanel();
this.add(this.gamePanel);
//显示
this.setTitle("中国象棋");
this.setLayout(null);
this.setSize(666,620);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
catch(Exception e)
{
JOptionPane.showMessageDialog(this,"程序出现异常错误,即将退出!\r\n\r\n"+e.toString(),"提示",JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
}
/**
* 功能:事件监听
*/
@Override
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
if("new".equals(command))
{
this.gamePanel.newGame();
}
else if("undo".equals(command))
{
this.gamePanel.undo();
}
else if("surrender".equals(command))
{
this.gamePanel.surrender();
}
else if("exit".equals(command))
{
System.exit(0);
}
else if("about".equals(command))
{
JOptionPane.showMessageDialog(this,"我是小木鱼(Lag)","提示",JOptionPane.INFORMATION_MESSAGE);
}
}
}
3、GamePanel.java 游戏面板类
package com.game.chess;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.BorderFactory;
/**
* 功能:游戏面板
* 作者:我是小木鱼(Lag)
*/
public class GamePanel extends JPanel implements MouseListener,MouseMotionListener,ActionListener
{
private static final long serialVersionUID = 1353029267562430095L;
/** 游戏逻辑 */
private GameLogic gameLogic;
/** 网格行数 */
final int gridRows = 10;
/** 网格列数 */
final int gridColumns = 9;
/** 网格尺寸 */
final int gridSize = 52;
/** 网格宽度 */
final int gridsWidth = gridSize * (gridColumns - 1);
/** 网格高度 */
final int gridsHeight = gridSize * (gridRows - 1);
/** 网格左上角X坐标 */
final int gridsLeftX = 42;
/** 网格左上角Y坐标 */
final int gridsTopY = 42;
/** 象棋面板(要分层,否则棋盘标签压棋子标签) */
private JLayeredPane panelChess;
/** 棋盘标签 */
JLabel labelChessBorad;
/** 棋盘图片 */
private ImageIcon imageIconChessBoard;
/** 棋盘状态信息(-1->无棋,其他数字->棋子信息数组的下标) */
int[][] chessBoradState = new int[gridRows][gridColumns];
/** 棋子尺寸 */
final int chessSize = 44;
/** 棋子标签 */
JLabel[] labelChess = new JLabel[32];
/**
* 棋子信息数组
* index -> 棋子索引
* color -> 棋子颜色(0-黑棋,255-红棋)
* type -> 棋子类型(rook、horse、elephant、guard、king、cannon、soldier)
* name -> 棋子名字(黑车、黑马、黑象、黑士、黑将、黑炮、黑卒、红兵、红炮、红车、红马、红相、红仕、红帅)
* number -> 棋子小标号(如卒1卒2中的1与2)
* direction -> 棋子方向(T-上方,B-下方)
* oldOldRow -> 棋子大上次行位置
* oldOldColumn -> 棋子大上次列位置
* oldRow -> 棋子上次行位置
* oldColumn -> 棋子上次列位置
* newRow -> 棋子本次行位置
* newColumn -> 棋子本次列位置
* dead -> 棋子是否处于死亡状态(T-死亡,F-活着)
* oldEatIndex -> 上次被其吃棋子下标
* eatIndex -> 本次被其吃棋子下标
*/
@SuppressWarnings("unchecked") //数组不支持泛型
Map[] mapChess = new Map[32];
/** 棋子图片 */
private ImageIcon[] imageIconChess = new ImageIcon[14];
/** 红棋标识 */
final int REDCHESS = 255;
/** 黑棋标识 */
final int BLACKCHESS = 0;
/** 对战方式(0-人机对战,1-人人对战) */
int fightType ;
/** 先手选择(1-玩家先手,2-电脑先手) */
int playFirst ;
/** 红黑选择(255-玩家执红,0-玩家执黑) */
int chessColor ;
/** 电脑棋子颜色 */
int computerChess = -1 ;
/** 玩家棋子颜色 */
int playerChess = -1 ;
/** 红棋悔棋数 */
int redUndoNum = 30;
/** 黑棋悔棋数 */
int blackUndoNum = 30;
/** 全部下棋信息 */
List
4、GameLogic.java 游戏逻辑类。
package com.game.chess;
import java.util.Map;
import java.util.HashMap;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.event.MouseEvent;
/**
* 功能:游戏逻辑
* 作者:我是小木鱼(Lag)
*/
public class GameLogic
{
/** 游戏面板 */
GamePanel gamePanel;
/** 最大搜索深度 */
int Maxdepth = 2;
Map mapNextChess = new HashMap();
public GameLogic(GamePanel _gamePanel)
{
this.gamePanel = _gamePanel;
}
/**
* 功能:得到X像素所对应的列坐标
*/
private int getColumn(int x)
{
//先判断靠哪列近些
int column = (x - this.gamePanel.gridsLeftX + this.gamePanel.gridSize / 2) / this.gamePanel.gridSize;
//再判断是否在有效范围内
int posX = this.gamePanel.gridsLeftX + column * this.gamePanel.gridSize;
if(x > (posX - this.gamePanel.chessSize / 2) && x < (posX + this.gamePanel.chessSize / 2)){}
else
{
column = -1;
}
return column;
}
/**
* 功能:得到Y像素所对应的行坐标
*/
private int getRow(int y)
{
//先判断靠哪行近些
int row = (y - this.gamePanel.gridsTopY + this.gamePanel.gridSize / 2) / this.gamePanel.gridSize;
//再判断是否在有效范围内
int posY = this.gamePanel.gridsTopY + row * this.gamePanel.gridSize;
if(y > (posY - this.gamePanel.chessSize / 2) && y < (posY + this.gamePanel.chessSize / 2)){}
else
{
row = -1;
}
return row;
}
/**
* 功能:判断下一步是红棋下还是黑棋下
*/
private int getNextChessColor()
{
int chessColor = -1;
//得到上一步信息
if(this.gamePanel.listChess.size() > 0)
{
Map mapLast = this.gamePanel.listChess.get(this.gamePanel.listChess.size() - 1);
if(Integer.parseInt(mapLast.get("color")) == this.gamePanel.BLACKCHESS)
{
chessColor = this.gamePanel.REDCHESS;
}
else
{
chessColor = this.gamePanel.BLACKCHESS;
}
}
else
{
if(this.gamePanel.fightType == 0) //人机对战
{
if(this.gamePanel.playFirst == 1) //玩家先手
{
chessColor = this.gamePanel.chessColor;
}
else //电脑先手(这是不想赢啊)
{
if(this.gamePanel.chessColor == this.gamePanel.BLACKCHESS)
{
chessColor = this.gamePanel.REDCHESS;
}
else
{
chessColor = this.gamePanel.BLACKCHESS;
}
}
}
else //人人对战
{
chessColor = this.gamePanel.chessColor;
}
}
return chessColor;
}
/**
* 功能:将军提示
*/
private void check()
{
//全体循环,不知道将哪头的军
for(int i=0;i map = this.gamePanel.listMove.get(j);
int index = this.gamePanel.chessBoradState[map.get("row")][map.get("column")];
if(index != -1 && "king".equals(this.gamePanel.mapChess[index].get("type")))
{
JOptionPane.showMessageDialog(null,"将军,十万火急!");
break;
}
}
}
this.gamePanel.listMove.clear();
this.gamePanel.repaint();
}
/**
* 功能:判断棋子是否可以放到目标位置
* 参数:_mapChess -> 棋子
* 参数:_newRow -> 目标行位置
* 参数:_newColumn -> 目标列位置
* 备注:点空位或对方棋子上,已方棋子略
*/
private boolean isAbleToMove(Map _mapChess,int _newRow,int _newColumn)
{
int oldRow = -1; //移动前行位置
int oldColulmn = -1; //移动前列位置
int index = -1; //目标索引
String type = ""; //棋子类型
String direction = ""; //棋子方向(T-上方,B-下方)
//死亡棋子不能移动
if("T".equals(_mapChess.get("dead"))){return false;}
oldRow = Integer.parseInt(_mapChess.get("newRow"));
oldColulmn = Integer.parseInt(_mapChess.get("newColumn"));
type = _mapChess.get("type");
direction = _mapChess.get("direction");
index = this.gamePanel.chessBoradState[_newRow][_newColumn];
//不能吃自己伙的棋子
if(index != -1 && Integer.parseInt(this.gamePanel.mapChess[index].get("color")) == Integer.parseInt(_mapChess.get("color"))){return false;}
//不能吃自身
if(oldRow == _newRow && oldColulmn == _newColumn) {return false;}
if("king".equals(type)) //将帅
{
//不能出九宫
if((_newRow > 2 && _newRow < 7) || _newColumn < 3 || _newColumn > 5){return false;}
//一次只能走一格
if(Math.abs(_newRow - oldRow) > 1 || Math.abs(_newColumn - oldColulmn) > 1){return false;}
//不能走斜线
if((_newRow - oldRow) * (_newColumn - oldColulmn) != 0){return false;}
//将帅不能露脸
if(index != -1 && "king".equals(this.gamePanel.mapChess[index].get(type)) && oldColulmn == _newColumn) //目标棋子是将帅并且在同一列上
{
//判断中间是否有棋子
int count = 0;
int min = Math.min(oldRow,_newRow);
int max = Math.max(oldRow,_newRow);
for(int row=min+1;row 2 && _newRow < 7) || _newColumn < 3 || _newColumn > 5){return false;}
//一次只能走一格
if(Math.abs(_newRow - oldRow) > 1 || Math.abs(_newColumn - oldColulmn) > 1){return false;}
//不能走横线或竖线
if((_newRow - oldRow) * (_newColumn - oldColulmn) == 0){return false;}
}
else if("elephant".equals(type)) //象相
{
//不能越界
if("T".equals(direction))
{
if(_newRow > 4){return false;}
}
else
{
if(_newRow < 5){return false;}
}
//不能走横线或竖线
if((_newRow - oldRow) * (_newColumn - oldColulmn) == 0){return false;}
//一次只能走二格
if(Math.abs(_newRow - oldRow) != 2 || Math.abs(_newColumn - oldColulmn) != 2){return false;}
//是否堵象眼
if(this.gamePanel.chessBoradState[Math.min(oldRow,_newRow) + 1][Math.min(oldColulmn,_newColumn) + 1] != -1){return false;}
}
else if("horse".equals(type)) //马(8种跳法,4种别腿)
{
//必须走日字格
if( Math.abs((_newRow - oldRow)) * Math.abs((_newColumn - oldColulmn)) != 2){return false;}
//向上跳
if(_newRow - oldRow == -2)
{
if(this.gamePanel.chessBoradState[oldRow - 1][oldColulmn] != -1){return false;}
}
//向下跳
if(_newRow - oldRow == 2)
{
if(this.gamePanel.chessBoradState[oldRow + 1][oldColulmn] != -1){return false;}
}
//向左跳
if(_newColumn - oldColulmn == -2)
{
if(this.gamePanel.chessBoradState[oldRow][oldColulmn - 1] != -1){return false;}
}
//向右跳
if(_newColumn - oldColulmn == 2)
{
if(this.gamePanel.chessBoradState[oldRow][oldColulmn + 1] != -1){return false;}
}
}
else if("rook".equals(type)) //车
{
//不能走斜线
if((_newRow - oldRow) * (_newColumn - oldColulmn) != 0){return false;}
//竖走
if(_newColumn == oldColulmn)
{
//判断中间是否有棋子
int min = Math.min(oldRow,_newRow);
int max = Math.max(oldRow,_newRow);
for(int row=min+1;row 1)
{
return false;
}
else if(count == 1)
{
if(this.gamePanel.chessBoradState[_newRow][_newColumn] == -1){return false;} //打空炮的不要
}
else
{
if(this.gamePanel.chessBoradState[_newRow][_newColumn] != -1){return false;}
}
}
else if("soldier".equals(type)) //卒兵
{
//不能走斜线
if((_newRow - oldRow) * (_newColumn - oldColulmn) != 0){return false;}
//一次只能走一格
if(Math.abs(_newRow - oldRow) > 1 || Math.abs(_newColumn - oldColulmn) > 1){return false;}
//小卒过河不回头
if("T".equals(direction)) //上方
{
if(oldRow > 4) //过河了
{
if(_newRow < oldRow){return false;} //不许向后退
}
else
{
if(_newColumn == oldColulmn && _newRow > oldRow){} //只能往前走
else
{
return false;
}
}
}
else //下方
{
if(oldRow < 5) //过河了
{
if(_newRow > oldRow){return false;} //不许向后退
}
else
{
if(_newColumn == oldColulmn && _newRow < oldRow){} //只能往前走
else
{
return false;
}
}
}
}
return true;
}
/**
* 功能:将下完的棋子信息复制一份存储到下棋列表中,悔棋用
* 备注:因为是对象引用,所以必须复制b
*/
private void addList(Map _mapChess)
{
Map map = new HashMap();
map.put("index",_mapChess.get("index"));
map.put("color",_mapChess.get("color"));
map.put("type",_mapChess.get("type"));
map.put("name",_mapChess.get("name"));
map.put("number",_mapChess.get("number"));
map.put("direction",_mapChess.get("direction"));
map.put("oldOldRow",_mapChess.get("oldOldRow"));
map.put("oldOldColumn",_mapChess.get("oldOldColumn"));
map.put("oldRow",_mapChess.get("oldRow"));
map.put("oldColumn",_mapChess.get("oldColumn"));
map.put("newRow",_mapChess.get("newRow"));
map.put("newColumn",_mapChess.get("newColumn"));
map.put("dead",_mapChess.get("dead"));
map.put("oldEatIndex",_mapChess.get("oldEatIndex"));
map.put("eatIndex",_mapChess.get("eatIndex"));
this.gamePanel.listChess.add(map);
}
/**
* 功能:悔棋具体步骤
*/
private void undoStep()
{
if(this.gamePanel.isGameOver){return;}
if(this.gamePanel.listChess.size() < 1){return;}
//得到最后一步棋信息
Map mapLast = this.gamePanel.listChess.get(this.gamePanel.listChess.size() - 1);
int index = Integer.parseInt(mapLast.get("index"));
int oldOldRow = Integer.parseInt(mapLast.get("oldOldRow"));
int oldOldColumn = Integer.parseInt(mapLast.get("oldOldColumn"));
int oldRow = Integer.parseInt(mapLast.get("oldRow"));
int oldColumn = Integer.parseInt(mapLast.get("oldColumn"));
int newRow = Integer.parseInt(mapLast.get("newRow"));
int newColumn = Integer.parseInt(mapLast.get("newColumn"));
int oldEatIndex = Integer.parseInt(mapLast.get("oldEatIndex"));
int eatIndex = Integer.parseInt(mapLast.get("eatIndex"));
//开始退回
this.gamePanel.mapChess[index].put("newRow",Integer.toString(oldRow));
this.gamePanel.mapChess[index].put("newColumn",Integer.toString(oldColumn));
this.gamePanel.mapChess[index].put("oldRow",Integer.toString(oldOldRow));
this.gamePanel.mapChess[index].put("oldColumn",Integer.toString(oldOldColumn));
this.gamePanel.mapChess[index].put("oldOldRow","-1");
this.gamePanel.mapChess[index].put("oldOldColumn","-1");
this.gamePanel.mapChess[index].put("dead","F");
this.gamePanel.mapChess[index].put("eatIndex",Integer.toString(oldEatIndex));
this.gamePanel.mapChess[index].put("oldEatIndex","-1");
this.gamePanel.labelChess[index].setBounds(this.gamePanel.gridsLeftX + oldColumn * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.gridsTopY + oldRow * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.chessSize,this.gamePanel.chessSize);
this.gamePanel.chessBoradState[oldRow][oldColumn] = index;
//判断是否吃棋子了
if(eatIndex == -1) //未吃棋子
{
this.gamePanel.chessBoradState[newRow][newColumn] = -1;
}
else //吃棋子了,给我吐出来
{
this.gamePanel.mapChess[eatIndex].put("dead","F");
this.gamePanel.labelChess[eatIndex].setBounds(this.gamePanel.gridsLeftX + newColumn * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.gridsTopY + newRow * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.chessSize,this.gamePanel.chessSize);
this.gamePanel.chessBoradState[newRow][newColumn] = eatIndex;
}
this.gamePanel.listChess.remove(this.gamePanel.listChess.size() - 1);
}
/**
* 功能:悔棋
*/
public boolean undo()
{
int index,color,oldRow,oldColumn;
Map mapLast = null;
if(this.gamePanel.isGameOver){return false;}
if(this.gamePanel.listChess.size() < 1){return false;}
//得到最后一步棋信息
mapLast = this.gamePanel.listChess.get(this.gamePanel.listChess.size() - 1);
index = Integer.parseInt(mapLast.get("index"));
color = Integer.parseInt(mapLast.get("color"));
oldRow = Integer.parseInt(mapLast.get("oldRow"));
oldColumn = Integer.parseInt(mapLast.get("oldColumn"));
if(this.gamePanel.fightType == 0) //人机对战(只有玩家才会悔棋,电脑才不会这么耍赖)
{
//人机要同时悔2步棋,所以要得到倒数第二步棋信息
if(this.gamePanel.listChess.size() < 2)
{
JOptionPane.showMessageDialog(null,"禁止悔棋!","提示",JOptionPane.INFORMATION_MESSAGE);
return false;
}
mapLast = this.gamePanel.listChess.get(this.gamePanel.listChess.size() - 2);
index = Integer.parseInt(mapLast.get("index"));
color = Integer.parseInt(mapLast.get("color"));
oldRow = Integer.parseInt(mapLast.get("oldRow"));
oldColumn = Integer.parseInt(mapLast.get("oldColumn"));
//判断玩家是否可以悔棋
if(this.gamePanel.chessColor == this.gamePanel.BLACKCHESS) //玩家执黑
{
if(this.gamePanel.blackUndoNum == 0)
{
JOptionPane.showMessageDialog(null,"黑棋的悔棋次数已经全部用完了!","提示",JOptionPane.INFORMATION_MESSAGE);
return false;
}
this.gamePanel.blackUndoNum--;
}
else
{
if(this.gamePanel.redUndoNum == 0)
{
JOptionPane.showMessageDialog(null,"红棋的悔棋次数已经全部用完了!","提示",JOptionPane.INFORMATION_MESSAGE);
return false;
}
this.gamePanel.redUndoNum--;
}
this.undoStep(); //电脑悔一步
this.undoStep(); //玩家悔一步
}
else
{
//判断是否可以悔棋
if(color == this.gamePanel.REDCHESS)
{
if(this.gamePanel.redUndoNum == 0)
{
JOptionPane.showMessageDialog(null,"红棋的悔棋次数已经全部用完了!","提示",JOptionPane.INFORMATION_MESSAGE);
return false;
}
this.gamePanel.redUndoNum--;
}
else
{
if(this.gamePanel.blackUndoNum == 0)
{
JOptionPane.showMessageDialog(null,"黑棋的悔棋次数已经全部用完了!","提示",JOptionPane.INFORMATION_MESSAGE);
return false;
}
this.gamePanel.blackUndoNum--;
}
this.undoStep(); //玩家悔一步
}
//重新生成落子指示器
this.gamePanel.mapPointerChess.put("row",oldRow);
this.gamePanel.mapPointerChess.put("column",oldColumn);
this.gamePanel.mapPointerChess.put("color",color);
this.gamePanel.mapPointerChess.put("show",1);
this.gamePanel.isFirstClick = false;
this.gamePanel.firstClickChess = this.gamePanel.mapChess[index];
//显示移动路线图
this.getMoveRoute(this.gamePanel.firstClickChess);
//更新提示
this.gamePanel.jlb_blackUndoText.setText("剩"+gamePanel.blackUndoNum+"次");
this.gamePanel.jlb_redUndoText.setText("剩"+gamePanel.redUndoNum+"次");
if(color == this.gamePanel.REDCHESS)
{
this.gamePanel.jlb_redStateText.setText("已下完");
this.gamePanel.jlb_blackStateText.setText("已选棋");
}
else
{
this.gamePanel.jlb_redStateText.setText("已选棋");
this.gamePanel.jlb_blackStateText.setText("已下完");
}
//刷新
this.gamePanel.repaint();
return true;
}
/**
* 功能:对当前局面进行估分
* 备注:若电脑下的棋则(电脑分-玩家分),反之(玩家分-电脑分)
*/
private int evaluation(int[][] _chessBoradMap)
{
//基础分
final int BASE_ROOK = 500;
final int BASE_HORSE = 350;
final int BASE_ELEPHANT = 250;
final int BASE_GUARD = 250;
final int BASE_KING = 10000;
final int BASE_CANNON = 350;
final int BASE_SOLDIER = 100;
//灵活分(每多一个可走位置的相应加分)
final int FLEXIBLE_ROOK = 6;
final int FLEXIBLE_HORSE = 12;
final int FLEXIBLE_ELEPHANT = 1;
final int FLEXIBLE_GUARD = 1;
final int FLEXIBLE_KING = 0;
final int FLEXIBLE_CANNON = 6;
final int FLEXIBLE_SOLDIER = 15;
//其他
int score = 0; //总评估分数
int redScore = 0; //红旗评估分数
int blackScore = 0; //黑棋评估分数
//判断该谁下棋
int nextColor = this.getNextChessColor();
//所有棋子循环
for(int m=0;m 4 && newRow < 9) //过河了(不要最底框那行)
{
riverScore = 70;
if(newRow >= 6)
{
if(newColumn >= 2 && newColumn <= 6)
{
if(newRow >= 7 && newRow <=8 && newColumn >= 3 && newColumn <= 5)
{
riverScore = riverScore + 50;
}
else
{
riverScore = riverScore + 40;
}
}
}
}
}
else //下方
{
if(newRow > 0 && newRow < 5) //过河了(不要最顶框那行)
{
riverScore = 70;
if(newRow <= 3)
{
if(newColumn >= 2 && newColumn <= 6)
{
if(newRow >= 1 && newRow <=2 && newColumn >= 3 && newColumn <= 5)
{
riverScore = riverScore + 50;
}
else
{
riverScore = riverScore + 40;
}
}
}
}
}
if(color == this.gamePanel.BLACKCHESS)
{
blackScore = blackScore + riverScore;
}
else
{
redScore = redScore + riverScore;
}
}
//该棋子可以走的位置
for(int row=0;row
*/
private int negaMax(int[][] _chessBoradMap,int _depth)
{
int value;
int bestValue = -9999999;
//有事,程序还有好多漏洞,暂时未完善,也没写α与β剪枝,等有空再完善。
//if(this.gameOver())return evaluation(this.gamePanel.chessBoradState); //胜负已分,返回估值,有问题
System.out.println("_depth="+_depth);
//叶子节点
if(_depth == 0)
{
return this.evaluation(this.gamePanel.chessBoradState); //调用估值函数,返回估值
}
//生成每一步走法
int nextColor = this.getNextChessColor();
System.out.println("nextColor="+nextColor);
for(int i=0;i= bestValue)
{
bestValue = value;
if(_depth == this.Maxdepth)
{
this.mapNextChess.put("index",""+i);
this.mapNextChess.put("newRow",row+"");
this.mapNextChess.put("newColumn",column+"");
}
}
//恢复原来位置
this.undoStep();
}
}
}
}
return bestValue; //返回最大值
}
/**
* 功能:轮到电脑下棋了
*/
public void computerPlay()
{
int value;
value = this.negaMax(this.gamePanel.chessBoradState,Maxdepth);
int index = Integer.parseInt(this.mapNextChess.get("index"));
int newRow = Integer.parseInt(this.mapNextChess.get("newRow")) ;
int newColumn = Integer.parseInt(this.mapNextChess.get("newColumn")) ;
System.out.println("value="+value);
System.out.println("index="+index);
System.out.println("newRow="+newRow);
System.out.println("newColumn="+newColumn);
this.moveTo(this.gamePanel.mapChess[index],newRow,newColumn);
//落子指示器
this.gamePanel.mapPointerChess.put("row",newRow);
this.gamePanel.mapPointerChess.put("column",newColumn);
this.gamePanel.mapPointerChess.put("show",1);
this.gamePanel.mapPointerChess.put("color",this.gamePanel.computerChess);
this.gamePanel.repaint();
}
/**
* 功能:得到某棋子的可移动路线图
*/
private void getMoveRoute(Map _mapChess)
{
this.gamePanel.listMove.clear();
//懒得分类挑,反正电脑计算快
for(int row=0;row map = new HashMap();
map.put("row",row);
map.put("column",column);
this.gamePanel.listMove.add(map);
}
}
}
}
/**
* 功能:判断游戏是否结束
*/
private boolean gameOver()
{
if(this.gamePanel.fightType == 0) //人机对战
{
if("T".equals(this.gamePanel.mapChess[4].get("dead"))) //黑将被吃
{
if(this.gamePanel.computerChess == this.gamePanel.BLACKCHESS)
{
JOptionPane.showMessageDialog(null,"恭喜,你终于赢电脑一把了!");
}
else
{
JOptionPane.showMessageDialog(null,"我去,你怎么连电脑都输啊!","提示",JOptionPane.ERROR_MESSAGE);
}
return true;
}
if("T".equals(this.gamePanel.mapChess[27].get("dead"))) //红帅被吃
{
if(this.gamePanel.computerChess == this.gamePanel.BLACKCHESS)
{
JOptionPane.showMessageDialog(null,"我去,你怎么连电脑都输啊!","提示",JOptionPane.ERROR_MESSAGE);
}
else
{
JOptionPane.showMessageDialog(null,"恭喜,你终于赢电脑一把了!");
}
return true;
}
}
else //人人对战
{
if("T".equals(this.gamePanel.mapChess[4].get("dead"))) //黑将被吃
{
JOptionPane.showMessageDialog(null,"恭喜,红棋赢了!");
return true;
}
if("T".equals(this.gamePanel.mapChess[27].get("dead"))) //红帅被吃
{
JOptionPane.showMessageDialog(null,"恭喜,黑棋赢了!");
return true;
}
}
return false;
}
/**
* 功能:棋子移动到新位置
*/
private void moveTo(Map _mapChess,int _newRow,int _newColumn)
{
//判断是移动还是吃子
int newIndex = this.gamePanel.chessBoradState[_newRow][_newColumn];
if(newIndex != -1) //吃子
{
//目标棋子清除
this.gamePanel.mapChess[newIndex].put("dead","T");
this.gamePanel.labelChess[newIndex].setBounds(this.gamePanel.gridsLeftX + -2 * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.gridsTopY + -2 * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.chessSize,this.gamePanel.chessSize);
}
//新棋子占位
int index = Integer.parseInt(_mapChess.get("index"));
_mapChess.put("oldOldRow",_mapChess.get("oldRow"));
_mapChess.put("oldOldColumn",_mapChess.get("oldColumn"));
_mapChess.put("oldRow",_mapChess.get("newRow"));
_mapChess.put("oldColumn",_mapChess.get("newColumn"));
_mapChess.put("newRow",Integer.toString(_newRow));
_mapChess.put("newColumn",Integer.toString(_newColumn));
_mapChess.put("oldEatIndex",_mapChess.get("eatIndex"));
_mapChess.put("eatIndex",Integer.toString(newIndex));
this.addList(_mapChess);
this.gamePanel.labelChess[index].setBounds(this.gamePanel.gridsLeftX + _newColumn * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.gridsTopY + _newRow * this.gamePanel.gridSize - this.gamePanel.chessSize/2,this.gamePanel.chessSize,this.gamePanel.chessSize);
this.gamePanel.chessBoradState[Integer.parseInt(_mapChess.get("oldRow"))][Integer.parseInt(_mapChess.get("oldColumn"))] = -1;
this.gamePanel.chessBoradState[_newRow][_newColumn] = index;
this.gamePanel.isFirstClick = true;
}
/**
* 功能:鼠标单击事件
*/
public void mouseClicked(MouseEvent e)
{
if(this.gamePanel.isGameOver){return;}
if(e.getButton() == MouseEvent.BUTTON1) //鼠标左键点击
{
if(e.getSource() == this.gamePanel.labelChessBorad) //点击到棋盘上
{
//第一次点击无效
if(this.gamePanel.isFirstClick){return;}
//判断位置(将X与Y由像素改为相应的行列坐标)
int row = this.getRow(e.getY());
int column = this.getColumn(e.getX());
if(row >= 0 && row < 10 && column >= 0 && column < 9) //第二次点击
{
//要移动棋子了
if(this.isAbleToMove(this.gamePanel.firstClickChess,row,column))
{
this.moveTo(this.gamePanel.firstClickChess,row,column);
//取消移动路线图
this.gamePanel.listMove.clear();
//落子指示器
this.gamePanel.mapPointerChess.put("row",row);
this.gamePanel.mapPointerChess.put("column",column);
this.gamePanel.mapPointerChess.put("show",1);
//更新提示
if(Integer.parseInt(gamePanel.firstClickChess.get("color")) == this.gamePanel.BLACKCHESS)
{
this.gamePanel.jlb_redStateText.setText("思考中");
this.gamePanel.jlb_blackStateText.setText("已下完");
}
else
{
this.gamePanel.jlb_redStateText.setText("已下完");
this.gamePanel.jlb_blackStateText.setText("思考中");
}
this.gamePanel.repaint();
//判断是否将军
this.check();
//如果是人机对战,机器要回应啊
if(this.gamePanel.fightType == 0) //人机对战
{
this.computerPlay();
if(this.gamePanel.computerChess == this.gamePanel.BLACKCHESS)
{
this.gamePanel.jlb_blackStateText.setText("已下完");
this.gamePanel.jlb_redStateText.setText("思考中");
}
else
{
this.gamePanel.jlb_redStateText.setText("已下完");
this.gamePanel.jlb_blackStateText.setText("思考中");
}
//判断游戏是否结束
if(this.gameOver())
{
this.gamePanel.isGameOver = true;
this.gamePanel.setComponentState(false);
this.gamePanel.jlb_blackStateText.setText("已结束");
this.gamePanel.jlb_redStateText.setText("已结束");
return;
}
}
}
}
else
{
return;
}
}
else //点到棋子上
{
JLabel label = (JLabel)e.getSource();
int index = Integer.parseInt(label.getName());
int row = Integer.parseInt(this.gamePanel.mapChess[index].get("newRow"));
int column = Integer.parseInt(this.gamePanel.mapChess[index].get("newColumn"));
//判断第几次点击
if(this.gamePanel.isFirstClick) //第一次(必须点击到该下棋方的棋子上)
{
if(Integer.parseInt(this.gamePanel.mapChess[index].get("color")) != this.getNextChessColor()){return;}
//画个落子指示器并记录下第一次点击对象
this.gamePanel.mapPointerChess.put("row",row);
this.gamePanel.mapPointerChess.put("column",column);
this.gamePanel.mapPointerChess.put("show",1);
this.gamePanel.mapPointerChess.put("color",Integer.parseInt(this.gamePanel.mapChess[index].get("color")));
this.gamePanel.firstClickChess = this.gamePanel.mapChess[index];
this.gamePanel.isFirstClick = false;
this.gamePanel.repaint();
if(Integer.parseInt(this.gamePanel.mapChess[index].get("color")) == this.gamePanel.BLACKCHESS)
{
this.gamePanel.jlb_redStateText.setText("等待中");
this.gamePanel.jlb_blackStateText.setText("已选棋");
}
else
{
this.gamePanel.jlb_redStateText.setText("已选棋");
this.gamePanel.jlb_blackStateText.setText("等待中");
}
//显示移动路线图
this.getMoveRoute(this.gamePanel.firstClickChess);
this.gamePanel.repaint();
}
else //第二次点击
{
//点击到该下棋方的棋子上则还算是第一次
if(Integer.parseInt(this.gamePanel.mapChess[index].get("color")) == this.getNextChessColor())
{
this.gamePanel.mapPointerChess.put("row",row);
this.gamePanel.mapPointerChess.put("column",column);
this.gamePanel.mapPointerChess.put("show",1);
this.gamePanel.firstClickChess = this.gamePanel.mapChess[index];
this.gamePanel.isFirstClick = false;
this.getMoveRoute(this.gamePanel.firstClickChess); //显示移动路线图
this.gamePanel.repaint();
}
else //要吃棋子了
{
if(this.isAbleToMove(this.gamePanel.firstClickChess,row,column)) //这个可以吃
{
this.moveTo(this.gamePanel.firstClickChess,row,column);
//取消移动路线图
this.gamePanel.listMove.clear();
//落子指示器
this.gamePanel.mapPointerChess.put("row",row);
this.gamePanel.mapPointerChess.put("column",column);
this.gamePanel.mapPointerChess.put("show",1);
if(Integer.parseInt(gamePanel.firstClickChess.get("color")) == this.gamePanel.BLACKCHESS)
{
this.gamePanel.jlb_redStateText.setText("思考中");
this.gamePanel.jlb_blackStateText.setText("已下完");
}
else
{
this.gamePanel.jlb_redStateText.setText("已下完");
this.gamePanel.jlb_blackStateText.setText("思考中");
}
this.gamePanel.repaint();
//判断是否将军
this.check();
}
//判断游戏是否结束
if(this.gameOver())
{
this.gamePanel.isGameOver = true;
this.gamePanel.setComponentState(false);
this.gamePanel.jlb_blackStateText.setText("已结束");
this.gamePanel.jlb_redStateText.setText("已结束");
return;
}
//判断双方是否战平(这个不行啊)
//如果是人机对战,机器要回应啊
if(this.gamePanel.fightType == 0) //人机对战
{
this.computerPlay();
if(this.gamePanel.computerChess == this.gamePanel.BLACKCHESS)
{
this.gamePanel.jlb_blackStateText.setText("已下完");
this.gamePanel.jlb_redStateText.setText("思考中");
}
else
{
this.gamePanel.jlb_redStateText.setText("已下完");
this.gamePanel.jlb_blackStateText.setText("思考中");
}
//判断游戏是否结束
if(this.gameOver())
{
this.gamePanel.isGameOver = true;
this.gamePanel.setComponentState(false);
this.gamePanel.jlb_blackStateText.setText("已结束");
this.gamePanel.jlb_redStateText.setText("已结束");
return;
}
}
}
}
}
}
}
/**
* 功能:鼠标移动事件
*/
public void mouseMoved(MouseEvent e)
{
int row = -1;
int column = -1;
int index = -1;
if(this.gamePanel.isGameOver){return;}
//得到行列位置
if(e.getSource() == this.gamePanel.labelChessBorad) //在棋盘上移动
{
row = this.getRow(e.getY());
column = this.getColumn(e.getX());
}
else //在棋子上移动
{
JLabel label = (JLabel)e.getSource();
index = Integer.parseInt(label.getName());
row = Integer.parseInt(this.gamePanel.mapChess[index].get("newRow"));
column = Integer.parseInt(this.gamePanel.mapChess[index].get("newColumn"));
}
//判断是否在棋盘内部移动
if(row >= 0 && row < 10 && column >= 0 && column < 9)
{
//清除落子指示器(先不显示)
this.gamePanel.mapPointerMove.put("show",0);
if(this.gamePanel.chessBoradState[row][column] == -1) //移动到棋盘上
{
this.gamePanel.mapPointerMove.put("row",row);
this.gamePanel.mapPointerMove.put("column",column);
this.gamePanel.mapPointerMove.put("show",1);
this.gamePanel.mapPointerMove.put("color",-1);
}
else //移动到棋子上
{
//第一次点击处理
if(this.gamePanel.isFirstClick)
{
//下棋方显示移动显示器,非下棋方不显示移动指示器
if(Integer.parseInt(this.gamePanel.mapChess[index].get("color")) == this.getNextChessColor())
{
this.gamePanel.mapPointerMove.put("row",row);
this.gamePanel.mapPointerMove.put("column",column);
this.gamePanel.mapPointerMove.put("show",1);
this.gamePanel.mapPointerMove.put("color",-1);
}
}
else //第二次点击处理
{
this.gamePanel.mapPointerMove.put("row",row);
this.gamePanel.mapPointerMove.put("column",column);
this.gamePanel.mapPointerMove.put("show",1);
this.gamePanel.mapPointerMove.put("color",-1);
}
}
this.gamePanel.repaint();
}
else //点棋盘外边了
{
if(this.gamePanel.mapPointerMove.get("show") == 1)
{
this.gamePanel.mapPointerMove.put("show",0);
this.gamePanel.repaint();
}
}
}
}