1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > java——博弈算法实现井字棋游戏

java——博弈算法实现井字棋游戏

时间:2021-08-18 04:38:22

相关推荐

java——博弈算法实现井字棋游戏

通过java语言开发了一个简单的井字棋游戏。主要有6个类,其中有一个是主类(Main.java),一个是抽象类(PiecesMove.java)组成。

下面对各个类简单介绍一下:

TicTicToe.java:

主要负责创建棋盘,管理棋盘。

TicTicToeUI.java:

主要由判断谁是先手的对话框、对战界面和提示谁输谁赢三个对话框组成,负责管理用户交互。

PiecesMove.java:

里面有2个方法,move(TicTacToe tict)是抽象方法由子类实现,isWinning(int[][] cur)判断是否游戏结束。

Computer.java:

负责计算机的落子位置计算,核心算法为博弈算法。

Player.java:

负责获取人落子的位置。

Main.java:

负责创建以上类的实例,控制谁先走子,游戏结束是否继续等逻辑处理。

下面贴出源代码:

TicTicToe.java:

/** Created by shphuang on /4/4.* */import javax.swing.*;import java.awt.*;public class TicTacToe {public static int num = 0;//计数走的步数//存储棋盘矩阵值private int[][] chessBd = new int[3][3];//按钮矩阵private JButton[][] buttons;//判断该谁走public boolean PLAYER_MOVE = true;//实例化Tictactoeprivate static TicTacToe tict = null;public static TicTacToe instanceTict(JButton[][] buttons){if (tict == null){tict = new TicTacToe(buttons);}return tict;}//初始化棋盘private TicTacToe(JButton[][] buttons){this.buttons = buttons;clearBoard();}//设置棋盘的值public void setChessBd(int x , int y , int checkBd) {this.chessBd[x][y] = checkBd;}//得到棋盘public int[][] getChessBd() {return chessBd;}//得到按钮矩阵public JButton[][] getButtons() {return buttons;}//清空棋盘public void clearBoard() {for (int i=0 ; i < 3 ; i++){for (int j=0 ; j < 3 ; j++){chessBd[i][j] = 0 ;}}num = 0;}//将棋盘画出来public void drawBoard(){updateUI();}//更新uiprivate boolean updateUI(){for (int i = 0; i < chessBd.length; i++) {for (int j = 0; j < chessBd.length; j++) {switch (chessBd[i][j]){case -1:buttons[i][j].setBackground(Color.white);break;case 0:buttons[i][j].setBackground(Color.lightGray);break;case 1:buttons[i][j].setBackground(Color.black);break;}}}return false;}}

TicTicToeUI.java:

/** Created by shphuang on /4/4.* */import javax.swing.*;import java.awt.*;public class TicTacToeUI {private JButton[][] buttons = new JButton[3][3];private JFrame jf;private JPanel jp;//实例化TictactoeUIprivate static TicTacToeUI tictactoeUI = null;public static TicTacToeUI instanceTictactoeUI(){if (tictactoeUI == null){tictactoeUI = new TicTacToeUI();}return tictactoeUI;}private TicTacToeUI(){init();}private void init(){//创建并设置framejf = new JFrame();jf.setTitle("designed by 爱编程的大鹏"); //设置显示窗口标题// 得到显示器屏幕的宽高int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;int width = 470;int height = 470;int offset_x = screenWidth/2-width/2;int offset_y = screenHeight/2-height/2;jf.setBounds(offset_x,offset_y,width,height); //设置窗口显示尺寸Container c= jf.getContentPane(); //获取当前窗口的内容窗格//创建并设置paneljp = new JPanel();jp.setBackground(new Color(159, 156, 157, 20)); //设置背景色jp.setLayout(new GridLayout(3,3,10,10)); //设置布局//初始化按钮矩阵for (int i = 0; i < buttons.length; i++) {for (int j = 0; j < buttons.length; j++) {JButton button = new JButton();buttons[i][j] = button;button.setBackground(Color.lightGray);jp.add(button);}}c.add(jp); //将panel面板添加到framejf.setVisible(true); //设置窗口是否可见jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //置窗口是否可以关闭}//初始化TictactoeUI//得到JFrame对象public JFrame getJf() {return jf;}//得到JPanel对象public JPanel getJp() {return jp;}//返回buttons对象public JButton[][] getButtons() {return buttons;}public boolean DialogUI(String msg) {try {Thread.sleep(200);int temp = JOptionPane.showConfirmDialog(jp,msg,"提示",0,1);if (temp == 0){return true;}} catch (InterruptedException e) {e.printStackTrace();}return false;}}

PiecesMove.java:

/** Created by shphuang on /4/4.* */abstract class PiecesMove {public abstract void move(TicTacToe tict);//返回0表示没有人赢,返回-1表示人赢了,返回1表示计算机赢了,返回2表示平局public static int isWinning(int[][] cur){for (int i = 0; i<3; i++){if (cur[i][0] == 1 && cur[i][1] == 1 && cur[i][2] == 1)return 1;if (cur[i][0] == -1 && cur[i][1] == -1 && cur[i][2] == -1)return -1;}for (int i = 0; i<3; i++){if (cur[0][i] == 1 && cur[1][i] == 1 && cur[2][i] == 1)return 1;if (cur[0][i] == -1 && cur[1][i] == -1 && cur[2][i] == -1)return -1;}if ((cur[0][0] == 1 && cur[1][1] == 1 && cur[2][2] == 1) || (cur[2][0] == 1 && cur[1][1] == 1 && cur[0][2] == 1))return 1;if ((cur[0][0] == -1 && cur[1][1] == -1 && cur[2][2] == -1) || (cur[2][0] == -1 && cur[1][1] == -1 && cur[0][2] == -1))return -1;if(TicTacToe.num >= 9){return 2;}return 0;}}

Computer.java:

/** Created by shphuang on /4/4.* */public class Computer extends PiecesMove {//电脑的棋子类型private static final int COMPUTER = 1;private static final int depth = 3;//实例化Playerprivate static Computer computer = null;public static Computer instanceComputer() {if (computer == null) {computer = new Computer();}return computer;}@Overridepublic void move(TicTacToe tict) {tict.num += 1;//步数+1int[][] curQP = createTempArray(tict.getChessBd());int[] xyVal = getXY(curQP);if (tict.getChessBd()[xyVal[0]][xyVal[1]] == 0) {tict.setChessBd(xyVal[0], xyVal[1], COMPUTER);tict.drawBoard();}}//得到x、y的坐标private int[] getXY(int[][] curQP) {int[] xy = new int[2];int[] val = new int[1];val[0] = -10000;int m = -10000, dep = 1;for (int x = 0; x < 3; x++) {for (int y = 0; y < 3; y++) {if (curQP[x][y] == 0) {curQP[x][y] = 1;if (isWinning(curQP) == 1) {xy[0] = x;xy[1] = y;return xy;}val[0] = cut(curQP, val, dep, true);if (val[0] > m) {m = val[0];xy[0] = x;xy[1] = y;}val[0] = -10000;curQP[x][y] = 0;}}}return xy;}//主算法部分,实现A-B剪枝的算法,val为上一层的评价值,dep为搜索深度,max记录上一层是否为极大层private int cut(int[][] curQP, int[] val, int dep, boolean max){//如果搜索深度达到最大深度,或者深度加上当前棋子数已经达到9,就直接调用评价函数if (dep == depth || dep + TicTacToe.num == 9){return value(createTempArray(curQP));}int i, j , temp;int[] flag = new int[1];boolean out = false; //out记录是否剪枝,初始为false//如果用户玩家输了,就置上一层的评价值为无穷(用很大的值代表无穷)if (isWinning(curQP) == 1){val[0] = 10000;return 0;}if (max)//如果上一层是极大层,本层则需要是极小层,记录flag为无穷大;反之,则为记录为负无穷大flag[0] = 10000; //flag记录本层节点的极值elseflag[0] = -10000;for (i = 0; i < 3 && !out; i++)//两重循环,遍历棋盘所有位置{for (j = 0; j < 3 && !out; j++) {if (curQP[i][j] == 0)//如果该位置上没有棋子{if (max)//并且为上一层为极大层,即本层为极小层,轮到用户玩家走了。{curQP[i][j] = -1;//该位置填上用户玩家棋子if (isWinning(curQP) == -1) //如果用户玩家赢了temp = -10000; //置棋盘评价值为负无穷elsetemp = cut(curQP,flag, dep + 1, !max); //否则继续调用ab剪枝函数if (temp < flag[0]) //如果下一步棋盘的评价值小于本层节点的极值,则置本层极值为更小者,即后辈结点极小值<=祖先节点极大值flag[0] = temp;} else{//如果上一层为极小层,算法与上面刚好相反curQP[i][j] = 1;//该位置填上电脑玩家棋子if (isWinning(curQP) == 1)//如果电脑玩家赢了,置棋盘评价值为正无穷temp = 10000;elsetemp = cut(curQP,flag, dep + 1, !max); // 否则继续调用ab剪枝函数if (temp > flag[0])//如果下一步棋盘的评价值大于本层节点的极值,则置本层极值为更小者,即后辈结点极大值>=祖先节点极小值flag[0] = temp;if (flag[0] >= val[0])//如果本层的极值已经大于上一层的评价值,则不需要搜索下去,剪枝 B剪枝out = true;}curQP[i][j] = 0; //把模拟下的一步棋还原,回溯}}}if (max){//根据上一层是否为极大层,用本层的极值修改上一层的评价值if (flag[0] > val[0])val[0] = flag[0];} else {if (flag[0] < val[0])val[0] = flag[0];}return flag[0]; //函数返回的是本层的极值}//评估函数private int value(int[][] curQP) {int p = 0;int q = 0;int[][] tmpQP = new int[3][3];for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {tmpQP[i][j] = curQP[i][j];}}//将棋盘中的空格填满自己的棋子,既将棋盘数组中的0变为1for (int i = 0; i<3; i++)for (int j = 0; j<3; j++)if (curQP[i][j] == 0)tmpQP[i][j] = 1;elsetmpQP[i][j] = curQP[i][j];//电脑一方//计算每一行中有多少行的棋子连成3个的for (int i = 0; i<3; i++)p += (tmpQP[i][0] + tmpQP[i][1] + tmpQP[i][2]) / 3;//计算每一列中有多少列的棋子连成3个的for (int i = 0; i<3; i++)p += (tmpQP[0][i] + tmpQP[1][i] + tmpQP[2][i]) / 3;//斜行有没有连成3个的?p += (tmpQP[0][0] + tmpQP[1][1] + tmpQP[2][2]) / 3;p += (tmpQP[2][0] + tmpQP[1][1] + tmpQP[0][2]) / 3;//将棋盘中的空格填满对方的棋子,既将棋盘数组中的0变为-1for (int i = 0; i<3; i++)for (int j = 0; j<3; j++)if (curQP[i][j] == 0)tmpQP[i][j] = -1;else tmpQP[i][j] = curQP[i][j];//对方//计算每一行中有多少行的棋子连成3个的for (int i = 0; i<3; i++)q += (tmpQP[i][0] + tmpQP[i][1] + tmpQP[i][2]) / 3;//计算每一列中有多少列的棋子连成3个的for (int i = 0; i<3; i++)q += (tmpQP[0][i] + tmpQP[1][i] + tmpQP[2][i]) / 3;//斜行有没有连成3个的?q += (tmpQP[0][0] + tmpQP[1][1] + tmpQP[2][2]) / 3;q += (tmpQP[2][0] + tmpQP[1][1] + tmpQP[0][2]) / 3;return p + q;}//返回一个局部变量的数组,防止干扰棋盘值private int[][] createTempArray(int[][] array) {int[][] temp = new int[3][3];for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {temp[i][j] = array[i][j];}}return temp;}}

Player.java:

/** Created by shphuang on /4/4.* */import javax.swing.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;public class Player extends PiecesMove {private static final int PLAYER = -1;//实例化Playerprivate static Player player = null;public static Player instancePlayer(){if (player == null){player = new Player();}return player;}//Player走一步@Overridepublic void move(TicTacToe tict) {while(true){int[] xy = getXY(tict);int position_x = xy[0];int position_y = xy[1];if (tict.getChessBd()[position_x][position_y] == 0){tict.num += 1;//步数+1tict.setChessBd(position_x, position_y , PLAYER);tict.drawBoard();break;}}}//监听用户走的位置private int[] getXY(TicTacToe tict) {int[] xy = new int[2];xy[0] = -1;xy[1] = -1;JButton[][] buttons = tict.getButtons();while (xy[0]==-1 || xy[1] == -1){for (int i = 0; i < buttons.length; i++) {for (int j = 0; j < buttons.length; j++) {int finalI = i;int finalJ = j;buttons[i][j].addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent actionEvent) {if (actionEvent.getSource() == buttons[finalI][finalJ]) {xy[0] = finalI;xy[1] = finalJ;}}});}}}return xy;}}

Main.java:

/** Created by shphuang on /4/4.*** 1、产生棋盘* 2、判断谁先(默认player先)* 3、player走一步* 4、判断player是否胜利* 5、computer走一步* 6、判断computer是否胜利* */public class Main {public static void main(String[] args) {//实例化TictactoeUI、Tictactoe、Player和ComputerTicTacToeUI ui = TicTacToeUI.instanceTictactoeUI();TicTacToe tict = TicTacToe.instanceTict(ui.getButtons());Player player = Player.instancePlayer();Computer computer = Computer.instanceComputer();//记录是否进行游戏boolean flag = true;while (flag){//清空棋盘tict.clearBoard();//画出棋盘tict.drawBoard();//记录谁先走boolean wfm = ui.DialogUI("你要先走吗?");//记录游戏是否结束,flag=false则游戏结束flag = startGame(tict,computer,player,wfm);//记录游戏结束时谁赢。-1:player胜利 1:computer胜利 2:平局int whoWin = PiecesMove.isWinning(tict.getChessBd());if (whoWin == -1){flag = ui.DialogUI("恭喜,你赢了 !\n\t\t你还要继续?");}else if (whoWin == 1){flag = ui.DialogUI("很抱歉,你输了 !\n\t\t你还要继续?");}else if(whoWin == 2){flag = ui.DialogUI("你真厉害,居然打成平手了 !\n\t\t你还要继续?");}}//关闭窗口ui.getJf().dispose();}//游戏开始private static boolean startGame(TicTacToe tict, Computer computer, Player player, boolean wfm){while (true){if (wfm){player.move(tict);switch (PiecesMove.isWinning(tict.getChessBd())){case -1:return false;case 1:return false;case 2:return false;}computer.move(tict);switch (PiecesMove.isWinning(tict.getChessBd())){case -1:return false;case 1:return false;case 2:return false;}} else {computer.move(tict);switch (PiecesMove.isWinning(tict.getChessBd())){case -1:return false;case 1:return false;case 2:return false;}player.move(tict);switch (PiecesMove.isWinning(tict.getChessBd())){case -1:return false;case 1:return false;case 2:return false;}}}}}

百度网盘链接:传送门 提取码:xmy7

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。