• Java.awt实现一个简单的围棋


    此文转载自:https://blog.csdn.net/Krumitz/article/details/110236045

    目录

    0.前言

    1.概述

    2.结构

    3.代码实现

    3.1 main

    3.1.1 main.Main

    3.2 stone

    3.2.1 stone.Stone 棋子类

    3.3 player

    3.3.1 player.Player 棋手类

    3.4 draw

    3.4.1 draw.BackGround 背景类

    3.4.2 draw.ChessPad 棋盘类

    3.4.3 draw.Place 落子类

    3.4.4 draw.TeNum 手数类

    3.4.5 draw.HighLight 高亮类

    3.5 rules

    3.5.1 rules.AlreadyHadStone 判断已有子

    3.5.2 rules.Inboard 判断棋盘内

    3.5.3 rules.Liberty 判断有气

    3.5.4 rules.Take 判断提子

    4. 小结


    0.前言

    我小时候学过一段时间的围棋,可惜脑子不好使,是个臭棋篓子,到现在也有十多年的时间没有下过棋了,但是近几年围棋AI的出现,又让我重新关注了围棋

    围棋真的很有意思,千变万化,有人简明的围空,有人进行复杂的战斗,在高手的对局里,一手棋都会对全局产生十分大的影响

    最近上班摸鱼,闲来无事,打开了IDEA,想着写一个围棋程序

    选择使用Java的原因完全是因为这台电脑的Visual Studio打开太卡了,其实感觉可能用C++或者C#写会更好一点

    网上关于围棋基础规则的文章不是很多,基本都是讲述围棋AI的实现,因此在完成了这个简单的围棋小游戏之后,特此记录一下


    1.概述

    这里先说明本文实现的内容,本文实现了绘制棋盘、黑白两棋交替落子、标记手数、提子、高亮最后一手棋的功能

    交替落子只实现了在棋盘内不能落在有子的交叉点的判断

    没有实现对打劫、自杀的判断(其实自杀的判断好像加一两行if判断就好了,但是临近周五下班,赶紧写了一篇记录出来,有兴趣的读者可以自己实现)

    提子的算法是参考

    深度优先搜索及python实现围棋“吃子”

    的算法实现

    他讲提子描述为一个迷宫问题,将相领的相同颜色的棋子视为通路,将不同颜色的棋子视为“墙”,用深度优先搜索算法,只要能搜索出出口,便是有气

    这应该是本文中最难实现的一个部分了,其他部分都很简单

    不过我的代码中,有些代码在打完之后让我觉得自己很愚蠢,在一开始没有计划好,后来为了不把“屎山”推倒重来,还引入了一些三维数组来实现功能

    如果想看其他内容的话,可以去搜索其他的文章了,没必要看这篇入门级的文章


    2.结构

    我的项目结构如下,其中有些英文是网上查来的,可能不够标准

    draw中实现绘图类,跟绘图有关的实现在该包中

    BackGround类是一个Frame

    ChessPad类是一个Frame里的Panel,绘制了棋盘

    HighLight类实现了高亮最后一手的功能

    Place类实现了绘制落子、提子

    TeNum类实现了绘制手数

    main中Main只简单创建BackGround

    player中的Player类存储对局棋手的信息,只有两个简单的属性,棋子的颜色和是否轮到他下

    stone的Stone类只有一个简单的属性,就是棋子的颜色----黑、白、无

    rules中实现了一些简单落子规则的判断

    AlreadyHadStone判断该落子点是否已有子

    InBoard判断落子点是否在棋盘内

    Ko本来想实现打劫的判断,但是还没有实现

    Liberty判断是否有气

    Take通过Liberty判断是否有气,进而判断是否可以提子

    详细的描述在代码注释中,这里不过多赘述


    3.代码实现

    3.1 main

    3.1.1 main.Main

    package com.krumitz.main;
    
    import com.krumitz.draw.BackGround;
    import com.krumitz.player.Player;
    
    public class Main {
    
        public static void main(String args[]){
            //调用创建棋盘
            new BackGround();
    
        }
    
    }
    

    3.2 stone

    3.2.1 stone.Stone 棋子类

    package com.krumitz.stone;
    
    /**
     * 棋子类
     */
    public class Stone {
    
        public enum StoneColor
        {
            BLACK,WHITE,NONE
        }
    
        private StoneColor stoneColor;
    
        public Stone()
        {
            this.stoneColor = StoneColor.NONE;
        }
    
        public void setStoneColor(StoneColor stoneColor)
        {
            this.stoneColor = stoneColor;
        }
    
        public StoneColor getStoneColor()
        {
            return  this.stoneColor;
        }
    }
    

    3.3 player

    3.3.1 player.Player 棋手类

    package com.krumitz.player;
    
    
    import com.krumitz.stone.Stone;
    
    public class Player {
    
        private Stone stone;
        private boolean isMoving;
    
        public Player()
        {
            stone = new Stone();
            stone.setStoneColor(Stone.StoneColor.NONE);
            this.isMoving = false;
        }
    
        public Stone getStone() { return this.stone; }
    
        public void setStone(Stone.StoneColor stoneColor){ this.stone.setStoneColor(stoneColor); }
    
        public boolean getIsMoving()
        {
            return this.isMoving;
        }
    
        public void setIsMoving(boolean isMoving)
        {
            this.isMoving = isMoving;
        }
    
    }
    

    3.4 draw

    3.4.1 draw.BackGround 背景类

    package com.krumitz.draw;
    
    import java.awt.*;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    
    public class BackGround extends Frame {
    
        ChessPad chessPad;
    
        public BackGround()
        {
            chessPad = new ChessPad();
            this.add(chessPad);
            this.setSize(600,600);
            this.setVisible(true);
            this.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
        }
    
    }
    

    3.4.2 draw.ChessPad 棋盘类

    package com.krumitz.draw;
    
    import com.krumitz.player.Player;
    import com.krumitz.rules.AlreadyHadStone;
    import com.krumitz.rules.InBoard;
    import com.krumitz.rules.Take;
    import com.krumitz.stone.Stone;
    
    import java.awt.*;
    import java.awt.event.*;
    
    public class ChessPad extends Panel implements MouseListener, ActionListener {
    
        /**
         * 声明Player类存储棋手下棋顺序
         * 声明落子绘图类用于绘制棋子
         * 声明teNum类用于绘制手数
         * 声明highLight高亮最后一手
         * 声明19*19 move数组,存储已落子的信息
         * 声明teNum记录手数
         * 声明move_teNum 记录每一个坐标的棋子是第几手棋
         * 声明上一手的坐标last_coordinate_x,last_coordinate_y
         */
        Player BLACK_PLAYER ;
        Player WHITE_PLAYER ;
        Place BLACK_STONE;
        Place WHITE_STONE;
        TeNum class_teNum;
        HighLight highLight;
        Stone.StoneColor move[][] ;
        int teNum;
        int move_teNum[][][];
        int last_coordinate_x,last_coordinate_y;
    
        /**
         *构造棋盘大小、背景、鼠标监听器
         */
        ChessPad()
        {
            // 初始化执黑棋手
            BLACK_PLAYER = new Player();
            BLACK_PLAYER.setIsMoving(true);
            BLACK_PLAYER.setStone(Stone.StoneColor.BLACK);
            // 初始化执白棋手
            WHITE_PLAYER = new Player();
            WHITE_PLAYER.setIsMoving(false);
            WHITE_PLAYER.setStone(Stone.StoneColor.WHITE);
            // 初始化手数类
            class_teNum = new TeNum();
            // 初始化高亮最后一手类
            highLight = new HighLight();
            // 初始化黑棋、白棋
            BLACK_STONE = new Place(this);
            WHITE_STONE = new Place(this);
            // 初始化棋谱数组、手数数组
            move = new Stone.StoneColor[19][19];
            move_teNum = new int[19][19][1];
            for (int i = 0; i < 19; i++)
            {
                for (int j = 0; j < 19; j++)
                {
                    move[i][j] = Stone.StoneColor.NONE;
                    move_teNum[i][j][0] = -1;
                }
            }
            //初始化手数、最后一手的坐标
            teNum = 1;
            last_coordinate_x = 0;
            last_coordinate_y = 0;
            this.add(BLACK_STONE);
            this.add(WHITE_STONE);
            this.add(class_teNum);
            this.setSize(600,600);
            this.setLayout(null);
            this.setBackground(Color.ORANGE);
            this.addMouseListener(this);
        }
    
        /**
         * 画棋盘的线和点
         * @param g
         */
        public void paint(Graphics g)
        {
            for (int i = 45; i <= 495; i += 25)
            {
                g.drawLine(i, 45, i, 495);
            }
            for (int i = 45; i <= 495; i += 25)
            {
                g.drawLine(45, i, 495, i);
            }
            //D16
            g.fillOval(116,116,8,8);
            //Q4
            g.fillOval(416,416,8,8);
            //D4
            g.fillOval(116,416,8,8);
            //Q16
            g.fillOval(416,116,8,8);
            //D10
            g.fillOval(116,266,8,8);
            //K16
            g.fillOval(266,116,8,8);
            //Q10
            g.fillOval(416,266,8,8);
            //K4
            g.fillOval(266,416,8,8);
            //天元
            g.fillOval(266,266,8,8);
    
        }
    
        /**
         * 按下鼠标,调用落子类绘图方法
         * @param mouseEvent
         */
        @Override
        public void mouseClicked(MouseEvent mouseEvent)
        {
            if((mouseEvent.getModifiers() == InputEvent.BUTTON1_MASK))
            {
                // 这里减数是棋子的宽度、高度的一半 -- 10
                int x = (int)mouseEvent.getX()-10;
                int y = (int)mouseEvent.getY()-10;
                // 这里先求余、相减、再除
                // 求余数和除数是棋盘每路之间的宽度 -- 25
                // 得到的是棋盘坐标
                // -1 为了跟数组对应
                int coordinate_x = (x-(x%25))/25-1;
                int coordinate_y = (y-(y%25))/25-1;
                // 这里用棋盘坐标乘以棋盘每路之间的宽度 -- 25
                // 再加上棋子的宽度、高度的一半 -- 10
                // 得到的是落子类绘图方法需要的坐标
                int place_x = (coordinate_x+1)*25 + 10;
                int place_y = (coordinate_y+1)*25 + 10;
                // 判断是否在棋盘内
                if(InBoard.ifInBoard(coordinate_x,coordinate_y))
                {
                    if(!AlreadyHadStone.ifAlreadyHadStone(move,coordinate_x,coordinate_y))
                    {
                        // 黑棋
                        if(this.BLACK_PLAYER.getIsMoving())
                        {
                            // 落子、绘图
                            Place.placeStone(this.BLACK_PLAYER,place_x, place_y, this.getGraphics());
                            // 绘制手数
                            class_teNum.drawTeNum(place_x,place_y,teNum,this.BLACK_PLAYER.getStone().getStoneColor(),this.getGraphics());
                            // 设置有子
                            move[coordinate_x][coordinate_y] = this.BLACK_PLAYER.getStone().getStoneColor();
                        }
                        // 白棋
                        if(this.WHITE_PLAYER.getIsMoving())
                        {
                            // 落子、绘图
                            Place.placeStone(this.WHITE_PLAYER,place_x, place_y, this.getGraphics());
                            // 绘制手数
                            class_teNum.drawTeNum(place_x,place_y,teNum,this.WHITE_PLAYER.getStone().getStoneColor(),this.getGraphics());
                            // 设置有子
                            move[coordinate_x][coordinate_y] = this.WHITE_PLAYER.getStone().getStoneColor();
                        }
                        // 手数加1
                        move_teNum[coordinate_x][coordinate_y][0] = teNum;
                        teNum ++;
                        // 如果可以提子
                        if(Take.takeStones(move,coordinate_x,coordinate_y))
                        {
                            takeStones(this.getGraphics());
                            System.out.println("提子");
                        }
                        else
                        {
                            System.out.println("落子");
                        }
                        // 高亮最后一手,并将倒数第二手的高亮去除
                        highLight.highLightLastStone(coordinate_x,coordinate_y,last_coordinate_x,last_coordinate_y,move,teNum-1,this.getGraphics());
                        last_coordinate_x = coordinate_x;
                        last_coordinate_y = coordinate_y;
                        // 两级反转.表明包
                        BLACK_PLAYER.setIsMoving(!(BLACK_PLAYER.getIsMoving()));
                        WHITE_PLAYER.setIsMoving(!(WHITE_PLAYER.getIsMoving()));
                    }
                    else
                    {
                        System.out.println("已有子");
                    }
                }
                else
                {
                    System.out.println("棋盘外");
                }
            }
    
            if((mouseEvent.getModifiers() == InputEvent.BUTTON3_MASK))
            {
                System.out.println("右键");
            }
        }
    
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
    
        }
    
        @Override
        public void mousePressed(MouseEvent mouseEvent) {
    
        }
    
        @Override
        public void mouseReleased(MouseEvent mouseEvent) {
    
        }
    
        @Override
        public void mouseEntered(MouseEvent mouseEvent) {
    
        }
    
        @Override
        public void mouseExited(MouseEvent mouseEvent) {
    
        }
    
        // 提子
        public void takeStones(Graphics graphics)
        {
            int coordinate_x,coordinate_y,remove_x,remove_y;
            // 获得提子数量
            int length[][] = Take.getLength();
            // 获得提子坐标
            int takeStones[][][] = Take.getTakeStones();
            for(int i=0;i<4;i++)
            {
                // 如果记录的数量不为0,有子可提
                if(length[i][0] != 0)
                {
                    for(int j=0;j<length[i][0];j++)
                    {
                        // 获得要提的子的坐标
                        coordinate_x = takeStones[i][j][0];
                        coordinate_y = takeStones[i][j][1];
                        // 将坐标转换为绘图坐标
                        remove_x = (coordinate_x+1)*25 + 10;
                        remove_y = (coordinate_y+1)*25 + 10;
                        // 去除棋谱上该子
                        move[coordinate_x][coordinate_y] = Stone.StoneColor.NONE;
                        // 提子
                        Place.takeStone(remove_x,remove_y,graphics);
                    }
                }
            }
            // 重绘
            removeAll();
            paint(graphics);
            // 重绘仍在棋盘上的棋子
            for (int i = 0; i < 19; i++)
            {
                for (int j = 0; j < 19; j++)
                {
                    if (move[i][j] == Stone.StoneColor.BLACK)
                    {
                        Place.placeStone(this.BLACK_PLAYER,((i+1)*25 + 10),((j+1)*25 + 10),this.getGraphics());
                        class_teNum.drawTeNum(((i+1)*25 + 10),((j+1)*25 + 10),move_teNum[i][j][0],move[i][j],this.getGraphics());
                    }
                    if (move[i][j] == Stone.StoneColor.WHITE)
                    {
                        Place.placeStone(this.WHITE_PLAYER,((i+1)*25 + 10),((j+1)*25 + 10),this.getGraphics());
                        class_teNum.drawTeNum(((i+1)*25 + 10),((j+1)*25 + 10),move_teNum[i][j][0],move[i][j],this.getGraphics());
                    }
                    if(move_teNum[i][j][0] == teNum)
                    {
                        highLight.highLightLastStone(i,j,0,0,move,0,this.getGraphics());
                    }
                }
            }
        }
    
    }
    

    3.4.3 draw.Place 落子类

    package com.krumitz.draw;
    
    import com.krumitz.player.Player;
    import com.krumitz.stone.Stone;
    
    import java.awt.*;
    
    public class Place extends Panel {
    
        ChessPad chessPad;
    
        public Place(ChessPad chessPad)
        {
            setSize(20,20);
            this.chessPad = chessPad;
        }
    
        // 落子
        public static void placeStone(Player player,int x,int y,Graphics graphics)
        {
            if(player.getStone().getStoneColor() == Stone.StoneColor.BLACK)
            {
                graphics.setColor(Color.BLACK);
                graphics.fillOval(x,y,20,20);
            }
            if(player.getStone().getStoneColor() == Stone.StoneColor.WHITE)
            {
                graphics.setColor(Color.WHITE);
                graphics.fillOval(x,y,20,20);
            }
        }
    
        // 提子
        public static void takeStone(int x,int y,Graphics graphics)
        {
            graphics.clearRect(x,y,20,20);
        }
    
    }
    

    3.4.4 draw.TeNum 手数类

    绘制手数,让手数的文字居中是根据

    0如何在Java中居中显示Graphics.drawString()?

    实现的

    package com.krumitz.draw;
    
    import com.krumitz.stone.Stone;
    
    import java.awt.*;
    
    public class TeNum extends Panel {
    
        public static void drawTeNum(int place_x, int place_y, int teNum, Stone.StoneColor color, Graphics graphics)
        {
            if(color == Stone.StoneColor.BLACK)
            {
                graphics.setColor(Color.WHITE);
            }
            if(color == Stone.StoneColor.WHITE)
            {
                graphics.setColor(Color.BLACK);
            }
            Font font = graphics.getFont();
            FontMetrics metrics = graphics.getFontMetrics(font);
            // Determine the X coordinate for the text
            int teNum_x = place_x + (20 - metrics.stringWidth(String.valueOf(teNum))) / 2;
            // Determine the Y coordinate for the text (note we add the ascent, as in java 2d 0 is top of the screen)
            int teNum_y = place_y + ((20 - metrics.getHeight()) / 2) + metrics.getAscent();
            // Set the font
            graphics.setFont(font);
            // Draw the String
            graphics.drawString(String.valueOf(teNum),teNum_x,teNum_y);
        }
    
    }
    

    3.4.5 draw.HighLight 高亮类

    这个方法实现的时候十分的偷懒,去除倒数第二颗棋子的高亮的时候,直接用棋盘底色覆盖了

    package com.krumitz.draw;
    
    import com.krumitz.stone.Stone;
    
    import java.awt.*;
    
    /**
     * 高亮最后一手
     */
    public class HighLight{
    
        private static BasicStroke strokeLine = new BasicStroke(1.5f);
    
        // 给最后一手棋子加一圈红色边框
        public static void highLightLastStone(int coordinate_x, int coordinate_y,
                                              int last_coordinate_x, int last_coordinate_y,
                                              Stone.StoneColor move[][],int teNum, Graphics graphics)
        {
            graphics.setColor(Color.RED);
            int draw_x = (coordinate_x+1)*25 + 10;
            int draw_y = (coordinate_y+1)*25 + 10;
            //
            Graphics2D g = (Graphics2D) graphics;
            g.setStroke(strokeLine);
            g.drawOval(draw_x,draw_y,20,20);
            // 如果手数大于1,把倒数第二手的红色边框去除
            if(teNum > 1)
            {
                removeLastButOneLight(last_coordinate_x,last_coordinate_y,move,g);
            }
        }
    
        // 直接偷懒,用棋盘底色在原来的那一圈上面再画一圈
        public static void removeLastButOneLight(int last_coordinate_x, int last_coordinate_y, Stone.StoneColor move[][], Graphics g)
        {
            int draw_x = (last_coordinate_x + 1) * 25 + 10;
            int draw_y = (last_coordinate_y + 1) * 25 + 10;
            if (move[last_coordinate_x][last_coordinate_y] == Stone.StoneColor.BLACK) {
                g.setColor(Color.BLACK);
            }
            if (move[last_coordinate_x][last_coordinate_y] == Stone.StoneColor.WHITE) {
                g.setColor(Color.WHITE);
            }
            g.drawOval(draw_x, draw_y, 20, 20);
            g.setColor(Color.ORANGE);
            g.drawOval(draw_x,draw_y,20,20);
        }
    
    }
    

    3.5 rules

    3.5.1 rules.AlreadyHadStone 判断已有子

    package com.krumitz.rules;
    
    import com.krumitz.stone.Stone;
    
    /**
     * 判断落子点是否已有子
     */
    public class AlreadyHadStone {
    
        public static boolean ifAlreadyHadStone(Stone.StoneColor move[][],int coordinate_x,int coordinate_y)
        {
    
            if(move[coordinate_x][coordinate_y] == Stone.StoneColor.NONE)
            {
                return false;
            }
            return true;
        }
    
    }
    

    3.5.2 rules.Inboard 判断棋盘内

    package com.krumitz.rules;
    
    /**
     * 判断是否在棋盘内
     */
    public class InBoard {
    
        public static boolean ifInBoard(int coordinate_x, int coordinate_y)
        {
            if((coordinate_x>=0 && coordinate_x<=18) && (coordinate_y>=0 && coordinate_y<=18))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    

    3.5.3 rules.Liberty 判断有气

    package com.krumitz.rules;
    
    import com.krumitz.stone.Stone;
    
    /**
     * 气
     */
    public class Liberty {
    
        // 声明记录数组
        private static int[][] visited = new int[19][19];
        // 声明上下左右四个方向
        private static int[][] directions = {{0,1},{1,0},{-1,0},{0,-1}};
        // 声明记录提子的坐标的二维数组
        private static int[][] liberty_takeStones = new int[19][2];
        // 声明记录二维数组的长度
        private static int liberty_length;
    
        // 记录数组初始化函数
        private static void setUpVisited()
        {
            for (int i = 0; i < 19; i++)
            {
                for (int j = 0; j < 19; j++)
                {
                    visited[i][j] = 0;
                }
            }
        }
    
        private static void setUpTakeStones()
        {
            for (int i = 0; i < 19; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    liberty_takeStones[i][j] = 0;
                }
            }
        }
    
        private static boolean DFS(Stone.StoneColor move[][], int coordinate_x, int coordinate_y)
        {
            int direction_x,direction_y;
            // 设置已访问标志1
            visited[coordinate_x][coordinate_y] = 1;
            // 将当前子的坐标存入提子数组,数组长度+1
            liberty_takeStones[liberty_length][0] = coordinate_x;
            liberty_takeStones[liberty_length][1] = coordinate_y;
            liberty_length++;
            // 遍历上下左右四个方向
            for(int i = 0;i < 4;i++)
            {
                direction_x = coordinate_x + directions[i][0];
                direction_y = coordinate_y + directions[i][1];
                // 判断是否在棋盘内
                if(!(InBoard.ifInBoard(direction_x,direction_y)))
                {
                    // 不在棋盘内就遍历下一个点
                    continue;
                }
                // 如果在棋盘内,且没访问过
                else if(visited[direction_x][direction_y] == 0)
                {
                    // 如果该位置无子,则有气,返回true
                    if(move[direction_x][direction_y] == Stone.StoneColor.NONE)
                    {
                        // 这些输出是在debug的时候用的,可以删掉
                        System.out.println("有气: "+direction_x+" "+direction_y);
                        return true;
                    }
                    // 如果该位置有子,且子的颜色不同,就遍历下一个点
                    if(move[direction_x][direction_y] != move[coordinate_x][coordinate_y])
                    {
                        System.out.println("不同色: "+direction_x+" "+direction_y);
                        continue;
                    }
                    // 如果该位置有子,且颜色相同,递归遍历该子
                    if(move[direction_x][direction_y] == move[coordinate_x][coordinate_y])
                    {
                        System.out.println("同色: "+direction_x+" "+direction_y);
                        //如果下一个子返回true
                        if(DFS(move,direction_x,direction_y))
                        {
                            return true;
                        }
                    }
                }
            }
            // 如果遍历完都没气,返回false
            return false;
        }
    
        // 判断是否有气函数
        public static boolean hasLiberty(Stone.StoneColor move[][], int coordinate_x, int coordinate_y)
        {
            // 初始化遍历记录访问数组
            setUpVisited();
            setUpTakeStones();
            // 重置记录长度
            liberty_length = 0;
            System.out.println("hasLiberty开始: "+coordinate_x+" "+coordinate_y);
            if(DFS(move,coordinate_x,coordinate_y))
            {
                System.out.println("hasLiberty结束,返回true");
                return true;
            }
            else
            {
                System.out.println("hasLiberty结束,返回false");
                return false;
            }
        }
    
        public static int[][] getTakeStones()
        {
            return liberty_takeStones;
        }
    
        public static int getLength()
        {
            return liberty_length;
        }
    
    }
    

    3.5.4 rules.Take 判断提子

    package com.krumitz.rules;
    
    import com.krumitz.stone.Stone;
    
    
    /**
     * 提子
     */
    public class Take {
    
        // 声明上下左右四个方向
        private static int[][] directions = {{0,1},{1,0},{-1,0},{0,-1}};
        // 记录上下左右四颗子的hasLiberty返回的长度
        private static int[][] take_length=new int[4][1];
        // 记录上下左右四颗子的hasLiberty返回的提子数组,这里感觉提的子不会很多,因此长度只有19
        // 4表示4个方向
        // 19表示第N个要提的子
        // 最后两位表示第N个要提的子的x、y坐标
        private static int[][][] take_takeStones=new int[4][19][2];
    
        // 初始化length
        private static void setUpLength()
        {
            for(int i=0;i<4;i++)
            {
                take_length[i][0] = 0;
            }
        }
    
        // 初始化takeStones
        private static void setUpTakeStones()
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 19; j++)
                {
                    for (int k = 0; k < 2; k++)
                    {
                        take_takeStones[i][j][k] = 0;
                    }
                }
            }
        }
    
        // 提子函数
        public static boolean takeStones(Stone.StoneColor move[][],int coordinate_x,int coordinate_y)
        {
            // flag为1则有子可提
            int flag = 0;
            // 初始化记录数组
            setUpLength();
            setUpTakeStones();
            int direction_x,direction_y;
            // 获得当前局面最后一手棋的颜色
            Stone.StoneColor color = move[coordinate_x][coordinate_y];
            // 判断该手棋上下左右四个方向的相领棋子
            for(int i=0;i<4;i++)
            {
                direction_x = coordinate_x + directions[i][0];
                direction_y = coordinate_y + directions[i][1];
                // 如果不在棋盘内,继续下一个循环
                if(!(InBoard.ifInBoard(direction_x,direction_y)))
                {
                    continue;
                }
                // 如果该方向上的有棋
                // 且棋子颜色与当前局面最后一手棋颜色不同
                else if(move[direction_x][direction_y] != color && move[direction_x][direction_y] != Stone.StoneColor.NONE)
                {
                    // 如果该棋子所在的块有气,继续下一个循环
                    if(Liberty.hasLiberty(move,direction_x,direction_y))
                    {
                        continue;
                    }
                    // 如果没气,flag为1
                    else
                    {
                        flag = 1;
                        // 记录第i个方向上的提子的数量
                        take_length[i][0] = Liberty.getLength();
                        // 记录第i个方向上的提子的坐标
                        int temp[][] = Liberty.getTakeStones();
                        for(int j=0;j<19;j++)
                        {
                            for(int k=0;k<2;k++)
                            {
                                take_takeStones[i][j][k] = temp[j][k];
                            }
                        }
                    }
                }
            }
            // flag不为0,可提子,返回true
            if(flag!=0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    
        public static int[][][] getTakeStones()
        {
            return take_takeStones;
        }
    
        public static int[][] getLength()
        {
            return take_length;
        }
    }
    

    4. 运行结果 & 小结

    本次实现的功能还是很简单的,赶在周五下班之前完成了这个程序并且记录了下来

    后续仍有继续改进已有功能和增加新的功能的意愿,如果有空实现了的话,将会继续更新

       

    更多内容详见微信公众号:Python测试和开发

    Python测试和开发

  • 相关阅读:
    LintCode-乱序字符串
    LintCode-字符串查找
    LintCode-比较字符串
    LintCode-两个字符串是变位词
    LintCode-不同的子序列
    View(视图)——AutoCompleteTextView、Spinner
    View(视图)——GridView(点击长按删除图片)
    给图片下加字符
    View(视图)——ListView:BaseAdapter、SimpleCursorAdapter
    View(视图)——ListView:ArrayAdapter、SimpleAdapter
  • 原文地址:https://www.cnblogs.com/phyger/p/14058997.html
Copyright © 2020-2023  润新知