java实现五子棋人机对战
package fir;
import java.awt.*;
import javax.swing.JPanel;
/**
* 有背景图片的Panel类
* @author tntxia
*/
public class BackgroundPanel extends JPanel {
private static final long serialVersionUID = -6352788025440244338L;
private Image image = null;
public BackgroundPanel(Image image) {
this.image = image;
}
// 固定背景图片,允许这个JPanel可以在图片上添加其他组件
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
}
}
package fir;
/**
* 初始化
* @author Administrator
*/
public class Ready {
private int x;
private int y;
private int count;
public int getCount(){
return this.count;
}
/**
* 计算所有赢法种类
* @return
*/
public Ready(int x,int y){
this.x=x;
this.y=y;
count=initCount();
}
private int initCount(){
int count=0;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y-4; j++) {
count++;
}
}
// 横线上
for (int i = 0; i < x; i++) {
for (int j = 0; j < y-4; j++) {
count++;
}
}
// 斜线上
for (int i = 0; i < x-4; i++) {
for (int j = 0; j < y-4; j++) {
count++;
}
}
// 反斜线上
for (int i = 0; i < x-4; i++) {
for (int j = y-1; j > 3; j--) {
count++;
}
}
return count;
}
/**
* 初始化所有赢法
* @param c
* @return
*/
public boolean[][][] initChess(){
boolean wins[][][]=new boolean[15][15][this.count];
int count=0;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y-4; j++) {
for (int k = 0; k < 5; k++) {
wins[i][j + k][count] = true;
}
count++;
}
}
for (int i = 0; i < x; i++) {
for (int j = 0; j < y-4; j++) {
for (int k = 0; k < 5; k++) {
wins[j + k][i][count] = true;
}
count++;
}
}
for (int i = 0; i < x-4; i++) {
for (int j = 0; j < y-4; j++) {
for (int k = 0; k < 5; k++) {
wins[i + k][j + k][count] = true;
}
count++;
}
}
for (int i = 0; i < x-4; i++) {
for (int j = y-1; j > 3; j--) {
for (int k = 0; k < 5; k++) {
wins[i + k][j - k][count] = true;//记录赢得可能性
}
count++;
}
}
return wins;
}
public int[] getMyWin(){
int []myWin=new int[count];
return myWin;
}
public int[] getConputerWin(){
int []conputer=new int[count];
return conputer;
}
/**
* 初始化棋盘
* @return
*/
public int[][] getChessBorad(){
int [][]chessBorad=new int[x][y];
return chessBorad;
}
}
package fir;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.ActionEvent;
import javax.swing.border.BevelBorder;
import javax.swing.JLabel;
import java.awt.Color;
/**
* 五子棋
* @author Administrator
*
* 棋子的大小为46像素(宽/高)
* 棋盘的大小为690像素(宽/高)
* 有效棋子总量(14*14)
*/
public class Fir extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Fir frame = new Fir();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public static int s=0;
public static boolean wins[][][];//五子棋的所有赢法,前两维代表棋盘,第三位代表所有赢法,每一个棋子都可以有多种赢法。
public static int[] myWin;//我方第i中赢法中,有n颗棋子,如果有5颗棋子代表已经赢了,例如:myWin[5]=2;代表第5中赢法中,已经有2颗棋子,
public static int[] computerWin;//计算机方第i中赢法中,有n颗棋子
public static int[][] chessBorad;//代表棋盘,值0代表没有下棋子,其他值代表已经下棋子了。
public Ready re=new Ready(15,15);//初始化数据
public boolean me=true;//true代表应该我方下棋
public boolean over=false;//游戏是否结束
JPanel panel=null;
public Fir() {//初始化界面
wins=re.initChess();
myWin=re.getMyWin();
computerWin=re.getConputerWin();
chessBorad=re.getChessBorad();
setTitle("fir");
Toolkit kit = Toolkit.getDefaultToolkit(); // 定义工具包
Dimension screenSize = kit.getScreenSize(); // 获取屏幕的尺寸
int screenWidth = screenSize.width; // 获取屏幕的宽
int screenHeight = screenSize.height; // 获取屏幕的高
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds((screenWidth-700)/2, (screenHeight-780)/2, 715, 770);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
this.setResizable(false);
Image image=new ImageIcon("image/background.jpg").getImage();
panel = new BackgroundPanel(image);//初始化背景面板
panel.setForeground(Color.BLACK);
panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel.setBounds(10, 10, 690, 690);
contentPane.add(panel);
panel.setLayout(null);
JButton btnBegin = new JButton("begin");
btnBegin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnBegin.setBounds(10, 710, 93, 23);
contentPane.add(btnBegin);
JButton btnRestart = new JButton("restart");
btnRestart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
btnRestart.setBounds(113, 710, 93, 23);
contentPane.add(btnRestart);
JButton btnClose = new JButton("close");//退出
btnClose.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
btnClose.setBounds(216, 710, 93, 23);
contentPane.add(btnClose);
/**
* 鼠标点击事件
*/
panel.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent e) { }//鼠标抬起
public void mousePressed(MouseEvent e) { }//鼠标按下
public void mouseExited(MouseEvent e) { }//鼠标离开
public void mouseEntered(MouseEvent e) { }//鼠标进入
public void mouseClicked(MouseEvent e) {//鼠标点击
if(!me||over){//如果不该我方下棋或已结束,则返回
return;
}
/**
* 计算点击时棋盘位置,坐标位置
*/
int i=e.getX();//棋盘位置(像素)
int j=e.getY();//棋盘位置(像素)
int px=i%46;//通过鼠标点击的位置计算棋子应该下的位置
int py=j%46;//通过鼠标点击的位置计算棋子应该下的位置
i=i-(px)+(px<=23?-23:23);//通过鼠标点击的位置计算棋子应该下的位置
j=j-(py)+(py<=23?-23:23);//通过鼠标点击的位置计算棋子应该下的位置
int x=(i+23)/46;//坐标位置(数组)
int y=(j+23)/46;//坐标位置(数组)
if(x==0||y==0||x>=15||y>=15){//规则:第一行,第一列不能下棋。
return ;
}
myStep(i,j,x,y);//我方下棋,
}
});
}
/**
* 我下棋
* @param i
* @param j
* @param x
* @param y
*/
public void myStep(int i,int j,int x,int y){
if (chessBorad[x][y] == 0) {
play(i,j);
chessBorad[x][y] = 1;
for (int k = 0; k < re.getCount(); k++) {
if (wins[x][y][k]) {
myWin[k]++;
computerWin[k] = 999;
if (myWin[k] == 5) {
System.out.println("my win");
over=true;
return;
}
}
}
}
me=!me;
computerStep();
}
/**
* 计算机下棋
*/
public void computerStep(){
if(over){//游戏结束
return;
}
int myScore[][] = new int[15][15];//评估我方评分
int computerScore[][] = new int[15][15];//评估计算机评分
int max = 0;
int x = 0;
int y = 0;
// 遍历棋盘
for (int i = 1; i < 15; i++) {//x轴
for (int j = 1; j < 15; j++) {//y轴
if (chessBorad[i][j] == 0) {// 当前可落子,如果不等于0代表已经有棋子
for (int k = 0; k < re.getCount(); k++) { // 每个点都在 多种赢法中,所以要遍历所有赢法
if (wins[i][j][k]) {// 计算他在K赢法中的 重要性
switch (myWin[k]) {//我方棋路,当前赢法中已经连上了几颗棋子
case 1:
myScore[i][j] += 200;
break;
case 2:
myScore[i][j] += 400;
break;
case 3:
myScore[i][j] += 2000;
break;
case 4:
myScore[i][j] += 10000;
break;
}
switch (computerWin[k]) {//计算机棋路,当前赢法中已经连上了几颗棋子
case 1:
computerScore[i][j] += 300;
break;
case 2:
computerScore[i][j] += 500;
break;
case 3:
computerScore[i][j] += 3000;
break;
case 4:
computerScore[i][j] += 20000;
break;
}
}
}
// 玩家最重要的落点
if (myScore[i][j] > max) {
max = myScore[i][j];
x = i;
y = j;
} else if (myScore[i][j] == max) {
if (computerScore[i][j] > computerScore[x][y]) { //
x = i;
y = j;
}
}
// AI最重要的落点
if (computerScore[i][j] > max) {
max = computerScore[i][j];
x = i;
y = j;
} else if (computerScore[i][j] == max) {
if (myScore[i][j] > myScore[x][y]) {
x = i;
y = j;
}
}
}
}
}
play(x*46-23,y*46-23);//下棋
chessBorad[x][y] = 2;//棋盘标记已下棋
for (int k = 0; k < re.getCount(); k++) {//遍历所有的赢法
if (wins[x][y][k]) {//如果(x,y)这个点在某一种赢法中
computerWin[k]++; //那么该种赢法中有多了一个棋子
myWin[k] = 999; //那么我方的这种赢法就不可能赢了,设一个异常的值
if (computerWin[k] == 5) { //如果计算机在某种赢法上连上了五个子,那么计算机就赢了,我方就输了
System.err.println("lose");
over = true; //结束游戏
return;
}
}
}
if (!over) {//如果没有结束游戏
me = !me;//换我方下棋
}
}
/***
* 把棋子放入棋盘
* @param x
* @param y
*/
public void play(int x,int y){
Icon icon;
if(s%2==0){
icon=new ImageIcon("image/black.png");//黑棋
}else{
icon=new ImageIcon("image/white.png");//白旗
}
s++;
JLabel lblNewLabel = new JLabel(icon);
lblNewLabel.setBounds(x,y, 46, 46);
panel.add(lblNewLabel);
panel.repaint();
}
}