码迷,mamicode.com
首页 > 其他好文 > 详细

五子棋———完美注释版,免费分享!!!

时间:2016-06-06 22:14:09      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:

这是一个基于穷举算法的五子棋。人机大战时,计算机的算法是扫描穷举法。下面是核心类的代码。

import javax.swing.JOptionPane;
import javax.swing.JPanel;

//五子棋游戏的核心类
public class GoGame {
    // 棋盘的高度,宽度。chessModel代表棋盘的种类1为20*15,2为30*20,3为40*30
    private int height, width, chessModel;
    // 棋盘的横纵坐标,用于获取点击坐标的,初始化的值为零。
    private int x = 0, y = 0;
    // 棋盘对应的颜色,取1,2,3,-5。
    // 1代表棋盘格上为黑子,2代表棋盘格上位白子,3代表棋盘格上没有棋子,-5代表棋盘格上不能下子//包括了边
    private int[][] chessMapShow;
    // isOdd交换棋手的标志,true是黑子(玩家)下,false是白子下,但是下完子之后,isodd马上会变成对方的标志。
    // isExist某棋盘格子上是否有棋子的标识true代表有棋子。
    private boolean isOdd, isExist;

    // 无参数的构造方法
    public GoGame() {
    }

    // 有参数的构造方法,初始化棋盘的数组,调用初始化棋盘的方法。
    public GoGame(int chessModel) {
        this.isOdd = true;
        if (chessModel == 1) {
            PanelInit(20, 15, chessModel);
        }
        if (chessModel == 2) {
            PanelInit(30, 20, chessModel);
        }
        if (chessModel == 3) {
            PanelInit(40, 30, chessModel);
        }
    }

    // 构造好棋盘的布局,只有本类能够调用,因为只有在构造初始化的时候调用,外部类不需要调用
    private void PanelInit(int width, int height, int chessModel) {
        this.width = width;
        this.height = height;
        this.chessModel = chessModel;
        this.chessMapShow = new int[width + 1][height + 1];
        // 行数代表高度,列数代表宽度
        for (int i = 0; i <= width; i++) {
            for (int j = 0; j <= height; j++) {
                chessMapShow[i][j] = -5;// 首先是不能下棋的
            }
        }
    }

    // 获取是否交换棋手的标识
    public boolean getIsOdd() {
        return this.isOdd;
    }

    // 设置交换棋手的标志。
    public void setIsOdd(boolean isOdd) {
        if (isOdd) {
            this.isOdd = true;
        }else {
            this.isOdd =false;      }

    }

    // 获取该棋盘某一格子上是否有棋子的标识
    public boolean getIsExist() {
        return this.isExist;
    }

    // 获取棋盘高度
    public int getHeight() {
        return this.height;

    }

    // 获取棋盘宽度
    public int getWidth() {
        return this.width;
    }

    // 获取棋盘的种类
    public int getChessModel() {
        return this.chessModel;
    }

    // 获取棋盘的地图上的棋格子的信息。
    public int[][] getChessMapShow() {
        return this.chessMapShow;
    }

    // 判断是下子是否横向越界,或纵向越界。
    public boolean overMap(int y, int x) {
        // 横向越界
        if (x >= width + 20 || x < 0)
            return true;
        // 纵向越界
        return y >= height + 20 || y < 0;
    }

    // 判断是格子上是否有棋子了
    public boolean chessExist(int i, int j) {
        // 如果数组上已经有黑子和白子,就返回true
        if (chessMapShow[i][j] == 1 || chessMapShow[i][j] == 2) {
            return true;
        }
        return false;
    }

    // 准备下棋,把坐标xy的棋格上变成可以下棋的数字标志。
    public void readyUp(int x, int y) {
        // 如果坐标xy越界了棋盘数组,就退出方法。
        if (overMap(x, y)) {
            return;
        }
        // 如果坐标xy上已经有棋子了,就退出方法。
        if (chessExist(x, y)) {
            this.isExist = true;
            return;
        }
        // 如果不存在棋子要没有越界,就把这个坐标的棋格上改为可以下棋
        chessMapShow[x][y] = 3;
    }

    // 在某一位置上下棋
    public void upChess(int x, int y) {
        // 如果越界了,退出方法。
        if (overMap(x, y)) {
            return;
        }
        // 如果存在棋子了,设置isExist标志成为true
        if (chessExist(x, y)) {
            this.isExist = true;
            return;
        } else {
            this.isExist = false;
            if (getIsOdd()) {
                // isOdd如果是true就下的是黑子,是false就下的是白子。
                // 总是要把交换标识isOdd变成对方执手,让对方下棋。
                setIsOdd(false);
                this.chessMapShow[x][y] = 1;
            } else {
                setIsOdd(true);
                this.chessMapShow[x][y] = 2;
            }
        }
    }

    // 记录电脑下子横向坐标
    public void setX(int x) {
        this.x = x;
    }

    // 记录电脑下子的纵向坐标
    public void setY(int y) {
        this.y = y;
    }

    // 获取电脑下子的横向坐标
    public int getX() {
        return this.x;
    }

    // 获取电脑下子的纵向坐标
    public int getY() {
        return this.y;
    }

    // 计算某一格子上的四个直线方向的棋子的最大值
    // 左,右直线方向。
    // 上下直线方向。
    // 左上,右下直线方向。
    // 右上,左下直线方向。
    // black_or_write是传进的数值,1位黑,2为白。
    public int checkMax(int x, int y, int black_or_write) {
        // num是计棋子数。max_num是自大棋子数,最终的返回值。max_temp是临时的用来 记录临时的最大的棋子数。
        int num = 0, max_num, max_temp = 0;
        // 为了不破坏传进来的xy值,用来存储此刻棋子格子的坐标
        int x_temp = x, y_temp = y;
        // 指针,二维指向坐标xy为中心的八个方向,四条直线。
        int x_temp1 = x_temp, y_temp1 = y_temp;
        // 判断右边,接着就是判断右边。每次相对传入xy坐标循环四次。
        for (int i = 1; i < 5; i++) {
            x_temp1 += 1;
            if (x_temp1 > this.width) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        // 判断左边,指针退指向原来的xy坐标位置
        x_temp1 = x_temp;
        for (int i = 1; i < 5; i++) {
            x_temp1 -= 1;
            if (x_temp1 < 0) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        if (num < 5) {
            max_temp = num;
        }
        // 判断上边,同样要先复原指针恢复为xy的坐标位置
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 0;
        for (int i = 1; i < 5; i++) {
            y_temp1 -= 1;
            if (y_temp1 < 0) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        // 判断下边
        y_temp1 = y_temp;
        num = 0;
        for (int i = 1; i < 5; i++) {
            y_temp1 += 1;
            if (y_temp1 > this.height) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        // 如果num大于上一次记录最大量。就把num的值传入max_num.
        if (num > max_temp && num < 5) {
            max_temp = num;
        }
        // 判断左上
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 0;
        for (int i = 1; i < 5; i++) {
            x_temp1 -= 1;
            y_temp1 -= 1;
            if (y_temp1 < 0 || x_temp1 < 0) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        // 判断右下
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        for (int i = 1; i < 5; i++) {
            x_temp1 += 1;
            y_temp1 += 1;
            if (y_temp1 > this.height || x_temp1 > this.width) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        if (num > max_temp && num < 5) {
            max_temp = num;
        }
        // 判断右上
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 0;
        for (int i = 1; i < 5; i++) {
            x_temp1 += 1;
            y_temp1 -= 1;
            if (y_temp1 < 0 || x_temp1 > this.width) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        // 判断左下
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 0;
        for (int i = 1; i < 5; i++) {
            x_temp1 -= 1;
            y_temp1 += 1;
            if (y_temp1 > this.height || x_temp1 < 0) {
                break;
            }
            if (chessMapShow[x_temp1][y_temp1] == black_or_write) {
                num++;
            } else {
                break;
            }
        }
        if (num > max_temp && num < 5) {
            max_temp = num;
        }
        max_num = max_temp;
        return max_num;
    }

    // 判断输赢,计算机和玩家下完棋之后都要调用的方法。
    public boolean judgeSuccess(int x, int y, boolean isOdd) {
        // 表示棋子在xy上有一颗棋子。
        int num = 1;
        int arrvalue;//是谁下的子。1为黑子,2为白子。
        int x_temp = x, y_temp = y;
        if (isOdd) {
            arrvalue = 2;
        } else {
            arrvalue = 1;
        }
        //设置横纵的两个指针。
        int x_temp1 = x_temp, y_temp1 = y_temp;
        // 判断右边
        for (int i = 1; i < 6; i++) {
            x_temp1 += 1;
            if (x_temp1 > width) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        // 判断左边
        x_temp1 = x_temp;
        for (int i = 1; i < 6; i++) {
            x_temp1 -= 1;
            if (x_temp1 < 0) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        if (num == 5) {
            return true;
        }
        // 判断上面
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 1;
        for (int i = 1; i < 6; i++) {
            y_temp1 -= 1;
            if (y_temp1 < 0) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        // 判断下面
        y_temp1 = y_temp;
        for (int i = 1; i < 6; i++) {
            y_temp1 += 1;
            if (y_temp1 > this.height) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        if (num == 5) {
            return true;
        }
        // 判断左上
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 1;
        for (int i = 1; i < 6; i++) {
            x_temp1 -= 1;
            y_temp1 -= 1;

            if (y_temp1 < 0 || x_temp1 < 0) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        // 判断右下
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        for (int i = 1; i < 6; i++) {
            y_temp1 += 1;
            x_temp1 += 1;
            if (y_temp1 > this.height || x_temp1 > this.width) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        if (num == 5) {
            return true;
        }
        // 判断右上
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        num = 1;
        for (int i = 1; i < 6; i++) {
            x_temp1 += 1;
            y_temp1 -= 1;

            if (y_temp1 < 0 || x_temp1 > this.width) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        // 判断左下
        x_temp1 = x_temp;
        y_temp1 = y_temp;
        for (int i = 1; i < 6; i++) {
            y_temp1 += 1;
            x_temp1 -= 1;
            if (y_temp1 > this.height || x_temp1 < 0) {
                break;
            }
            if (this.chessMapShow[x_temp1][y_temp1] == arrvalue) {
                num++;
            } else {
                break;
            }
        }
        if (num == 5) {
            return true;
        }
        return false;
    }

    // 显示赢了之后的界面
    public void showSuccess(JPanel jp) {
        JOptionPane.showMessageDialog(jp, "你赢了,你好厉害", "win", JOptionPane.INFORMATION_MESSAGE);
    }

    // 显示输了之后的界面
    public void showDefeat(JPanel jp) {
        JOptionPane.showMessageDialog(jp, "你输了,好遗憾", "you lose", JOptionPane.INFORMATION_MESSAGE);
    }

    // 计算机走棋,使用穷举法计算每一个做标点的上下左右四个方向的最大棋子数,最后得出棋子数最大值的坐标,下子
    public void computerUpchess(int width, int height) {
        int max_black, max_write, max_temp, max = 0;
        setIsOdd(true);// 先交换棋手,不然永远都是计算机下棋了,永远都是白子。true黑子才是黑子,是玩家下棋。
        System.out.println("计算机走棋。。。。");
        for (int i = 0; i <= this.width; i++) {
            for (int j = 0; j <= this.height; j++) {
                // 双重循环的中,如这一点上子多,就堵住
                if (!chessExist(i, j)&&!overMap(i, j)) {// 判断是否下棋
                    max_write = checkMax(i, j, 2);// 判断白子的最大值
                    max_black = checkMax(i, j, 1);
                    //把白子和黑子的最大值付给max_temp变量。
                    max_temp = Math.max(max_write, max_black);
                    if (max_temp > max) {
                        //把最佳下子位置记录下来。
                        max = max_temp;
                        this.x = i;
                        this.y = j;
                    }
                }
            }
        }
        //下完棋一定要设置自己下棋的位置,为了计算机下棋之后判断输赢用。
        //计算机下完棋之后,调用getX和getY来判断计算机输赢。
        setX(this.x);
        setY(this.y);
        //下白子。
        chessMapShow[this.x][this.y] = 2;
    }

}

下面是为了界面化面板类的代码:实现了点击下棋和画出棋盘和棋子。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.color.CMMException;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * @author 王爷 此类主要是完成如下的功能 1.构建一个面板,并在面板上画棋盘。 2.处理该面板上的事件
 */
public class ChessPanel extends JPanel implements MouseListener, MouseMotionListener {

    // 棋盘的高度和宽度
    private int width, height;
    // 为了从核心类获取棋盘的信息来画数组,这里设置一个引用。在构造方法里传入对象。
    private GoGame goGame;

    // 构造方法,传入核心对象,并从核心对象获取高度和宽度的属性。
    public ChessPanel(GoGame goGame) {
        this.goGame = goGame;
        this.width = goGame.getWidth();
        this.height = goGame.getHeight();
        addMouseListener(this);// 为整个花瓣添加点击事件。
    }

    // 设置gogame的高度和宽度
    public void setGoGame(GoGame goGame) {
        this.goGame = goGame;
        width = goGame.getWidth();
        height = goGame.getHeight();
    }

    // 根据坐标计算出棋盘每一个棋格的信息(如是黑子还是白子)
    // 然后调用draw方法上画出棋子。draw之后自己定义。
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 画出出边界之外 的棋盘。遍历数组时一定要从0开始便利,
        //不然计算机下棋不会显示,自己下棋也不能下在第一列和第一行!!!我调试过很久才调出来。
        //忘要参考的读者莫要饭错误
        for (int i = 0; i <= this.width; i++) {
            for (int j = 0; j <= this.height; j++) {
                int v = goGame.getChessMapShow()[i][j];
                // i是横坐标,j是纵坐标。
                draw(g, i, j, v);
            }
        }
    }

    // 根据提供的xy坐标画出棋子和棋盘。
    private void draw(Graphics g, int i, int j, int v) {
        //背景随便什么颜色都行,如果用常量值不爽,可以自己实例化一个Color对象出来,然后传入rgb数值。
        setBackground(Color.CYAN);
        // 这样画的棋盘就不会从面板边缘开始。
        int x = 20 * i + 20;
        int y = 20 * j + 20;
        // 先把画布都画成白色的矩形框。
        if (i != width && j != height) {
            g.setColor(Color.white);
            g.fillRect(x, y, 20, 20);
            g.setColor(Color.BLACK);
            g.drawRect(x, y, 20, 20);
        }
        // 画黑子
        if (v == 1) {
            g.setColor(Color.black);
            g.fillOval(x - 8, y - 8, 16, 16);
            g.setColor(Color.gray);
            // 绘制椭圆,分别根据左上角的横纵坐标,椭圆的高度和宽度椭圆
            g.drawOval(x - 8, y - 8, 16, 16);
        }
        // 画白子
        if (v == 2) {
            g.setColor(Color.white);
            g.fillOval(x - 8, y - 8, 16, 16);
            g.setColor(Color.gray);
            g.drawOval(x - 8, y - 8, 16, 16);
        }
        if (v == 3) {
            // 设置为青色
            g.setColor(Color.cyan);
            g.drawOval(x - 8, y - 8, 16, 16);
        }
    }

    // 棋盘画布的点击事件
    @Override
    public void mousePressed(MouseEvent e) {
        // 获取鼠标点击的坐标xy
        // 因为在ChessBoard类中的MapSize()方法中,高度和宽度是width*20+50和height*20+100,所以坐标要除以20
        // 而在画棋子的时候,我们为了让边缘不是在窗口的界面边缘,我们加上了一个矩形的宽度,所以下棋时要减去半个矩形的宽度。
        int x = (e.getX() - 10) / 20;
        int y = (e.getY() - 10) / 20;
        System.out.println("横坐标:" + x + "纵坐标:" + y);
        // 如果获取的是鼠标的事件的掩码。则下棋
        if (e.getModifiers() == MouseEvent.BUTTON1_MASK) {
            goGame.upChess(x, y);
        }
        System.out.println(goGame.getIsOdd() + "" + goGame.getChessMapShow()[x][y]);
        repaint();
        // 下完棋之后我,我们根据这个坐标来判断玩家的输赢
        // 用户判断输赢时是根据鼠标获取的位置对映的数组坐标来判断的。
        if (goGame.judgeSuccess(x, y, goGame.getIsOdd())) {
            goGame.showSuccess(this);
            // 不能让鼠标继续下棋了。鼠标点击面板没有用了。所以销毁传入的鼠标对象
            e.consume();
            // 把状态量改为false,表示不是计算机下棋。
            ChessBoard.isComputer = false;
        }
        // 判断是否为人机对弈,如果是人机对弈而且棋子不存在。,就计算机下棋
        if (ChessBoard.isComputer && !goGame.getIsExist()) {
            goGame.computerUpchess(goGame.getWidth(), goGame.getHeight());
            repaint();
            // 计算机下棋,他会记录自己下的坐标,所以在判断输赢时,要用getX和getY方法判断。
            System.out.println(goGame.getIsOdd());
            System.out.println(goGame.getX()+" "+goGame.getY());
            if (goGame.judgeSuccess(goGame.getX(), goGame.getY(), goGame.getIsOdd())) {
                goGame.showDefeat(this);
                // 计算机赢了也不能下棋了。所以销毁传入的鼠标对象
                e.consume();
            }
        }
    }

    // 鼠标拖动事件
    @Override
    public void mouseMoved(MouseEvent e) {
        int x = (e.getX() - 10) / 20;
        int y = (e.getY() - 10) / 20;
        // 鼠标移动到哪一点,数组就会响应的变为可以下棋状态。
        goGame.readyUp(x, y);
        repaint();
    }

    // 显示赢了之后的界面
    public void showSuccess(JPanel jp) {
        JOptionPane.showMessageDialog(jp, "你赢了,你好厉害", "win", JOptionPane.INFORMATION_MESSAGE);
    }

    // 显示输了之后的界面
    public void showDefeat(JPanel jp) {
        JOptionPane.showMessageDialog(jp, "你输了,好遗憾", "you lose", JOptionPane.INFORMATION_MESSAGE);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

}

下面是窗口类。用于实现窗口话和点击菜单会激发不同的事件。如:关闭窗口时系统也退出。游戏棋盘的选择,游戏模式的选择。游戏窗口视图的选择。

import java.awt.Container;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

//这个类主要是加载五子棋的整个窗口以及菜单
public class ChessBoard extends JFrame implements ActionListener {

    // 可选的棋盘大小
    private String[] strSize = { "20*15", "30*20", "40*30" };
    // 可选的对战模式
    private String[] strModel = { "人机对战", "人人对战" };
    // 用连个boolean 来判断是人机还是人人,isComputer和checkcomputer为true是为了默认开局方式为人机。
    public static boolean isComputer = true, checkComputer = true;
    // 窗口的宽和高
    private int height, width;
    // 核心类对象
    private GoGame goGame;
    // 棋盘对象
    private ChessPanel chessPanel;

    // 构造五子棋的窗体
    public ChessBoard() {
        this.setTitle("五子棋---个人制作");
        // 初始化核心类的对对象。
        goGame = new GoGame(1);
        // 使用核心类,初始化面板对象。
        chessPanel = new ChessPanel(goGame);
        // 获取本窗口的容器。
        Container con = this.getContentPane();
        // 容器里加入面板,并设置布局为中心。
        con.add(chessPanel, "Center");
        //把窗口设置为大小不可调整。
        this.setResizable(false);
        //添加一个窗口监听事件,主要是实现按关闭按钮能够关闭系统,退出虚拟机。为了精简代码,这里使用了匿名内部类。
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        // 先使用类内部的设置窗口的方法来初始化窗口大小
        this.MapSize(20, 15);
        // 创建窗口的菜单条,一方便
        JMenuBar mbar = new JMenuBar();
        this.setJMenuBar(mbar);
        // 创建游戏菜单
        JMenu gameMenu = new JMenu("游戏");
        // 将菜单加入到菜单条,自己创建一个方法反回一个已经构造好的菜单。加在菜单条上。
        mbar.add(makeMenu(gameMenu, new Object[] {
                "开局", "棋盘", "模式", null, "退出" }, this));
        // 创建视图菜单
        JMenu lookMenu = new JMenu("视图");
        // 将菜单添加到菜单条
        mbar.add(makeMenu(lookMenu, new Object[] { 
                "Metal", "Motif", "Windows" }, this));
        // 创建帮助菜单
        JMenu helpMenu = new JMenu("帮助");
        // 将菜单添加到菜单条
        mbar.add(makeMenu(helpMenu, new Object[] { 
                "关于" }, this));

    }

    // 获取人机iscompputer
    public boolean getIsComputer() {
        return this.isComputer;
    }

    // 构造五子棋的主菜单,第一步是要创建一个菜单的引用,以便之后创建菜单实例返回。
    public JMenu makeMenu(Object parent, Object items[], Object target) {
        //创建一个菜单引用。
        JMenu m = null;
        //如果传入的本来就是菜单,则直接强制转换。如果是字符串,则使用字符创建菜单。
        if (parent instanceof JMenu) {
            m = (JMenu) parent;
        } else if (parent instanceof String) {
            m = new JMenu((String) parent);
        } else {
            return null;
        }
        //下面是为菜单构建菜单项。还是使用方法返回。
        for (int i = 0; i < items.length; i++) {
            if (items[i] == null) {
                m.addSeparator();
            } else if (items[i] == "棋盘") {
                JMenu jm = new JMenu("棋盘");
                ButtonGroup group = new ButtonGroup();
                JRadioButtonMenuItem rmenu;
                for (int j = 0; j < strSize.length; j++) {
                    rmenu = makeRadioButtonMenuItem(strSize[j], target);
                    if (j == 0) {
                        rmenu.setSelected(true);
                    }
                    //先把多按钮加入到菜单中,再把多按钮加入到按钮组里,这样才能实现单选。
                    jm.add(rmenu);
                    group.add(rmenu);
                }
                m.add(jm);
            } else if (items[i] == "模式") {
                JMenu jm = new JMenu("模式");
                ButtonGroup group = new ButtonGroup();
                JRadioButtonMenuItem rmenu;
                for (int h = 0; h < strModel.length; h++) {
                    rmenu = makeRadioButtonMenuItem(strModel[h], target);
                    if (h == 0) {
                        rmenu.setSelected(true);
                    }
                    jm.add(rmenu);
                    group.add(rmenu);
                }
                //记住,一定要是加入菜单条里的菜单
                m.add(jm);
            } else {
                //如果菜单项没有在包含多选项,则用方法直接构造一个菜单项返回并添加到菜单里。
                m.add(makeMenuItem(items[i], target));
            }
        }
        return m;
    }

    // 构造五子棋的菜单项,构造方法和上面构造菜单的不部分类似。不过 得添加监听事件
    private JMenuItem makeMenuItem(Object item, Object target) {
        JMenuItem menuItem = null;
        if (item instanceof String) {
            menuItem = new JMenuItem((String) item);
        } else if (item instanceof JMenuItem) {
            menuItem = (JMenuItem) item;
        } else {
            return null;
        }
        if (target instanceof ActionListener) {
            menuItem.addActionListener((ActionListener) target);
        }
        return menuItem;
    }

    // 构造五子棋的单选按钮式菜单项,和上面的方法非常类似。不再赘述。
    private JRadioButtonMenuItem makeRadioButtonMenuItem(Object item, Object target) {
        JRadioButtonMenuItem jRadioButtonMenuItem = null;
        if (item instanceof String) {
            jRadioButtonMenuItem = new JRadioButtonMenuItem((String) item);
        } else if (item instanceof JRadioButtonMenuItem) {
            jRadioButtonMenuItem = (JRadioButtonMenuItem) item;
        } else {
            return null;
        }
        if (target instanceof ActionListener) {
            jRadioButtonMenuItem.addActionListener((ActionListener) target);
        }
        return jRadioButtonMenuItem;
    }

    // 设置界面大小
    public void MapSize(int w, int h) {
        //这里设置的宽度和高度,和鼠标点击时获取坐标值有很大的关联。
        setSize(w * 20 + 50, h * 20 + 100);
        if (this.checkComputer) {
            this.isComputer = true;
        } else {
            this.isComputer = false;
        }
        chessPanel.setGoGame(goGame);
        chessPanel.repaint();
    }

    // 重新开始
    public void restart() {
        int modelChess = goGame.getChessModel();
        if (modelChess <= 3 && modelChess >= 1) {
            goGame = new GoGame(modelChess);
            MapSize(goGame.getWidth(), goGame.getHeight());
        } else {
            System.out.println("\u81EA\u5B9A\u4E49");
        }
    }

    @Override
    // 实现ActionListenner的主要方法。
    public void actionPerformed(ActionEvent e) {
        String arg = e.getActionCommand();
        try {
            if (arg.equals("Windows")) {
                UIManager.setLookAndFeel(
                        "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            } else if (arg.equals("Motif")) {
                UIManager.setLookAndFeel(
                        "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
            } else {
                UIManager.setLookAndFeel(
                        "javax.swing.plaf.metal.MetalLookAndFeel");
            }
            SwingUtilities.updateComponentTreeUI(this);
        } catch (Exception e2) {
        }
        if (arg.equals("20*15")) {
            this.width = 20;
            this.height = 15;
            goGame = new GoGame(1);
            MapSize(this.width, this.height);
            SwingUtilities.updateComponentTreeUI(this);

        }
        if (arg.equals("30*20")) {
            this.width = 30;
            this.height = 20;
            goGame = new GoGame(2);
            MapSize(this.width, this.height);
            SwingUtilities.updateComponentTreeUI(this);

        }
        if (arg.equals("40*30")) {
            this.width = 40;
            this.height = 30;
            goGame = new GoGame(3);
            MapSize(this.width, this.height);
            SwingUtilities.updateComponentTreeUI(this);

        }
        if (arg.equals("人机对弈")) {
            this.checkComputer = true;
            this.isComputer = true;
            goGame = new GoGame(goGame.getChessModel());
            MapSize(goGame.getWidth(),goGame.getHeight());
            SwingUtilities.updateComponentTreeUI(this);
        }
        if (arg.equals("人人对弈")) {
            this.checkComputer = true;
            this.isComputer = true;
            goGame = new GoGame(goGame.getChessModel());
            MapSize(goGame.getWidth(),goGame.getHeight());
            SwingUtilities.updateComponentTreeUI(this);
        }
        if (arg.equals("开局")) {
            restart();
        }
        if (arg.equals("关于")){

            JOptionPane.showMessageDialog(this, "五子棋游戏测试版本", "关于", 0);
        }
        if (arg.equals("退出")) {
            System.exit(0);
        }
    }

}

这里是为了练习项目。为大家提供的代码和注释,应该是一看就能看懂的,非常适合初学者。

五子棋———完美注释版,免费分享!!!

标签:

原文地址:http://blog.csdn.net/a907691592/article/details/51597334

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!