zoukankan      html  css  js  c++  java
  • 实现一个Java五子棋

    五子棋手把手教你写:

    写在前面的话:

    回想起从前初学代码的五子棋简直写的不像样子。今天闲来无事就写了个五子棋的小程序。

    一来呢回忆一下很久以前写代码时的感觉。

    二来呢顺便帮下诸位有需求的学生,顺利的Ctrl+C。

    五子棋的运行效果如下。

    开发环境:

    这个小程序是基于Java实现的。因此呢需要提前安装JDK环境。(老油条忽略此条信息)

    开发环境jdk1.8 + eclipse

    eclipse 目录结构如下所示,就三个类啊。

    棋盘数据结构核心:

    无论你做数据库开发还是做一些小程序,第一时间考虑的必须是需求+建模。把核心设计出来。

    此次我们用一个二维数组作为棋盘,每条线交叉的地方设为二维数组的值,并约定:

    0=空

    1=白棋

    2=黑棋

    然后对应的把下棋,悔棋,判断输赢(横竖斜)和清盘的算法都实现出来。

    具体展现如下:

    悔棋时候我们需要用一个栈来保存我们之前下棋的信息:

    /**
         * 在该位置下棋  1:white 2:black 
         * @param x 横坐标
         * @param y 纵坐标
         * @param var 棋子种类
         * @return 1:white 赢   2:black赢
         */
        public int ChessIt(int x,int y,int var) {
            if(__CanInput(x,y)) {
                core[x][y] =var;
                Chess chess = new Chess(x,y);
                stack.push(chess);
                return checkVictory(x, y, var);
            }
            else return -1;
        }
    
    //悔棋
        public boolean RetChess() {
            if(stack.isEmpty()) return false;
            Chess chess = stack.pop();
            core[chess.x][chess.y]= 0;
            return true;
        }

    总体:Core.java 的代码如下·:

    package main;
    
    import java.util.Stack;
    
    /**
     * @author GodofOrange
     *    棋盘数据结构
     */
    public class Core {
        //棋盘大小
        private int[][] core;
        private int x;
        private int y;
        //记录下棋的类
        class Chess{
            int x;
            int y;
            public Chess(int x,int y) {
                this.x=x;
                this.y=y;
            }
        }
        //
        Stack<Chess> stack;
        //构造方法
        public Core(int x,int y) {
            stack = new Stack<>();
            core = new int[x][y];
            this.x=x;
            this.y=y;
        }
        //检查该地是否有空位置
        private boolean __CanInput(int x,int y) {
            if(core[x][y]==0) return true;
            else return false;
        }
        //判断输赢
        private int checkVictory(int x,int y,int var) {
            //横向判断
            int trans = 0;
            for(int i=x-4;i<x+5;i++) {
                if(i<0||i>=this.x) continue;
                if(core[i][y]==var) {
                    trans++;
                }
                else {
                    trans=0;
                }
                if(trans==5) return var;
            }
            //纵向判断
            int longitudinal = 0;
            for(int i=y-4;i<y+5;i++) {
                if(i<0||i>=this.y) continue;
                if(core[x][i]==var) {
                    longitudinal++;
                }
                else {
                    longitudinal=0;
                }
                if(longitudinal==5) return var;
            }
            //从左上到右下
            int leftUPToDown = 0;
            for(int i=x-4,j=y+4;i<x+5&&j>y-5;i++,j--) {
                if(i<0||i>=this.x||j<0||j>=this.y) continue;
                if(core[i][j]==var) {
                    leftUPToDown++;
                }else {
                    leftUPToDown=0;
                }
                if(leftUPToDown==5) return var;
            }
            //从左下到右上
            int leftDownToUP = 0;
            for(int i=x+4,j=y+4;i>x-5&&j>y-5;i--,j--) {
                if(i<0||i>=this.x||j<0||j>=this.y) continue;
                if(core[i][j]==var) {
                    leftDownToUP++;
                }else {
                    leftDownToUP=0;
                }
                if(leftDownToUP==5) return var;
            }
            return 0;
        }
        /**
         * 在该位置下棋  1:white 2:black 
         * @param x 横坐标
         * @param y 纵坐标
         * @param var 棋子种类
         * @return 1:white 赢   2:black赢
         */
        public int ChessIt(int x,int y,int var) {
            if(__CanInput(x,y)) {
                core[x][y] =var;
                Chess chess = new Chess(x,y);
                stack.push(chess);
                return checkVictory(x, y, var);
            }
            else return -1;
        }
        //悔棋
        public boolean RetChess() {
            if(stack.isEmpty()) return false;
            Chess chess = stack.pop();
            core[chess.x][chess.y]= 0;
            return true;
        }
        //获得棋盘状态
        public int[][] getCore(){
            return this.core;
        }
        //重新开始
        public void Restart() {
            for(int i=0;i<this.x;i++) {
                for(int j=0;j<this.y;j++) {
                    this.core[i][j]=0;
                }
            }
            this.stack.clear();
        }
    }

    Windows的前端代码

     

    在上一步我们把一个五子棋的数据结构实现了之后,我们下一步就需要用JavaSwing的知识来画前端。

    首先我们定义一个类来继承JFrame,从而包含JFrame的所有功能。

    以下是JFrame常用的方法。

    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭JFrame时运行System.exit(0)
    jFrame.setLocationRelativeTo(null);//屏幕中央显示
    jFrame.setVisible(true);//可见

    其次我们需要单击屏幕进行下棋,所以我们需要符合鼠标单击事件的接口。因此我们去接上MouseListener的接口。

    再然后我们重写JFrame里的paint方法来画画。

    具体体现:如下

    其中横线和竖线都是调用的Graphics中的drawLine方法。

    画圈圈用的是drawOval和fillOval分别是画空心圆和画实心圆。

    @Override
        public void paint(Graphics g) {
            // TODO Auto-generated method stub
            super.paint(g);
            //
            for (int i = 0; i < 19; i++)
                g.drawLine(30, 30 + i * 30, 570, 30 + i * 30);
            // 竖线
            for (int i = 0; i < 19; i++)
                g.drawLine(30 + i * 30, 60, 30 + i * 30, 570);
    
            int[][] board = core.getCore();
            for (int i = 0; i < 19; i++) {
                for (int j = 0; j < 19; j++) {
                    if (board[i][j] == 1)
                        g.drawOval(20 + i * 30, 50 + j * 30, 20, 20);
                    if(board[i][j]==2)
                        g.fillOval(20+i*30, 50+j*30, 20, 20);
                }
            }
            g.drawRect(690,60, 50, 30);
            g.drawString("悔棋",700,80);
            g.drawRect(690,120,50, 30);
            g.drawString("开始",700,140);
            g.drawRect(690,180,50, 30);
            g.drawString("设置",700,200);
            g.drawString("Code by 秃桔子 QQ:1243137612", 600,260);
        }

    再然后我们需要确定每次鼠标单击的事件和信息。

    具体实现如下:

    @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub
            if (e.getX() < 570 && e.getY() < 570) {
                int a = core.ChessIt(_CgetX(e.getX()), (_CgetY(e.getY())), var);
                this.repaint();
                if (a == 1) {
                    JOptionPane.showMessageDialog(null,"白的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
                }
                if(a==2) {
                    JOptionPane.showMessageDialog(null,"黑的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
                }
                if(a!=-1) {
                    if(var==1) var=2;
                    else if(var==2) var=1;
                }
            }
            else if(e.getX()>690&&e.getX()<760&&e.getY()>60&&e.getY()<90) {
                core.RetChess();
                if(var==1) var=2;
                else if(var==2) var=1;
                this.repaint();
            }
            if(e.getX()>690&&e.getX()<760&&e.getY()>120&&e.getY()<150) {
                core.Restart();
                this.repaint();
            }
            if(e.getX()>690&&e.getX()<760&&e.getY()>180&&e.getY()<210) {
                Object[] options = {"白先","黑先"};
                int n = JOptionPane.showOptionDialog(null,"红先还是黑先?","游戏设置",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null,options,options[0]);
                if(n==0) this.var=1;
                if(n==1) this.var=2;
                this.core.Restart();
                this.repaint();
            }
        }

    再然后每次单击的时候进行repaint重绘将代码重写出来。

    这些东西我也不记得,看api就好了。

    下面是总体源码:

    package main;
    
    import java.awt.Graphics;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    /**
     * 
     * @author GodofOrange
     * @see 图形界面
     */
    public class Windows extends JFrame implements MouseListener {
        public Core core;
        private static final long serialVersionUID = 1L;
        private int var = 1;
        public Windows(String title) {
            super(title);
            core = new Core(19, 19);
            this.setSize(800, 600);
            this.setLocation(800, 300);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setVisible(true);
            this.setResizable(false);
            this.addMouseListener(this);
        }
    
        @Override
        public void paint(Graphics g) {
            // TODO Auto-generated method stub
            super.paint(g);
            //
            for (int i = 0; i < 19; i++)
                g.drawLine(30, 30 + i * 30, 570, 30 + i * 30);
            // 竖线
            for (int i = 0; i < 19; i++)
                g.drawLine(30 + i * 30, 60, 30 + i * 30, 570);
    
            int[][] board = core.getCore();
            for (int i = 0; i < 19; i++) {
                for (int j = 0; j < 19; j++) {
                    if (board[i][j] == 1)
                        g.drawOval(20 + i * 30, 50 + j * 30, 20, 20);
                    if(board[i][j]==2)
                        g.fillOval(20+i*30, 50+j*30, 20, 20);
                }
            }
            g.drawRect(690,60, 50, 30);
            g.drawString("悔棋",700,80);
            g.drawRect(690,120,50, 30);
            g.drawString("开始",700,140);
            g.drawRect(690,180,50, 30);
            g.drawString("设置",700,200);
            g.drawString("Code by 秃桔子 QQ:1243137612", 600,260);
        }
    
        @Override
        public void mouseClicked(MouseEvent arg0) {
    
        }
    
        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub
            if (e.getX() < 570 && e.getY() < 570) {
                int a = core.ChessIt(_CgetX(e.getX()), (_CgetY(e.getY())), var);
                this.repaint();
                if (a == 1) {
                    JOptionPane.showMessageDialog(null,"白的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
                }
                if(a==2) {
                    JOptionPane.showMessageDialog(null,"黑的赢了", "恭喜", JOptionPane.DEFAULT_OPTION);;
                }
                if(a!=-1) {
                    if(var==1) var=2;
                    else if(var==2) var=1;
                }
            }
            else if(e.getX()>690&&e.getX()<760&&e.getY()>60&&e.getY()<90) {
                core.RetChess();
                if(var==1) var=2;
                else if(var==2) var=1;
                this.repaint();
            }
            if(e.getX()>690&&e.getX()<760&&e.getY()>120&&e.getY()<150) {
                core.Restart();
                this.repaint();
            }
            if(e.getX()>690&&e.getX()<760&&e.getY()>180&&e.getY()<210) {
                Object[] options = {"白先","黑先"};
                int n = JOptionPane.showOptionDialog(null,"红先还是黑先?","游戏设置",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null,options,options[0]);
                if(n==0) this.var=1;
                if(n==1) this.var=2;
                this.core.Restart();
                this.repaint();
            }
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub
    
        }
    
        private int _CgetX(int x) {
            x -= 30;
            if (x % 15 <= 7)
                return x / 30;
            else
                return x / 30 + 1;
        }
    
        private int _CgetY(int y) {
            y -= 60;
            if (y % 15 <= 7)
                return y / 30;
            else
                return y / 30 + 1;
        }
    }

    然后就是启动函数了

    这个函数放哪都行-.-。。。。。一看就懂吧?

    package main;
    
    public class Main {
        /** 启动函数
         * @param args
         */
        public static void main(String[] args) {
            new Windows("五子棋");
        }
    }

    总结:

    其实五子棋的小程序对于初学者来说并不简单。不适合做练手项目,不过当代码量积累到一定程度,写这个小程序简直不要太轻松。完成起来分分钟钟。一定要打好数据结构的基础并加大代码量。

  • 相关阅读:
    HDU4529 郑厂长系列故事——N骑士问题 —— 状压DP
    POJ1185 炮兵阵地 —— 状压DP
    BZOJ1415 聪聪和可可 —— 期望 记忆化搜索
    TopCoder SRM420 Div1 RedIsGood —— 期望
    LightOJ
    LightOJ
    后缀数组小结
    URAL
    POJ3581 Sequence —— 后缀数组
    hdu 5269 ZYB loves Xor I
  • 原文地址:https://www.cnblogs.com/godoforange/p/10935821.html
Copyright © 2011-2022 走看看