Java版五子棋小游戏(java控制台)

前言: 该项目 为 Java 版五子棋小游戏,为控制台小游戏,主要功能有 人机大战,左右互战,可以悔棋可以提示,

人机大战采用 五元贡献法,代码简单 实况效果好 ,相比 一般 博弈论 判断局面的方式,比正真的AI 还是有一定的差距。还有更多可扩展 可以自行摸索

 

源码

 

核心代码:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
//游戏运行入口
public class FiveChess{public static void main(String[] args){new FiveChessMenu();}}
//界面类,这是游戏主体框架
class FiveChessWindows extends JFrame {//五子棋窗口
	private Chessboard chessboard = new Chessboard();//五子棋盘【关键】
	private Chess chess = new Chess();	//五子棋业务逻辑【关键】	
	private Panel toolbar1,toolbar2,toolbar3;	
	private boolean flag;//
	private JButton startButton;
	private JTextField text1, text2,text3,text4;
	private JButton prompt1,prompt2;
	private JButton backButton1,backButton2;
	private JButton exitButton;
	private int owner_flag=1;//用于左右互搏
	private boolean prompt_flag=false;
	private String utf_hz = null,utf_bz=null; //
	//完成五子棋游戏界面
	public void init(Boolean flag,int res_flag){
		this.flag=flag;Chess.FIRST=res_flag;
		setTitle("java版五子棋-five");//创建游戏界面窗口
		toolbar1 = new Panel();
		toolbar2 = new Panel();
		toolbar3 = new Panel();
		toolbar1.setLayout(new GridLayout(3,1,20,20));
		toolbar3.setLayout(new GridLayout(3,1,20,20));
		text1 = new JTextField();
		text1.setPreferredSize(new Dimension(60, 60)); // 设置大小
		text1.setFont(new Font(null, Font.BOLD,50));
		text1.setEditable(false);//设置不可编辑
		text2 = new JTextField();
		text2.setPreferredSize(new Dimension(60, 60)); // 设置大小
		text2.setFont(new Font(null, Font.BOLD,50));
		text2.setEditable(false);//设置不可编辑
		text3 = new JTextField();
		text3.setPreferredSize(new Dimension(60, 60)); // 设置大小
		text3.setFont(new Font(null, Font.BOLD,50));
		text3.setEditable(false);//设置不可编辑
		text4 = new JTextField();
		text4.setPreferredSize(new Dimension(60, 60)); // 设置大小
		text4.setFont(new Font(null, Font.BOLD,50));
		text4.setEditable(false);//设置不可编辑
		//把“选项”菜单加入到菜单栏
		//MyButton startButton= new MyButton("       重   新    开     始           ");
		startButton = new MyButton("       重     新    开     始           ");
		backButton1 = new MyButton("       悔      棋         ");
		backButton2 = new MyButton("       悔      棋         ");
		prompt1 = new MyButton("   提        ?      示       ");
		prompt2 = new MyButton("   提        ?      示       ");
		exitButton = new MyButton("        返     回    菜    单             ");
		toolbar1.setBackground(Color.cyan);
		toolbar2.setBackground(Color.green);
		toolbar3.setBackground(Color.cyan);
		if(!flag)toolbar1.add(new JLabel(new ImageIcon("./src/玩家.png")));
		else toolbar1.add(new JLabel(new ImageIcon("./src/电脑1.png")));
		toolbar3.add(new JLabel(new ImageIcon("./src/玩家.png")));
		JPanel j3 =new JPanel(new GridLayout(2,1,5,5));
		j3.add(text1);j3.add(text3);
		toolbar1.add(j3);
		if(!flag)text1.setText("—玩 家—");
		else text1.setText("—电 脑—");
		JPanel j4 =new JPanel(new GridLayout(2,1,5,5));
		j4.add(text2);j4.add(text4);
		toolbar3.add(j4);
		text2.setText("—玩 家—");
		JPanel j1=new JPanel();
		 j1.setLayout(new GridLayout(3,1,20,20));
		 j1.setBackground(Color.cyan);
		 j1.add(prompt1);
		 j1.add(backButton1);
		 toolbar1.add(j1);
		 JPanel j2=new JPanel();
		 j2.setLayout(new GridLayout(3,1,20,20));//网格布局
		 j2.setBackground(Color.cyan);
		 j2.add(prompt2);
		 j2.add(backButton2);
		 toolbar3.add(j2);
		 exitButton.setSize(180, 60);
		toolbar2.add(startButton);
		toolbar2.add(exitButton);
		Gbk_Utf1();
		textInit();
		ButtonInit();//按钮事件绑定初始化
			add(toolbar1, BorderLayout.WEST);
			add(toolbar2, BorderLayout.SOUTH);
			add(toolbar3, BorderLayout.EAST);
			add(chessboard,BorderLayout.CENTER);//把五子棋盘加入到frame
			//绑定鼠标事件,要下棋了,为了避免写无用的抽象方法的实现,
			chessboard.addMouseListener(new MouseAdapter(){
				public void mouseClicked(MouseEvent e){
					play(e);//鼠标点击引发下棋事件,处理下棋事件比较繁琐,为此开一个方法
				}
			});	
		//设置frame窗口左上角图标
		 setIconImage(this.getToolkit().getImage("./src/favicon.png"));
		 setLocation(225, 100);
		 setSize(1198, 800);
		 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		 setResizable(false);
		 setVisible(true);
		 AIFirstOptionInit();//
	}
	public void ButtonInit() {
		backButton1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				int xy=chessboard.goback();
				if(xy>0)chess.goback(xy);
			}
		});
		backButton2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
			    // goback();
				int xy=chessboard.goback();
				if(xy>0)chess.goback(xy);
			}
		});
		prompt1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				prompt_flag=!prompt_flag;
				chessboard.setPrompt(prompt_flag);
				if(prompt_flag) chessboard.setScores(chess.getScores());
				chessboard.repaint();
				
			}
		});	
		prompt2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				prompt_flag=!prompt_flag;
				chessboard.setPrompt(prompt_flag);
				if(prompt_flag) {chessboard.setScores(chess.getScores());}
				chessboard.repaint();
			}
		});	
		exitButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				new FiveChessMenu();
                dispose();
			}
		});	
			
		startButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				FiveChessWindows five = new FiveChessWindows();
				  five.init(flag,1);
				  new RockPaperScissors(flag,five);
				  dispose();
			}
		});	
	}
	//“先后手处理事件
	public void AIFirstOptionInit(){
				//棋盘还没有落子的时候可以选择“机器先手”,一旦有落子,选择“机器先手”失效
				if(chessboard.isEmpty()){
					if(Chess.FIRST ==-1) {
					//机器先手,则先在中间位置下一个棋子
					chessboard.addChessman(7, 7, -1);
					chess.addChessman(7, 7, -1);
				}
	}
}
	public void Gbk_Utf1() {
		try {
				utf_hz= new String("⚫".getBytes("UTF-8"), "UTF-8");
				utf_bz = new String("⚪".getBytes("UTF-8"), "UTF-8");
			} catch (UnsupportedEncodingException e1) {e1.printStackTrace();}
	}
	public void textInit() {
		if(Chess.FIRST==-1) {text3.setText(" 先手"+utf_hz);text4.setText(" 后手 "+utf_bz);}
		else {text3.setText(" 后手 "+utf_bz);text4.setText(" 先手 "+utf_hz);}
	}
	//核心业务逻辑  处理鼠标落子事件
	public void play(MouseEvent e){
		int cellSize = chessboard.getCellSize();//每个格子的边长
		int x = (e.getX() - 5) / cellSize;//像素值转换成棋盘坐标
		int y = (e.getY() - 5) / cellSize;//像素值转换成棋盘坐标
		//判断落子是否合法
		boolean isLegal = chess.isLegal(x, y);
		//如果落子合法
		if(isLegal){
			chessboard.addChessman(x, y, owner_flag);//界面方面加一个棋子
			chess.addChessman(x, y, owner_flag);//逻辑业务方面加一个棋子
			//判断人类是否胜利
			if(chess.isWin(x, y, owner_flag)){
				 chessboard.setIsWin(chess.getisWinChess());
				 JOptionPane.showMessageDialog(this, "                   己方获胜", "您赢了!", JOptionPane.PLAIN_MESSAGE);
				chessboard.init();//初始化
				chess.init();
				textInit();
				return;
			}
			Location loc = chess.searchLocation();//根据五元贡献的方法确定
			if(flag) {
				//机器落子
				//Location loc = chess.searchLocation();//根据五元贡献的方法确定
				chessboard.addChessman(loc);
				chess.addChessman(loc.getX(), loc.getY(), loc.getOwner());
				//判断机器是否胜利
				if(chess.isWin(loc.getX(), loc.getY(), -1)){
					chessboard.setIsWin(chess.getisWinChess());
					JOptionPane.showMessageDialog(this, "             对方获胜", "您输了!", JOptionPane.PLAIN_MESSAGE);
					chessboard.init();
					chess.init();
					textInit();
					return;
				}
			}else owner_flag=-owner_flag;
			chessboard.setPrompt(prompt_flag);//更行提示分数和棋子
			 chess.searchLocation();chessboard.setScores(chess.getScores());
		}
	} 
}
 class Chessboard extends JPanel{//棋盘类 继承了 JPanel
	private static final long serialVersionUID = 1L;
	public static final int CHESSBOARD_SIZE = 15;//棋盘大小15X15
	private ArrayList<Location> locationList = new ArrayList<>();//棋盘上所有可以落子的位置坐标等信息
	private Color backgroundColor = new Color(255, 245, 186);//棋盘背景色
	private Color lineColor = new Color(66, 66, 66);//棋盘线条颜色
	private int margin = 30;//棋盘边缘长度
	private int[][] scores;//获取胜利棋子;
	private int[] iswinxy;
	private boolean prompt_flag=false;
	public void init(){locationList.clear();repaint();}	//初始化棋盘
	public void setPrompt(boolean prompt_flag2) {this.prompt_flag=prompt_flag2;}//获取是否提示状态
	public void setScores(int[][] scores) {this.scores=scores;}//获取分数数据
	public void setIsWin(int[] iswinxy) {this.iswinxy=iswinxy;}
	public void paint(Graphics g){//覆盖paint方法
		super.paint(g);
		drawChessboard(g);//画棋盘
		drawScores(g);//画分数
		drawiswin(g);//画胜利棋子
		drawChessman(g);//画棋子
	}
	public void drawChessboard(Graphics g){//画棋盘
		
		g.setColor(backgroundColor);//先画背景
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		g.setColor(lineColor);//画线
		int cellSize = (this.getWidth() - 2*margin)/(CHESSBOARD_SIZE - 1);//每个格子的边长
		for(int i = 0; i < CHESSBOARD_SIZE; i++){
			g.drawLine(margin, margin + i*cellSize,this.getWidth() - margin, margin + i*cellSize);//画横线
			g.drawLine(margin + i*cellSize, margin, margin + i*cellSize, this.getHeight() -margin);//画纵线
		}
	}
	public void drawChessman(Graphics g){//画棋子
		for(int i = 0; i < locationList.size(); i++){
			Location loc = locationList.get(i);
			int cellSize = (this.getWidth() - 2*margin)/(CHESSBOARD_SIZE - 1);//每个格子的边长
		  if(i==locationList.size()-1) {
				g.setColor(new Color(207,13,62));// 标记最后一个棋子四周为红色
				g.fillRoundRect(margin + cellSize*loc.getX() - cellSize/2-5, margin + cellSize*loc.getY() - cellSize/2-5, cellSize+8, cellSize+8,100,100);
				g.setColor(backgroundColor);
				g.fillRoundRect(margin + cellSize*loc.getX() - cellSize/2-2, margin + cellSize*loc.getY() - cellSize/2-2, cellSize+2, cellSize+2,100,100);
			}	 
		    //根据先后手设置棋子为黑色和白色
			if(loc.getOwner() == Chess.FIRST)g.setColor(Color.BLACK);
		    else g.setColor(Color.WHITE);	//画棋子
			g.fillOval(margin + cellSize*loc.getX() - cellSize/2+3, margin + cellSize*loc.getY() - cellSize/2+3, cellSize-6, cellSize-6);

		}
	}
  //划分数
	public void drawScores(Graphics g) {
		if(prompt_flag) {
		   int Maxscore=0,Maxx=-1,Maxy=-1;
		  g.setColor(Color.darkGray);
		  int cellSize = (this.getWidth() - 2*margin)/(CHESSBOARD_SIZE - 1);//每个格子的边长
		  for(int i = 0; i < CHESSBOARD_SIZE; i++)
			for(int j = 0; j < CHESSBOARD_SIZE; j++) {
				if(Maxscore<=scores[i][j]){Maxscore=scores[i][j];Maxx=i;Maxy=j;}
				g.drawString(""+scores[i][j],margin + i*cellSize, margin + j*cellSize);
		  }
		  g.setColor(Color.green);//画提示棋子。
		  g.fillOval(margin + cellSize*Maxx - cellSize/2+5, margin + cellSize*Maxy - cellSize/2+5, cellSize-8, cellSize-8);
		}
	}		
		public void drawiswin(Graphics g) { //画胜利棋子
			 if(iswinxy!=null && iswinxy.length>3) {
			  g.setColor(Color.darkGray);System.out.println(iswinxy.length);
			  int cellSize = (this.getWidth() - 2*margin)/(CHESSBOARD_SIZE - 1);//每个格子的边长
			  int x1,y1;
			  for(int i=0;i<5;i++) {
			     x1=iswinxy[i]/100;y1=iswinxy[i]%100;
			    g.setColor(new Color(207,13,62));//
				g.fillRoundRect(margin + cellSize*x1 - cellSize/2-5, margin + cellSize*y1 - cellSize/2-5, cellSize+8, cellSize+8,100,100);
				g.setColor(backgroundColor);
				g.fillRoundRect(margin + cellSize*x1 - cellSize/2-2, margin + cellSize*y1 - cellSize/2-2, cellSize+2, cellSize+2,100,100);
			  }	
			  iswinxy=null;
		  }  
		}	
	public int goback() {
		if (locationList.size() == 0)return -1;
		int x=locationList.get(locationList.size()-1).getX();
		int y=locationList.get(locationList.size()-1).getY();
		locationList.remove(locationList.size()-1);repaint();
		return x*100+y;
	}
	public void addChessman(int x, int y, int owner){locationList.add(new Location(x, y, owner));repaint();}//落子
	public void addChessman(Location loc){locationList.add(loc);repaint();}
	public int getCellSize(){return (this.getWidth() - 2*margin)/(CHESSBOARD_SIZE - 1);}//计算棋盘每个小格子的大小
	public boolean isEmpty() {return locationList.size() == 0 ? true : false;}//判断棋盘是否还没有棋子
}
class Location{
	private int x;//某个棋盘位置横坐标,0-14
	private int y;//某个棋盘位置纵坐标,0-14
	private int owner;//占据该位置的棋手方,1是人类,-1是机器,0是空
	private int score;//对该位置的打的分数
	public Location(){}//构造方法
	public Location(int x, int y, int owner){this.x = x;this.y = y;this.owner = owner;}
	public Location(int x, int y, int owner, int score){this(x, y, owner);this.score = score;}
	public int getX(){return this.x;}//x 坐标
	public void setX(int x){this.x = x;}
	public int getY(){return this.y;} //y坐标
	public void setY(int y){this.y = y;}
	public int getOwner(){return this.owner;}// 棋盘点 状态坐标
	public void setOwner(int owner){this.owner = owner;}
	public int getScore(){return this.score;}// 该点分数
	public void setScore(int score){this.score = score;}
}
//下棋业务核心类,与界面棋盘对应,业务放在这里,可以和界面代码分离
 class Chess{
	public static final int CHESSBOARD_SIZE = 15;
	public static int FIRST = 1;//先手,-1表示机器,1表示人类,与Location类中的对应
	private int[][] chessboard = new int[CHESSBOARD_SIZE][CHESSBOARD_SIZE];//与界面棋盘对应,0代表空,-1代表机器,1代表人类
	private int[][] score = new int[CHESSBOARD_SIZE][CHESSBOARD_SIZE];//每个位置得分
	private int[] iswinxy=new int[6];//胜利棋子坐标。
	public Chess(){}	
	public void goback(int xy) {chessboard[xy/100][xy%100]=0;}
	public void init(){
		FIRST = 1;//默认人类先手
		for(int i = 0; i  < CHESSBOARD_SIZE; i++)
			for(int j = 0; j < CHESSBOARD_SIZE; j++){chessboard[i][j] = 0; score[i][j] = 0;}//初始化棋盘 和分数表
	}
	public void addChessman(int x, int y, int owner){chessboard[x][y] = owner;}	//落子
	public boolean isLegal(int x, int y){//棋盘边界判断 以及是否落子	//判断落子位置是否合法
		if(x >=0 && x < CHESSBOARD_SIZE && y >= 0 && y < CHESSBOARD_SIZE && chessboard[x][y] == 0)return true;
		return false;
	}
	public boolean isWin(int x, int y, int owner){//判断哪方赢了(必定有刚落的子引发,因此只需判断刚落子的周围),owner为-1代表机器,owner为1代表人类
	 int sum = 0,k=1; for(int i=0;i<6;i++)iswinxy[i]=0;
	 iswinxy[0]=x*100+y;
	 //判断纵向上下方向
	 for(int i = x - 1; i >= 0; i--)if(chessboard[i][y] == owner){ sum++;iswinxy[k++]=i*100+y;}else break;	
	 for(int i = x + 1; i < CHESSBOARD_SIZE; i++)if(chessboard[i][y] == owner){sum++;iswinxy[k++]=i*100+y;}else break;
     if(sum >= 4) {return true;}
	 //判断横向向左右边
     sum = 0;k=1;
	 for(int i = y - 1; i >= 0; i--)if(chessboard[x][i] == owner){sum++;iswinxy[k++]=x*100+i;}else break;
	 for(int i = y + 1; i < CHESSBOARD_SIZE; i++)if(chessboard[x][i] == owner){sum++;iswinxy[k++]=x*100+i;}else break;
	 if(sum >= 4) {return true;}
	 //判断左上角到右下角方向上侧和左上角到右下角方向下侧(正斜线)
	 sum = 0;k=1;
	 for(int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j-- )if(chessboard[i][j] == owner){sum++;iswinxy[k++]=i*100+j;}else break;
	 for(int i = x + 1, j = y + 1; i < CHESSBOARD_SIZE && j < CHESSBOARD_SIZE; i++, j++ )if(chessboard[i][j] == owner){sum++;iswinxy[k++]=i*100+j;}else break;
	 if(sum >= 4) {return true;}
	 //判断右上角到左下角方向上侧和右上角到左下角方向下侧(反斜线)
	  sum = 0;k=1;
	  for(int i = x + 1, j = y - 1; i < CHESSBOARD_SIZE && j >= 0; i++, j--)if(chessboard[i][j] == owner){sum++;iswinxy[k++]=i*100+j;}else break;
	  for(int i = x - 1, j = y + 1; i >= 0 && j < CHESSBOARD_SIZE; i--, j++ )if(chessboard[i][j] == owner){sum++;iswinxy[k++]=i*100+j;}else break;
	  if(sum >= 4) {return true;}
       return false;
	}
	public int[] getisWinChess() { return iswinxy;}//获取胜利棋子
	public int[][] getchessborad() { return chessboard;}//获取胜利棋子
	//确定机器落子位置
	//使用五元贡献评分算法
	//算法思路:对15X15的572个五元组分别评分,一个五元组的得分就是该五元组为其中每个位置贡献的分数,  一个位置的分数就是其所在所有五元组分数之和。所有空位置中分数最高的那个位置就是落子位置。
	public Location searchLocation(){
		int humanChessmanNum = 0;//五元组中的黑棋数量
		int machineChessmanNum = 0;//五元组中的白棋数量
		int tupleScoreTmp = 0;//五元组得分临时变量
		int goalX = -1;//目标位置x坐标
		int goalY = -1;//目标位置y坐标	
		int maxScore = -1;//最大分数
		for(int i = 0; i  < CHESSBOARD_SIZE; i++)//每次都初始化下score评分数组(全部置零)////每次机器找寻落子位置,评分都重新算一遍
		 for(int j = 0; j < CHESSBOARD_SIZE; j++) score[i][j] = 0;
		//1.扫描横向和横向的15个行
		for(int i = 0; i < CHESSBOARD_SIZE; i++){
			for(int j = 0; j < CHESSBOARD_SIZE-4; j++){
				for(int k = j; k < j + 5; k++)//每次加五个状态
					if(chessboard[i][k] == -1) machineChessmanNum++;else if(chessboard[i][k] == 1)humanChessmanNum++;
			  tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);//为该五元组的每个位置添加分数
				for(int k = j; k < j + 5; k++)score[i][k] += tupleScoreTmp;
				humanChessmanNum =tupleScoreTmp=machineChessmanNum=0;//清零
				for(int k = j; k < j + 5; k++){//每次加五个状态
					if(chessboard[k][i] == -1) machineChessmanNum++;
					else if(chessboard[k][i] == 1)humanChessmanNum++;
				 }
			  tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);
				for(int k = j; k < j + 5; k++)score[k][i] += tupleScoreTmp;
			   humanChessmanNum =tupleScoreTmp=machineChessmanNum=0;//清零
			}
		}
		//3.扫描右上角到左下角上侧部分
		for(int i = CHESSBOARD_SIZE-1; i >= 4; i--){
			for(int k = i, j = 0; j < CHESSBOARD_SIZE && k >= 0; j++, k--){
				int m = k, n = j;
				while(m > k - 5 && k - 5 >= -1){
					if(chessboard[m][n] == -1) machineChessmanNum++;
					else if(chessboard[m][n] == 1)humanChessmanNum++;
					m--;n++;
				}
				if(m == k-5){//注意斜向判断的时候,可能构不成五元组(靠近四个角落),遇到这种情况要忽略掉
					tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);
					for(m = k, n = j; m > k - 5 ; m--, n++)score[m][n] += tupleScoreTmp;//为该五元组的每个位置添加分数
				}
				  humanChessmanNum =tupleScoreTmp=machineChessmanNum=0;//清零
			}
		}
		//4.扫描右上角到左下角下侧部分
		for(int i = 1; i < CHESSBOARD_SIZE; i++){
			for(int k = i, j = CHESSBOARD_SIZE-1; j >= 0 && k < CHESSBOARD_SIZE; j--, k++){
				int m = k,n=j;
				while(m < k + 5 && k + 5 <= CHESSBOARD_SIZE){
					if(chessboard[n][m] == -1) machineChessmanNum++;
					else if(chessboard[n][m] == 1)humanChessmanNum++;
					m++;n--;
				}
				if(m == k+5){//注意斜向判断的时候,可能构不成五元组(靠近四个角落),遇到这种情况要忽略掉
					tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);
					for(m = k, n = j; m < k + 5; m++, n--)score[n][m] += tupleScoreTmp;//为该五元组的每个位置添加分数
				}
				humanChessmanNum =tupleScoreTmp=machineChessmanNum=0;//清零
			}
		}
		//5.扫描左上角到右下角部分
		for(int i = 0; i < CHESSBOARD_SIZE-4; i++){
			for(int k = i, j = 0; j < CHESSBOARD_SIZE && k < CHESSBOARD_SIZE; j++, k++){
				int m,n;
				for(m=k,n=j;m < k + 5 && k + 5 <= CHESSBOARD_SIZE;m++,n++){
					if(chessboard[m][n] == -1) machineChessmanNum++;
					else if(chessboard[m][n] == 1)humanChessmanNum++;
				}
				if(m == k + 5){//注意斜向判断的时候,可能构不成五元组(靠近四个角落),遇到这种情况要忽略掉
					tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);
					for(m = k, n = j; m < k + 5; m++, n++)score[m][n] += tupleScoreTmp;	//为该五元组的每个位置添加分数
				}
				  humanChessmanNum =tupleScoreTmp=machineChessmanNum=0;//清零
			   for(m=k,n=j;m < k + 5 && k + 5 <= CHESSBOARD_SIZE;m++,n++){
						if(chessboard[n][m] == -1) machineChessmanNum++;
						else if(chessboard[n][m] == 1)humanChessmanNum++;
				}
				if(m == k + 5){//注意斜向判断的时候,可能构不成五元组(靠近四个角落),遇到这种情况要忽略掉
					tupleScoreTmp = tupleScore(humanChessmanNum, machineChessmanNum);
				   //为该五元组的每个位置添加分数
					for(m = k, n = j; m < k + 5; m++, n++)score[n][m] += tupleScoreTmp;
				 }
				humanChessmanNum =tupleScoreTmp=machineChessmanNum=0;//清零 
			}
		}		
		for(int i = 0; i < CHESSBOARD_SIZE; i++)//从空位置中找到得分最大的位置(确定落子位置)
			for(int j = 0; j < CHESSBOARD_SIZE; j++)
				if(chessboard[i][j] == 0 && score[i][j] > maxScore){goalX = i; goalY = j; maxScore = score[i][j];}
				else if(chessboard[i][j] != 0)score[i][j]=0;
		if(goalX != -1 && goalY != -1)return new Location(goalX, goalY, -1);
		return new Location(-1, -1, -1);//没找到坐标说明平局了
	}
	public int[][] getScores() {return score;}
	//各种五元组情况评分表
	public int tupleScore(int humanChessmanNum, int machineChessmanNum){
		int[] hb= {0,15,400,1800,100000};//人类落子 1,2,3,4 分别对应 15 400 1800,100000
		int[] mb= {0,35,800,15000,800000};//机器落子 1,2,3,4分别对应 35 800 15000 800000
		//1.既有人类落子,又有机器落子,判分为0
		if(humanChessmanNum > 0 && machineChessmanNum > 0)return 0;
		if(humanChessmanNum == 0 && machineChessmanNum == 0)return 7;
		if(machineChessmanNum >0)return mb[machineChessmanNum];
		if(humanChessmanNum>0)return hb[humanChessmanNum];
		return -1;//若是其他结果肯定出错了。这行代码根本不可能执行
	}
}
//自定义按钮
 class MyButton extends JButton  {
	 private Color quit = new Color(205, 255, 205);// 离开时颜色
	 public static final Color BUTTON_COLOR1 = new Color(205, 255, 205);
	 public static final Color BUTTON_COLOR2 = new Color(51, 154, 47);
	 public MyButton(String s) {
	  super(s);	
		setFont(new java.awt.Font(null,  1,  22)); //
		setBorder(BorderFactory.createRaisedBevelBorder());//凸出
		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
	  setContentAreaFilled(false);// 是否显示外围矩形区域 选否
	 }
	 public void paintComponent(Graphics g) {
	  g.setColor(quit);
	  g.fillRoundRect(0, 0, getSize().width - 1, getSize().height - 1,20, 20);
	  super.paintComponent(g);
	 }
	 public void paintBorder(Graphics g) { g.drawRoundRect(0, 0, getSize().width - 1, getSize().height - 1,20, 20);}
 }

 

页面展示

1 主菜单页面展示

2 猜拳决定落子展示

3.下棋展示(当前落子圈红)

4.获胜突出现实展示

5.开启提示展示(绿色提示落子)

完整资源链接: 下载链接