试试用字符串的方法来思考人机五子棋

试试用字符串的方法来思考人机五子棋

1 说明

​ 记得第一篇博客就是写的用C语言实现人机五子棋,完成后当时非常开心,但是现在看来,写得很尴尬。因为后期项目会有用到的缘故,让我再一次重新思考五子棋游戏的算法实现,思路其实和以前没多大变化,但在设计中,发现用字符串自带的方法可以让问题变得很简单(效率方面的话可能会有点影响,但可忽略不计)。

2 胜负判断(核心)

​ 我的思路仍然是依次遍历4个方向(横’-’,竖’|’,左斜’/’,右斜"\"),根据这些方向是否出现5子就可判断输赢。那问题是如何实现呢?标题是用字符串解决,那么当然是使用字符串啦!棋盘我选用二维数组,char类型,'0’表示没有棋,'1’表示黑棋,'2’表示白棋。

​ 具体思路:我可以通过循环获取当前棋子所在方向的字符串,然后通过查找子串的方式判断是否出现五个’1’或’2’,这里给出Java代码示例:

//x和y是坐标,index区分当前棋子颜色
public boolean isVictory(int x, int y, int index)
{
    String panDuan = (index == 1 ? "11111" : "22222" );

    String heng = "";  //-
    for (int i = 0; i < 15; i++) heng += chessboard[i][y];
    if (heng.indexOf(panDuan) != -1)  return true;

    String shu = ""; //|
    for (int i = 0; i < 15; i++) shu += chessboard[x][i];
    if (shu.indexOf(panDuan) != -1)  return true;

    int tempX = x, tempY = y;

    String zhuoXie = chessboard[x][y] + ""; //  '/'
    tempX = x; tempY = y; //向上遍历
    while (tempX++ < 14 && tempY-- > 0) zhuoXie = zhuoXie + chessboard[tempX][tempY];
    tempX = x; tempY = y; //向下遍历
    while (tempX-- > 0 && tempY++ < 14) zhuoXie = chessboard[tempX][tempY] + zhuoXie;
    if (zhuoXie.indexOf(panDuan) != -1)  return true;

    String youxie = chessboard[x][y] + ""; //  '\'
    tempX = x; tempY = y; //向上遍历
    while (tempX-- > 0 && tempY-- > 0) youxie = chessboard[tempX][tempY] + youxie;
    tempX = x; tempY = y; //向下遍历
    while (tempX++ < 14 && tempY++ < 14) youxie = youxie + chessboard[tempX][tempY];
    if (youxie.indexOf(panDuan) != -1)  return true;

    return false;
}

需要注意的是斜方向字符串拼接的顺序(灵感来源于用字符串求回文串),另外代码命名不规范,并且有一个多余的代码,主要看思路吧

3 人机走法(核心)

​ 我的思路仍然是通过遍历棋盘每个可以下棋的位置,根据网上给出的码表得出目前最高分的位置,此位置就是人机落子点。这里请务必先看看这位老师的讲解(当时就是看的这篇博客写的人机算法)。一直觉得这种方法很奇特,原理如此简单,但是效果很神奇( 也可能是我五子棋技术确实太菜了😄)。那问题是如何编写呢?

3.1 棋盘和码表制作

public static char[][] chessboard =new char[15][15];
/*      x表示空格 A表示棋子 score中第一个是自己情况,第二个是阻止对方
        成五:AAAAA                     10000      1000
        活四:XAAAAX                    200        100
        死四:XAAAA或AAAAX              50         20
        活三:XAAAX                     30         10
        死三:XAAA或AAAX                8          5
        活二:XAAX                      2          1
        死二:XAA或AAX                  2          1
        活一:XAX                       1          0
        死一:XA或AX                    1          0
        死绝: 全是A但小于5(使用A代替)    -1          0
        */ //死绝情况说明:就是下了也没有比如说两端不可以下了,中间下了也没有5颗棋子,这里顺便把没出现在码表的情况也判断了
public static Map<String, Integer[]> policyTables  = new HashMap<String, Integer[]>();
//保存每一步下棋步骤,可以悔棋,可以看出每一步顺序
public List<String> saveStep = new LinkedList<>();
static
{
    String[] condition = { "AAAAA", "XAAAAX", "XAAAA", "AAAAX", "XAAAX", "XAAA",
                          "AAAX", "XAAX", "XAA", "AAX", "XAX", "XA", "AX", "A"};

    Integer[][] score = {{100000,1000}, {200,100}, {50,20}, {50,20}, {30,10}, {8,5},
                         {8,5}, {2,1}, {2,1}, {2,1}, {1,0}, {1,0}, {1,0}, {-1,0}};
    //初始化码表
    for (int i = 0; i < condition.length; i++)  policyTables.put(condition[i], score[i]);
    //初始化棋盘
    for (int i = 0; i < 15; i++) Arrays.fill(chessboard[i], '0');
}

​ 其实也可以不使用码表,直接在代码中写,但是这样的话很不方便,分数满天飞,想增加点也不方便。码表使用键值对方式,值使用的数组,第一个元素是自己得分,第二个是阻止敌人后的得分。

3.2 进一步分析

​ 现在我们有了棋盘也有了码表,那接下又该干啥呢?现在想象一下我就是一颗棋,棋盘摆在我的面前,我当前的位置如果我落下去了,会有哪些可能性?你可能会说那可能性太多了吧?但是其实大部分就是码表出现的情况,因此我把当前位置看成中心,像判断胜负那样去判断我当前位置 水平方向,竖直方向,两个斜方向是码表中的哪一种情况,把对应的得分累加起来,但不要忘了,我们还要考虑阻止敌人的情况,所以我们还要把自己当成敌人,然后使用同样的方法看这个位置下去后会对有多大影响,两次影响之和就是最终得分。看到这里你可能会晕,这可能是我的表述问题,但看代码可能就好了。另外,我们发现可能会写大量重复的代码,而且和胜负判断的代码也会使用到。我们还是把问题拆分成小问题好一点。第一步:先写一个函数,功能是通过传入的字符串,下标,得出在码表可以出现的键;第二步:类似胜负判断代码,水平方向,竖直方向,两个斜方向分别调用此函数,得出最终得分,最后返回;第三步:遍历棋盘,把每个空位都判断一遍,得出最高分并且返回坐标。下面是示例代码:

3.2.1 根据字符串匹配码表
public String getPolicyValue(String test, int x, char index)
{
    char reversal = (index == '1' ? '2' : '1');
    String ret = index + "";
    //如果是当前标志,就继续; 否则退出,并且如果是墙就是死,是其他就是死,是空格就是活
    for (int i = x + 1; i < test.length(); i++) //15
    {
        if (test.charAt(i) == index) ret = ret + index;

        if (test.charAt(i) == reversal) break;

        if (test.charAt(i) == '0')
        {
            ret = ret + 'X';
            break;
        }
    }

    for (int i = x - 1; i >= 0; i--)
    {
        if (test.charAt(i) == index) ret = index + ret;

        if (test.charAt(i) == reversal) break;

        if (test.charAt(i) == '0')
        {
            ret = 'X' + ret;
            break;
        }

    }

    ret = ret.replace(index, 'A');

    if (ret.indexOf("AAAAA") != -1) return "AAAAA";
    if (ret.indexOf("X") == -1) return "A";

    return ret;
}
3.2.2 根据码表得出当前位置的分数
//chessboard是棋盘,x和y是棋子,index表明颜色,返回分数
public int getScore(int x, int y, char index)
{
    char preventEnemy = (index == 1 ? '2' : '1' );
    String heng = "";  //-
    for (int i = 0; i < 15; i++) heng += chessboard[i][y];
    String heng1 = getPolicyValue(heng, x, index);
    String heng2 = getPolicyValue(heng, x, preventEnemy);

    String shu = ""; //|
    for (int i = 0; i < 15; i++) shu += chessboard[x][i];
    String shu1 = getPolicyValue(shu, y, index);
    String shu2 = getPolicyValue(shu, y, preventEnemy);

    int tempX = x, tempY = y;
    String zhuoXie = chessboard[x][y] + ""; //  /
    tempX = x; tempY = y; //向上遍历
    while (tempX++ < 14 && tempY-- > 0) zhuoXie = zhuoXie + chessboard[tempX][tempY];
    tempX = x; tempY = y; //向下遍历
    int cnt = 0; //记录向下遍历了次数
    while (tempX-- > 0 && tempY++ < 14)
    {
        zhuoXie = chessboard[tempX][tempY] + zhuoXie;
        cnt++;
    }
    String zhuoXie1 = getPolicyValue(zhuoXie, cnt, index);
    String zhuoXie2 = getPolicyValue(zhuoXie, cnt, preventEnemy);

    String youxie = chessboard[x][y] + ""; //  '\'
    tempX = x; tempY = y; //向上遍历
    cnt = 0;
    while (tempX-- > 0 && tempY-- > 0)
    {
        youxie = chessboard[tempX][tempY] + youxie;
        cnt++;
    }
    tempX = x; tempY = y; //向下遍历
    while (tempX++ < 14 && tempY++ < 14) youxie = youxie + chessboard[tempX][tempY];
    String youxie1= getPolicyValue(youxie, cnt, index);
    String youxie2 =getPolicyValue(youxie, cnt, preventEnemy);

    int score = -1;
    String[] scoreList = {heng1, heng2, shu1, shu2, zhuoXie1, zhuoXie2, youxie1, youxie2};
    for (String i : scoreList)
    {
        score += policyTables.get(i)[0];
        score += policyTables.get(i)[1];
    }

    return score;
}
3.2.3 遍历棋盘返回最高分位置
public int[] calc()
{
    int max = -10000;
    int x = -1, y = -1;
    for (int i = 0; i < 15; i++)
    {
        for (int j = 0; j < 15; j++)
        {
            if (chessboard[j][i] == '0')
            {
                int score = getScore(j, i, '2');
                if (max < score)
                {
                    max = score;
                    x = j;
                    y = i;
                }
            }
        }
    }
    System.out.println("\n" + "当前人机落子点:" + x + "," + y);

    return new int[]{x, y};
}

目前为止,人机算法全部实现,会发现大量使用了和胜负判断相同的代码,实际写可以把这些重复代码写成方法,这只是我的实现方式,网上还有许多方法,下面顺便也提供一下其他几个功能的实现。

4 悔棋功能

​ 此功能比较简单,大致思路是创建一个容器,当我和人机每一次下棋的时候就把坐标和颜色push进去,当我使用悔棋功能的时候只需要从容器中pop出来,然后把棋盘对应位置的值修改为无棋就ok了,如果是c语言可能需要自己手写数据结构,其他很多语言都有对应的容器解决,后面会有Java代码。

5 存档读档

​ 读档的规则依赖于存储,所以先说存档吧。存档功能也比较简单,但是可以有一个小的优化,那就是并不需要把整个棋盘状态都保存。可以只去存放有落子点的坐标和颜色,这样如果我们下了很少的步数,非常节约内存,最大也不过是255个。那我们可以把棋子封装成一个字符串,比如说保存棋子(位置是6,8,颜色是白)我们可以这样写:“06082”,比如说保存棋子(位置是12,14,颜色 是黑)我们可以这样写:“12141”。最后遍历容器把数据放入到文件中。

​ 读档就很简单了,因为我们存档有明确的规则,所以我们只需要按照规则去读出来,然后把数据加入到对应的二维数组棋盘就ok了。这里我采用的是对象序列化和反序列化,后面会有Java代码。

6 封装一下

​ 这里把刚刚的代码整理一下,写一个GobangUtil类,整的稍微专业一点点,如果是用Java语言都可以直接拿来用了!我们可以更加专注界面设计,这里有些代码做了一点点小规范,但是上面的代码没问题的话这个类也不在话下:

package com.hmj;

import java.io.*;
import java.util.*;

public class GobangUtil
{
    public static final Character NO_CHESS  = '0';
    public static final Character BLACK_CHESS = '1';
    public static final Character WHITE_CHESS = '2';
    public static final String BLACK_WIN = "11111";
    public static final String WHITE_WIN = "22222";
    public static final Integer CHESSBOARD_SIZE = 15;

    public static Map<String, Integer[]> policyTables  = new HashMap<String, Integer[]>();
    static
    {
        String[] condition = { "AAAAA", "XAAAAX", "XAAAA", "AAAAX", "XAAAX", "XAAA",
                "AAAX", "XAAX", "XAA", "AAX", "XAX", "XA", "AX", "A"};

        Integer[][] score = {{100000,1000}, {200,100}, {50,20}, {50,20}, {30,10}, {8,5},
                {8,5}, {2,1}, {2,1}, {2,1}, {1,0}, {1,0}, {1,0}, {-1,0}};
        //初始化码表
        for (int i = 0; i < condition.length; i++)  policyTables.put(condition[i], score[i]);
    }

    /**
     * 获取一个SaveStep表 可以用来保存每一步下棋步骤,悔棋功能可以用到,也可以看出每一步顺序
     * @return SaveStep表
     */
    public static List<String> getSaveStep()
    {
        return new LinkedList<>();
    }

    /**
     * 获取一个15*15的字符二维数组
     * @return 返回一个Chessboard(用户需要)
     */
    public static char[][] getChessboard()
    {
        char[][] chessboard =new char[CHESSBOARD_SIZE][CHESSBOARD_SIZE];
        for (int i = 0; i < CHESSBOARD_SIZE; i++) Arrays.fill(chessboard[i], NO_CHESS);
        return chessboard;
    }

    /**
     * 判断胜负
     * @param chessboard 当前棋盘
     * @param x 棋子x坐标
     * @param y 棋子y坐标
     * @param index BLACK_CHESS或者WHITE_CHESS
     * @return true表示胜利
     */
    public static boolean isVictory(char[][] chessboard, int x, int y, char index)
    {
        String panDuan = (index == BLACK_CHESS ? BLACK_WIN : WHITE_WIN );

        String heng = "";  //-
        for (int i = 0; i < CHESSBOARD_SIZE; i++) heng += chessboard[i][y];
        if (heng.indexOf(panDuan) != -1)  return true;

        String shu = ""; //|
        for (int i = 0; i < CHESSBOARD_SIZE; i++) shu += chessboard[x][i];
        if (shu.indexOf(panDuan) != -1)  return true;

        int tempX = x, tempY = y;

        String zhuoXie = chessboard[x][y] + ""; //  /
        tempX = x; tempY = y; //向上遍历
        while (tempX++ < CHESSBOARD_SIZE-1 && tempY-- > 0) zhuoXie = zhuoXie + chessboard[tempX][tempY];
        tempX = x; tempY = y; //向下遍历
        while (tempX-- > 0 && tempY++ < CHESSBOARD_SIZE-1) zhuoXie = chessboard[tempX][tempY] + zhuoXie;
        if (zhuoXie.indexOf(panDuan) != -1)  return true;

        String youxie = chessboard[x][y] + ""; //  '\'
        tempX = x; tempY = y; //向上遍历
        while (tempX-- > 0 && tempY-- > 0) youxie = chessboard[tempX][tempY] + youxie;
        tempX = x; tempY = y; //向下遍历
        while (tempX++ < CHESSBOARD_SIZE-1 && tempY++ < CHESSBOARD_SIZE-1) youxie = youxie + chessboard[tempX][tempY];
        if (youxie.indexOf(panDuan) != -1)  return true;

        return false;
    }

    //返回的就是可以直接判断码表中情况的字符串
    private static String getPolicyValue(String test, int x, char index)
    {
        char reversal = (index == BLACK_CHESS ? WHITE_CHESS : BLACK_CHESS);
        String ret = index + "";
        //如果是当前标志,就继续; 否则退出,并且如果是墙就是死,是其他就是死,是空格就是活
        for (int i = x + 1; i < test.length(); i++)
        {
            if (test.charAt(i) == index) ret = ret + index;
            if (test.charAt(i) == reversal) break;
            if (test.charAt(i) == NO_CHESS) { ret = ret + 'X'; break;}
        }

        for (int i = x - 1; i >= 0; i--)
        {
            if (test.charAt(i) == index) ret = index + ret;
            if (test.charAt(i) == reversal) break;
            if (test.charAt(i) == NO_CHESS) {  ret = 'X' + ret; break;}
        }

        ret = ret.replace(index, 'A');
        if (ret.indexOf("AAAAA") != -1) return "AAAAA";
        if (ret.indexOf("X") == -1) return "A";

        return ret;
    }

    //chessboard是棋盘,x和y是棋子,index表明颜色,返回分数
    private static int getScore(char[][] chessboard, int x, int y, char index)
    {
        char preventEnemy = (index == BLACK_CHESS ? WHITE_CHESS : BLACK_CHESS );
        String heng = "";  //-
        for (int i = 0; i < CHESSBOARD_SIZE; i++) heng += chessboard[i][y];
        String heng1 = getPolicyValue(heng, x, index);
        String heng2 = getPolicyValue(heng, x, preventEnemy);

        String shu = ""; //|
        for (int i = 0; i < CHESSBOARD_SIZE; i++) shu += chessboard[x][i];
        String shu1 = getPolicyValue(shu, y, index);
        String shu2 = getPolicyValue(shu, y, preventEnemy);

        int tempX = x, tempY = y;
        String zhuoXie = chessboard[x][y] + ""; //  /
        tempX = x; tempY = y; //向上遍历
        while (tempX++ < CHESSBOARD_SIZE - 1 && tempY-- > 0) zhuoXie = zhuoXie + chessboard[tempX][tempY];
        tempX = x; tempY = y; //向下遍历
        int cnt = 0; //记录向下遍历了次数
        while (tempX-- > 0 && tempY++ < CHESSBOARD_SIZE - 1)
        {
            zhuoXie = chessboard[tempX][tempY] + zhuoXie;
            cnt++;
        }
        String zhuoXie1 = getPolicyValue(zhuoXie, cnt, index);
        String zhuoXie2 = getPolicyValue(zhuoXie, cnt, preventEnemy);

        String youxie = chessboard[x][y] + ""; //  '\'
        tempX = x; tempY = y; //向上遍历
        cnt = 0;
        while (tempX-- > 0 && tempY-- > 0)
        {
            youxie = chessboard[tempX][tempY] + youxie;
            cnt++;
        }
        tempX = x; tempY = y; //向下遍历
        while (tempX++ < CHESSBOARD_SIZE - 1 && tempY++ < CHESSBOARD_SIZE - 1) youxie = youxie + chessboard[tempX][tempY];
        String youxie1= getPolicyValue(youxie, cnt, index);
        String youxie2 =getPolicyValue(youxie, cnt, preventEnemy);

        int score = -1;
        String[] scoreList = {heng1, heng2, shu1, shu2, zhuoXie1, zhuoXie2, youxie1, youxie2};
        for (String i : scoreList)
        {
            score += policyTables.get(i)[0];
            score += policyTables.get(i)[1];
        }

        return score;
    }

    /**
     * 判断人机最佳落子点
     * @param chessboard 当前棋盘
     * @return 一个int类型的二维数组,最优的位置
     */
    public static int[] calc(char[][] chessboard)
    {
        int max = -10000;
        int x = -1, y = -1;
        for (int i = 0; i < CHESSBOARD_SIZE; i++)
        {
            for (int j = 0; j < CHESSBOARD_SIZE; j++)
            {
                if (chessboard[j][i] == NO_CHESS)
                {
                    int score = getScore(chessboard, j, i, WHITE_CHESS);
                    if (max < score) { max = score; x = j; y = i;}
                }
            }
        }
        return new int[]{x, y};
    }

    /**
     * 落子
     * @param chessboard 当前棋盘
     * @param saveStep 步骤保存表
     * @param x x坐标
     * @param y y坐标
     * @param index BLACK_CHESS或者WHITE_CHESS
     */
    public static void downChess(char[][] chessboard, List<String> saveStep, int x, int y, char index)
    {
        chessboard[x][y] = index;
        saveStep.add(String.format("%02d %02d %c", x, y, index)); //"01 02 1"
    }

    /**
     * 悔棋
     * @param chessboard 棋盘
     * @param saveStep 步骤保存表
     */
    public static void back(char[][] chessboard, List<String> saveStep)
    {
        if (saveStep.size() >= 2)
        {
            for (int i = 0; i < 2; i++)
            {
                String lastSteps = saveStep.get(saveStep.size() - 1);
                String[] str = lastSteps.split(" ");
                chessboard[Integer.parseInt(str[0])][Integer.parseInt(str[1])] = NO_CHESS;
                saveStep.remove(saveStep.size() - 1);
            }
        }
    }

    /**
     * 存档功能
     * @param chessboard 棋盘
     * @param path 保存的路径
     */
    public static void enCode(char[][] chessboard, String path)
    {
        List<String> saveChessboard = new ArrayList<>();
        for (int i = 0; i < CHESSBOARD_SIZE; i++)
            for (int j = 0; j < CHESSBOARD_SIZE; j++)
                if (chessboard[i][j] != NO_CHESS)
                    saveChessboard.add(String.format("%02d %02d %c", i, j, chessboard[i][j]));

        //序列化
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path)))
        {
            oos.writeObject(saveChessboard);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }

    /**
     * 读档
     * @param chessboard 棋盘
     * @param path 读取的路径
     * @return true表示成功读档
     */
    public static boolean deCode(char[][] chessboard, String path)
    {
        //反序列化
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path)))
        {
            List<String> ret = (List<String>)ois.readObject();
            for (String i : ret)
            {
                String[] s = i.split(" ");
                chessboard[Integer.parseInt(s[0])][Integer.parseInt(s[1])] = s[2].charAt(0);
            }
            return true;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 当前位置有棋吗
     * @param chessboard 棋盘
     * @param x x坐标
     * @param y y坐标
     * @return true表示当前位置有棋
     */
    public static boolean haveChess(char[][] chessboard, int x, int y)
    {
        return chessboard[x][y] != NO_CHESS;
    }

    /**
     * 显示当前棋盘情况(GUI界面下可自己实现)
     * @param chessboard 棋盘
     */
    public static void showChessboard(char[][] chessboard)
    {
        for (int i = 0; i < CHESSBOARD_SIZE; i++)
        {
            for (int j = 0; j < CHESSBOARD_SIZE; j++)
            {
                String s = "";
                if (chessboard[j][i] == BLACK_CHESS) s = "1";
                else if (chessboard[j][i] == WHITE_CHESS) s = "2";
                else s = "-";
                System.out.printf("%-3s", s);
                if (j == CHESSBOARD_SIZE - 1)
                    System.out.print(" "+ i);
            }
            System.out.println();
        }

        System.out.println();
        for (int i = 0; i < CHESSBOARD_SIZE; i++) System.out.printf("%-3d", i);
        System.out.println();
    }

}

7 写一个测试类

​ 把刚刚的代码加入到了项目中后,写一个简单命令行来爽一把,顺便把里面的方法都用用,我们可以根据这个例子加入图像化界面,这里可能会有一些小的bug,就当是留给大家的作业啦!

import java.util.List;
import java.util.Scanner;

public class GobangUtilTest
{
    public static void main(String[] args)
    {
        System.out.println("欢迎来到人机五子棋测试\n" + "输入:\n" +
                            "   1 进入游戏\n" +
                            "   2 读档\n" +
                            "   3 退出游戏\n");

        Scanner in = new Scanner(System.in);

        char[][] chessboard = GobangUtil.getChessboard();
        List<String> saveStep = GobangUtil.getSaveStep();

        while (true)
        {
            switch (in.nextInt())
            {
                case 1: startGame(chessboard, saveStep); break;
                case 2: deCode(chessboard, saveStep, "out.txt"); break;
                case 3: System.exit(0); break;
                default: System.out.println("请重新输入!");
            }
        }

    }

    //开始游戏
    public static void startGame(char[][] chessboard, List<String> saveStep)
    {
        System.out.println("欢迎来到游戏!");
        GobangUtil.showChessboard(chessboard);
        try{
            while (true)
            {
                System.out.println("back 悔棋; save 存档; exit 退出游戏");
                Scanner s = new Scanner(System.in);
                String[] ret = s.nextLine().split(" ");
                //悔棋功能实现
                if (ret[0].equals("back"))
                {
                    GobangUtil.back(chessboard, saveStep);
                    GobangUtil.showChessboard(chessboard);
                    continue;
                }
                else if (ret[0].equals("save")) //存档功能实现
                {
                    GobangUtil.enCode(chessboard, "out.txt");
                    GobangUtil.showChessboard(chessboard);
                    continue;
                }
                else if (ret[0].equals("exit")) //存档功能实现
                {
                    System.exit(0);
                }

                int a = Integer.parseInt(ret[0]);
                int b = Integer.parseInt(ret[1]);

                if (GobangUtil.haveChess(chessboard, a, b))
                {
                    System.out.println("不可重复落子!请重新输入!");
                    continue;
                }

                GobangUtil.downChess(chessboard, saveStep, a, b, '1');

                if (GobangUtil.isVictory(chessboard, a, b, '1'))
                {
                    System.out.println("你赢了");
                    GobangUtil.showChessboard(chessboard);
                    break;
                }

                int[] matchin = GobangUtil.calc(chessboard);
                GobangUtil.downChess(chessboard, saveStep, matchin[0], matchin[1], '2');
                System.out.println("人机当前落子位置:" + matchin[0] + "," + matchin[0]);
                if (GobangUtil.isVictory(chessboard, matchin[0], matchin[1], '2'))
                {
                    System.out.println("人机赢了!");
                    GobangUtil.showChessboard(chessboard);
                    break;
                }
                GobangUtil.showChessboard(chessboard);
            }
        }catch (Exception e){
            System.out.println("输入导致程序发生异常啦!该背时!");
        }

    }

    //读档(解码)
    public static void deCode(char[][] chessboard, List<String> saveStep, String path)
    {
        if (GobangUtil.deCode(chessboard, path))
            startGame(chessboard, saveStep);
        else
        {
            System.out.println("读档失败");
            return;
        }
    }

}

8 结语

​ 这里做了一个抛砖引玉,有没有觉得字符串有时很神奇?大家也可以在评论区发表一下自己的看法哦😄!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值