项目实现的功能
1、实现人与人对决。
2、实现人与机器对决,对局双方各执一色棋子,要求其中一方为机器。
3、游戏开始要求为空棋盘。
4、黑先、白后,交替下子,每次只能下一子。
5、棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
6、黑方的第一枚棋子可下在棋盘任意交叉点上。
7、直到有一方获胜,结束对局。
8、要有图形界面,且界面设计美观、交互性好
9、允许悔棋
项目实现效果图
部分效果实现思路
为了计算实现悔棋操作,定义了一个栈,用来记录每一步的棋子。
机器方AI类的定义,该类中使用到的数据结构有两个Map,分别为AttackMap,其中存放的是进攻棋型,以及棋型对应的权值;DefendMap存放的是防守棋型,以及棋型对应的权值。这两个Map中,棋型是key,权值是value。Ai会根据算法算出当前棋盘空白交叉的的权值,然后Ai会下在权值最大的位置。
Ai算法的逻辑
清空权值矩阵,判断是否是Ai的回合,获取一个点的所有棋链(即进攻棋链和防御棋链)。定义一个二维数组来存放棋盘所有点的权值,最后计算最佳下棋点。
写代码遇到的坑
Java在传参时,只能传引用类型(类类型,接口类型和数组),基本数据类型(byte,short,int,long,char,float,double,Boolean)在传参的时候没有改变实际参数。简单来说,如果想两个类共享一个属性,这个属性必须是引用类型,不能是基本数据类型。
完整代码
Chess类
public class Chess {//记录每下一个棋子的状态
private int row, col;
private int color;
public Chess(int row,int col,int color){
this.row = row;
this.col = col;
this.color = color;
}
public Chess(){
}
public void setRow(int row) {
this.row = row;
}
public void setCol(int col) {
this.col = col;
}
public void setColor(int color) {
this.color = color;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public int getColor() {
return color;
}
}
ChessListener类
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class ChessListener extends MouseAdapter implements ActionListener {
public final int BOARD_SIZE = 13;
// 定义棋盘数组
public final int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
// 定义棋子的颜色,0表示无棋子,1表示黑子,2表示白子
private final int NONE = 0;
private final int BLACK = 1;
private final int WHITE = 2;
// 定义当前轮到哪种颜色的棋子
public int currentColor = BLACK;
public BoardPanel boardpanel;
public Graphics g ;
public GameReview gameReview=new GameReview();
public int idex=0;
public FiveChess reboard ;
public boolean isregret = true;
public boolean isPVE = true;
public boolean aifirst=false;
public Ai ai = new Ai();
public void setBoardPanel(BoardPanel boardpanel){//通过棋子的动态数组修改棋局
this.boardpanel=boardpanel;
}
public void actionPerformed(ActionEvent e) {
JButton jButton = (JButton) e.getSource();
if (jButton.getActionCommand().equals("悔棋")&&isregret) {
// for (Chess c : gameReview.chesses) {
// System.out.println("要回其的列" + c.getCol());
// }
Chess chess1 = gameReview.chesses.get(gameReview.chesses.size() - 1);
gameReview.chesses.remove(gameReview.chesses.size() - 1);
board[chess1.getRow()][chess1.getCol()] = NONE;
Chess chess2 = gameReview.chesses.get(gameReview.chesses.size() - 1);
gameReview.chesses.remove(gameReview.chesses.size() - 1);
board[chess2.getRow()][chess2.getCol()] = NONE;
boardpanel.repaint();
} else if (jButton.getActionCommand().equals("再来一局")) {
boardpanel.resetBoard();
gameReview.allclear();
boardpanel.repaint();
idex=0;//指针也要重新归零
System.out.println(jButton.getActionCommand());
} else if (jButton.getActionCommand().equals("人人对战")) {
isPVE = false;
} else if (jButton.getActionCommand().equals("人机对战")) {
isPVE = true;
}else if (jButton.getActionCommand().equals("你先手")) {
isPVE = true;
}else if (jButton.getActionCommand().equals("AI先手")&&!aifirst) {
Chess chess = new Chess(BOARD_SIZE/2,BOARD_SIZE/2,WHITE);
gameReview.chesses.add(chess);
board[chess.getRow()][chess.getCol()]=WHITE;
System.out.println("ai下中间了");
boardpanel.repaint();
aifirst=true;
}
else if (jButton.getActionCommand().equals("复盘")) {
boardpanel.resetBoard();
isregret=false;
System.out.println(jButton.getActionCommand());
boardpanel.repaint();
// FiveChess reboard = new FiveChess();
// for (Component component : reboard.getComponents()) {
// if (component instanceof JButton) {
// JButton button = (JButton) component;
// if (button.getActionCommand().equals("悔棋")||button.getActionCommand().equals("人人对战")||button.getActionCommand().equals("人机对战")) {
// reboard.remove(button);
// }
// }
// }
} else if (jButton.getActionCommand().equals("复盘上一步")) {
if (idex >0) {
Chess chess1 = gameReview.chesses.get(--idex);
board[chess1.getRow()][chess1.getCol()] = NONE;
boardpanel.repaint();
}
System.out.println(jButton.getActionCommand());
} else if (jButton.getActionCommand().equals("复盘下一步")) {
if (idex < gameReview.chesses.size()) {
Chess chess3 = gameReview.chesses.get(idex++);
if (chess3.getColor() == BLACK) {
board[chess3.getRow()][chess3.getCol()] = BLACK;
System.out.println(jButton.getActionCommand());
} else {
board[chess3.getRow()][chess3.getCol()] = WHITE;
}
boardpanel.repaint();
}
else{
JOptionPane.showMessageDialog(boardpanel, "复盘结束!");
}
}
}
public void mouseReleased (MouseEvent e) {
// 重绘棋盘面板
// 获取鼠标点击的坐标
int x = e.getX();
int y = e.getY();
int row=0;
int col=0;
aifirst=true;
// 将坐标转换为棋盘数组的索引
if(((y - 15) % 30)>=15) {
row = ((y - 15) / 30)+1;
System.out.println("row:"+row);
}
else if(((y - 15) % 30)<15) {
row = ((y - 15) / 30);
System.out.println(row);
}
if(((x- 15) % 30)>=15) {
col = ((x - 15) / 30)+1;
System.out.println(col);
}
else if(((x- 15) % 30)<15) {
col = ((x - 15) / 30);
}
//boardpanel.repaint();
// 判断是否在棋盘范围内并且该位置没有棋子
if (row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE && board[row][col] == NONE) {
// 在该位置放置当前颜色的棋子
board[row][col] = currentColor;
boardpanel.repaint();
boardpanel.validate();
Chess chess;
if(currentColor==1){
chess = new Chess(row, col, BLACK);
//System.out.println("chess=:"+chess.getRow()+"和"+chess.getCol());
}
else{
chess = new Chess(row, col, WHITE);
}
gameReview.chesses.add(chess);
//System.out.println(currentColor);
// 判断是否有五子连珠,即获胜
if (boardpanel.isWin(row, col, currentColor)) {
String colorName = currentColor == BLACK ? "黑" : "白";
JOptionPane.showMessageDialog(boardpanel, colorName + "方获胜!");
} else {
if (!isPVE) {//如果模式是人人对战
// 没有获胜则交换棋子颜色,继续下一轮
currentColor = currentColor == BLACK ? WHITE : BLACK;
boardpanel.currentColor = currentColor;
if (currentColor == BLACK) {
System.out.println("下一个:黑方");
} else {
System.out.println("下一个:白方");
}
// 更新状态栏显示
boardpanel.updateStatusBar();
}
else{
Ai.board =boardpanel.board;
Ai.gameReview=gameReview;
Ai.AiPlay();
//boardpanel.board = Ai.board;
boardpanel.repaint();
}
}
}
}
}
BoardPanel类
import javax.swing.*;
import java.awt.*;
// 定义内部类表示棋盘和棋子,继承自JPanel
public class BoardPanel extends JPanel {
public final int BOARD_SIZE = 13;
// 定义棋盘数组
public int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
// 定义棋子的颜色,0表示无棋子,1表示黑子,2表示白子
private final int NONE = 0;
private final int BLACK = 1;
private final int WHITE = 2;
// 定义当前轮到哪种颜色的棋子
public int currentColor=BLACK;
// 定义状态栏
public JLabel statusBar=new JLabel();
public BoardPanel() {
super();
setLayout(new BorderLayout());
// 初始化棋盘数组为全0
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
board[i][j] = NONE;
}
}
}
//重写JPanel的paintComponent方法
public void paint(Graphics g) {
super.paint(g);
// 设置背景颜色
setBackground(Color.GRAY);
// 设置画笔颜色为黑色
g.setColor(Color.BLACK);
// 画15条横线和竖线来形成棋盘网格
for (int i = 0; i < BOARD_SIZE; i++) {
g.drawLine(15, 15 + i * 30, 15 + (BOARD_SIZE - 1) * 30, 15 + i * 30);
g.drawLine(15 + i * 30, 15, 15 + i * 30, 15 + (BOARD_SIZE - 1) * 30);
}
// 遍历棋盘数组,画出相应颜色的棋子
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] == BLACK) {
g.setColor(Color.BLACK);
g.fillOval(5 + j * 30, 5 + i * 30, 20, 20);
} else if (board[i][j] == WHITE) {
g.setColor(Color.WHITE);
g.fillOval(5 + j * 30, 5 + i * 30, 20, 20);
}
}
}
this.updateStatusBar();
}
// 判断是否有五子连珠的方法,参数为最后一步下的棋子的位置和颜色
public boolean isWin(int row, int col, int color) {
// 定义四个方向的增量数组,分别表示水平,垂直,左上右下,右上左下
int[][] directions = {{1, 0}, {0, 1}, {1, 1}, {1, -1}};
// 遍历四个方向
for (int[] direction : directions) {
// 计算该方向上连续同色棋子的个数
int count = 1;
int x = col;
int y = row;
// 往该方向前进,直到遇到边界或者不同色的棋子,累加计数器
while (true) {
x += direction[0];
y += direction[1];
if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || board[y][x] != color) {
break;
}
count++;
}
// 往该方向后退,直到遇到边界或者不同色的棋子,累加计数器
x = col;
y = row;
while (true) {
x -= direction[0];
y -= direction[1];
if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || board[y][x] != color) {
break;
}
count++;
}
// 如果计数器达到5,表示有五子连珠,返回true
if (count >= 5) {
return true;
}
}
// 如果四个方向都没有五子连珠,返回false
return false;
}
// 重置棋盘的方法,将棋盘数组全部置为0,将棋子颜色重置为黑色,并更新状态栏
public void resetBoard() {
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
board[i][j] = NONE;
}
}
this.currentColor = BLACK;
this.updateStatusBar();
}
// 更新状态栏的方法,根据当前轮到的棋子颜色显示相应的文本
public void updateStatusBar() {
String colorName = this.currentColor == BLACK ? "黑" : "白";
statusBar.setText("轮到" + colorName + "方下棋");
}
}
GameReview类
import java.util.ArrayList;
public class GameReview {//有最终胜利的棋局,有各个棋子下的顺序
public ArrayList<Chess> chesses = new ArrayList<>();
private BoardPanel boardpanel;
public void remove(){
chesses.remove(chesses.size()-1);
chesses.remove(chesses.size()-1);
boardpanel.repaint();
}
public void allclear(){//清空动态数组的所有元素
chesses.clear();
}
}
Ai类
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Ai {
private static Map<String,Integer> AttackMap=new HashMap<>();
private static Map<String,Integer> DefendMap=new HashMap<>();
public static final int board_size = 13;
// 定义棋盘数组
private static Boolean aiTurn=true; //该值用来判断是否为ai的回合,所以初值为true
private static final int NONE = 0;
private static final int BLACK = 1;
private static final int WHITE = 2;
public static int aicolor=WHITE;
public static int pcolor=BLACK;
public static int[][] board = new int[board_size][board_size];
public static int[][] valuePad = new int[board_size][board_size]; //棋盘的权值矩阵,用来记录每一个位置的权值
public static BoardPanel boardpanel;
public static GameReview gameReview = new GameReview();
static {
//还要重新设计赋分策略,才能保证五子棋机器人的准确判断
//因为已经固定了 *为黑子,且默认将机器人设为黑方,所以机器人只能是黑方
//还要设置防守方的数值,防止被gank掉
//右边put的map值,是防守分数,这样Ai就不会一味的猛冲
//左边:进攻棋链,权值越大说明该棋链越接近胜利 右边:防御棋链,权值越大说明该棋链约值得防御
AttackMap.put("*****", 100000);//连五
/* */DefendMap.put("ooooo", 30000);
AttackMap.put("-****-", 5000);//活四
/* */DefendMap.put("-oooo-", 3000);
AttackMap.put("*-***", 700);//冲四 1
/* */DefendMap.put("o-ooo", 150);
AttackMap.put("***-*", 700);//冲四 1 反向
/* */DefendMap.put("ooo-o", 150);
AttackMap.put("-****o", 1000);//冲四 2
/* */DefendMap.put("-oooo*", 200);
AttackMap.put("o****-", 1000);//冲四 2 反向
/* */DefendMap.put("*oooo-", 200);
AttackMap.put("**-**", 700);//冲四 3
/* */DefendMap.put("oo-oo", 200);
AttackMap.put("-***-", 500);//活三 1
/* */DefendMap.put("-ooo-", 100);
AttackMap.put("*-**", 150);//活三 2
/* */DefendMap.put("o-oo", 50);
AttackMap.put("**-*", 150);//活三 2 反向
/* */DefendMap.put("oo-o", 50);
AttackMap.put("--***o", 100);//眠三 1
/* */DefendMap.put("--ooo*", 20);
AttackMap.put("o***--", 100);//眠三 1 反向
/* */DefendMap.put("*ooo--", 20);
AttackMap.put("-*-**o", 80);//眠三 2
/* */DefendMap.put("-o-oo*", 15);
AttackMap.put("o**-*-", 80);//眠三 2 反向
/* */DefendMap.put("*oo-o-", 15);
AttackMap.put("-**-*o", 60);//眠三 3
/* */DefendMap.put("-oo-o*", 10);
AttackMap.put("o*-**-", 60);//眠三 3 反向
/* */DefendMap.put("*o-oo-", 10);
AttackMap.put("*--**", 60);//眠三 4
/* */DefendMap.put("o--oo", 10);
AttackMap.put("**--*", 60);//眠三 4 反向
/* */DefendMap.put("oo--o", 10);
AttackMap.put("*-*-*", 60);//眠三 5
/* */DefendMap.put("o-o-o", 10);
AttackMap.put("o-***-o", 60);//眠三 6
/* */DefendMap.put("*-ooo-*", 2);
AttackMap.put("--**--", 50);//活二 1
/* */DefendMap.put("--oo--", 2);
AttackMap.put("-*-*-", 20);//活二 2
/* */DefendMap.put("-o-o-", 2);
AttackMap.put("*--*", 20);//活二 3
/* */DefendMap.put("o--o", 2);
AttackMap.put("---**o", 10);//眠二 1
/* */DefendMap.put("---oo*", 1);
AttackMap.put("o**---", 10);//眠二 1 反向
/* */DefendMap.put("*oo---", 1);
AttackMap.put("--*-*o", 10);//眠二 2
/* */DefendMap.put("--o-o*", 1 );
AttackMap.put("o*-*--", 10);//眠二 2 反向
/* */DefendMap.put("*o-o--", 1);
AttackMap.put("-*--*o", 10);//眠二 3
/* */DefendMap.put("-o--o*", 1);
AttackMap.put("o*--*-", 10);//眠二 3 反向
/* */DefendMap.put("*o--o-", 1);
AttackMap.put("*---*", 10);//眠二 4
/* */DefendMap.put("o---o", 1);
}
//Ai下棋主流程
public static void AiPlay(){
//清空权值矩阵,避免前一回合影响本回合的判断
clearvaluePad();
//判断是否为人机回合,AI永远下黑棋
// if (!aiTurn){
// return;
// }
Chess bestaichess=new Chess();
if(isEmptyPad()){
//如果是空棋盘,则永远下中间点的位置,
bestaichess = new Chess(board_size/2,board_size/2,aicolor);
gameReview.chesses.add(bestaichess);
putChess(bestaichess);
System.out.println(Arrays.deepToString(board));
System.out.println("AI下中间");
boardpanel.repaint();
}
else {
//先计算防御棋链,看看当前棋局是否有需要防御的地方
boolean defend=false;
// for (int i=0;i<board_size;i++){
// for (int j=0;j<board_size;j++){
// ArrayList<String> defends = getPositionChessLink(i, j, "defend");
// for (String s : defends) {
// if (s.equals("ooooo")){
// System.out.println("防御");
// bestaichess=new Chess(i,j,aicolor);
// defend=true;
// break ;
// }
// }
// }
// }
if (!defend){
//计算整个棋盘的权值
getAllValue();
//选取最佳下棋位置
bestaichess = getBestaichess();
gameReview.chesses.add(bestaichess);
System.out.println("最佳位置的行"+bestaichess.getRow()+"最佳位置的列"+bestaichess.getCol());
}
}
//将棋下入颜色棋盘
putChess(bestaichess);
//判断AI是否胜利
if (boardpanel.isWin(bestaichess.getRow(), bestaichess.getCol(), WHITE)) {
//String colorName = currentColor == BLACK ? "黑" : "白";
JOptionPane.showMessageDialog(boardpanel, "AI获胜!");
}
}
public static void AiPlayText(){
board[0][0]=WHITE;
board[0][1]=WHITE;
}
public static void clearvaluePad(){
for (int i = 0; i < board_size; i++) {
for (int j = 0; j < board_size ;j++) {
valuePad[i][j]=-1;
}
}
}
/**
* 该方法实现Ai的下棋操作,传入的Position对象 坐标为行列坐标
* @param
*/
public static void putChess(Chess p){
//System.out.println("哈哈,这就是最佳位置");
//更改颜色矩阵,完成下棋操作
board[p.getRow()][p.getCol()] = aicolor;
}
/**
* 该方法啊实现选取权值最大的点,AI下的棋就是下在这个点上
* @return 返回的是一个行列坐标的position对象
*/
public static Chess getBestaichess(){
//遍历权值棋盘,找出权值最大的点
int max=-1;
Chess position=new Chess();
for(int i = 0; i<board_size; i++){
for (int j = 0; j < board_size; j++){
//判断该点的权值是否大于最大值,同时该点必须为空棋
if(valuePad[i][j] > max){
max = valuePad[i][j];
position.setRow(i);
position.setCol(j);
}
}
}
position.setColor(aicolor);
return position;
// // //遍历找出所有的最大权值点
// List<Position> allMaxPosition=new ArrayList<>();
//
// for(int i=0;i<size;i++){
// for (int j=0;j<size;j++){
// //判断该点的权值是否大于最大值,同时该点必须为空棋
// if(colorPad[i][j]==ChessColor.Blank&&valuePad[i][j]==max){
// allMaxPosition.add(new Position(i,j));
// }
// }
// }
// //在最大权值点列表种,随机取出一个点(随机取的原因是:遍历数组都是按固定顺序遍历的,若不采取随机取的方法,则玩家能够通过固定的套路取胜)
// int s=allMaxPosition.size()-1;
// return allMaxPosition.get((int)(Math.random()*s));
}
/**
* 为整个权值棋盘,赋值
*/
public static void getAllValue(){
//获取权值棋盘
// int[][] valuePad = ChessPad.valuePad;
// int size = ChessPad.size;
for (int i=0;i<board_size;i++){
for (int j = 0; j < board_size; j++) {
//将每一个点传入计算权值
valuePad[i][j]=CalculateValue(i,j);
}
}
}
// public static int getPositionDefendValue(int row , int col){
// ArrayList<String> defendList = getPositionChessLink(row,col,"defend");
//
// //计算权值
// int defendValue=0;
//
// for (String s : defendList) {
// if(DefendMap.containsKey(s)){
// defendValue+=DefendMap.get(s);
// }
// }
//
// return defendValue;
// }
/**
* 该方法实现计算传入点的权值
*/
public static int CalculateValue(int row,int col){
//调用方法,返回该点的棋链
ArrayList<String> attackList = getPositionChessLink(row,col,"attack");
ArrayList<String> defendList = getPositionChessLink(row,col,"defend");
//计算权值
int attackValue=0;
int defendValue=0;
for (String s : attackList) {
if(AttackMap.containsKey(s)){
attackValue+=AttackMap.get(s);
}
}
for (String s : defendList) {
if(DefendMap.containsKey(s)){
defendValue+=DefendMap.get(s);
}
}
return Math.abs(attackValue-defendValue); //值越大说明该点即适合防御又适合进攻
}
/**
* 该方法实现获取一个点的所有棋链
* 棋链的获取分为四个方向:横、竖、斜、反斜
*/
public static ArrayList<String> getPositionChessLink(int row,int col,String type){
boolean flag=false;//flag为临时下的棋的标注
if(board[row][col]==NONE&&type.equals("attack")){
//假设该空点下的棋为黑棋
board[row][col]=aicolor;
flag=true;
}
else if(board[row][col]==NONE&&type.equals("defend")){
board[row][col]=pcolor;
flag=true;
}
ArrayList<String> resultList=new ArrayList<>();
// System.out.println("竖方向:");
if(flag) {
//先从竖方向获取棋链
for (int i = 4; i <= 7; i++) { //先寻找棋链长度最短为4 最后寻找最长不超过7
for (int j = 0; j < i; j++) { //判断传入的棋子在棋链上的位置(即第几个棋子,从左向右数)
String s = ""; //初始化
int startRow = row - j; //计算竖方向的开始坐标
int endRow = startRow + i - 1; //计算竖方向的结束坐标
//此处需要判断开始的点和结束的点是否超出了棋盘
if (startRow < 0 || endRow >= board_size) {
//该点超过了棋盘的范围
continue;
}
for (; startRow <= endRow; startRow++) {
if (board[startRow][col] == NONE) {
s = s + "-";
} else if (board[startRow][col] == aicolor) {
s = s + "*";
} else {
s = s + "o";
}
}
// System.out.println(s);
resultList.add(s); //将该棋链加入结果列表
}
}
// System.out.println("横方向:");
//计算横方向的棋链权值
for (int i = 4; i <= 7; i++) { //棋链长度,最短4,最长7
for (int j = 0; j < i; j++) { //棋在棋链上的位置,(从上往下)
String s = "";
//由于是横方向,故只需要计算开始的y和结束的y坐标
int startCol = col - j;
int endCol = startCol + i - 1;
//判断开始位置和结束位置是否在棋盘范围内
if (startCol < 0 || endCol >= board_size) {
continue;
}
for (; startCol <= endCol; startCol++) {
if (board[row][startCol] == NONE) {
s = s + "-";
} else if (board[row][startCol] == aicolor) {
s = s + "*";
} else {
s = s + "o";
}
}
// System.out.println(s);
resultList.add(s);
}
}
// System.out.println("斜方向:");
//从斜方向获取棋链
for (int i = 4; i <= 7; i++) {
for (int j = 0; j < i; j++) {
//此处为斜方向,改变棋在棋链上的位置,涉及 x 和 y 两个方向的改变,从左下往右上的方向来计算 两个坐标的变化为
int startRow = row + j;
int startCol = col - j;
int endRow = startRow - i + 1;
int endCol = startCol + i - 1;
//判断开始点和结束点是否在棋盘内
if (!((startRow >= 0 && startRow < board_size && startCol >= 0 && startCol < board_size) && (endRow >= 0 &&
endRow < board_size && endCol >= 0 && endCol < board_size))) {
continue;
}
String s = "";
for (int _row = startRow, _col = startCol;
_row >= endRow && _col <= endCol;
_row--, _col++) {
if (board[_row][_col] == NONE) {
s = s + "-";
} else if (board[_row][_col] == aicolor) {
s = s + "*";
} else {
s = s + "o";
}
}
// System.out.println(s);
resultList.add(s);
}
}
// System.out.println("反斜方向:");
//反斜方向
for (int i = 4; i <= 7; i++) {
for (int j = 0; j < i; j++) {
//计算开始的点
int startRow = row - j;
int startCol = col - j;
int endRow = startRow + i - 1;
int endCol = startCol + i - 1;
String s = "";
if (!((startRow >= 0 && startRow < board_size && startCol >= 0 && startCol < board_size) &&
(endRow >= 0 && endRow < board_size && endCol >= 0 && endCol < board_size))) {
continue;
}
for (int _row = startRow, _col = startCol; _row <= endRow && _col <= endCol; _row++, _col++) {
if (board[_row][_col] == NONE) {
s = s + "-";
} else if (board[_row][_col] == aicolor) {
s = s + "*";
} else {
s = s + "o";
}
}
// System.out.println(s);
resultList.add(s);
}
}
}
//返回之前将临时下的棋恢复
if (flag){
board[row][col]=NONE;
}
return resultList;
}
/**
* 该方法用于判断棋盘是不是都为空
* @return
*/
public static boolean isEmptyPad(){
for (int i=0;i<board_size;i++) {
for(int j=0;j<board_size;j++){
if(!(board[i][j]==NONE)) return false;
}
}
return true;
}
}
主类FiveChess
import javax.swing.*;
import java.awt.*;
public class FiveChess extends JFrame {
public FiveChess(){
// 创建状态栏并设置初始文本
BoardPanel boardpanel =new BoardPanel();
setTitle("五子棋");
//设置初始化文本
boardpanel.updateStatusBar();
// 将棋盘面板和状态栏添加到窗口中
add(boardpanel, BorderLayout.CENTER);
add(boardpanel.statusBar,BorderLayout.SOUTH);
Box select = Box.createVerticalBox();
ChessListener listenner = new ChessListener();
listenner.reboard=this;
select.setPreferredSize(new Dimension(180,500));
String[] button = {"再来一局","人人对战","人机对战","你先手","AI先手","悔棋","复盘","复盘上一步","复盘下一步"};//创建按钮数组
for(int i=0;i<button.length;i++) {
JButton jbu = new JButton(button[i]);//创建按钮对象,并赋给其数组值
jbu.setPreferredSize(new Dimension(160,110));//设置按钮大小
jbu.setActionCommand(button[i]);
select.add(jbu);//给操控面板添加按钮组件
jbu.addActionListener(listenner);//给按钮添加鼠标监听器
}
add(select,BorderLayout.EAST);
// 设置窗口大小和位置,并显示
setSize(650, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建棋盘面板并添加鼠标监听器
listenner.setBoardPanel(boardpanel);
listenner.g=boardpanel.getGraphics();
boardpanel.addMouseListener(listenner);
listenner.boardpanel=boardpanel;
Ai.boardpanel = boardpanel;
boardpanel.board =listenner.board;
// boardpanel.currentColor =listenner.currentColor;这么写没用
setVisible(true);
}
public static void main(String[] args) {
FiveChess newFivechess= new FiveChess();
}
}