五子棋简易AI算法1

简介: 基本思想设置不同连接方式的权值并进行存储

一、基本思想:五子棋存在多种连接方式,这也就决定了每一个空位的权值有所不同,我们对五子棋的不同连接方式设置权值,然后遍历棋盘,算出每一个空位上的权值,选择权值最大的空位下棋,所以这个算法的关键就在于:1.设置并且存储不同连接方式及其对应的权值 2.计算棋盘空位上的权值。

二、设置不同连接方式的权值并进行存储

棋子的连接分为活连与死连,假设0代表空位,1代表黑棋,2代表白旗,如010为活连,01(遇到边界)为死连为不同连接方式设置对应权值:

假设0代表空位,1代表黑棋,2代表白旗

权值表(还可以细分)

连接方式 权值 010 50 0110 150 01110 500 011110 3000 020 50 0220 150 02220 500 022220 3000 01 30 011 90 0111 300 01111 3000 02 30 022 90 0222 300 02222 3000

设置好权值表后,就要考虑如何存储权值表,因为权值表中的数据是用来后续计算空位总权值所需的。这里我们考虑用哈希表进行存储“连接方式——权值”这样子的键值对

Key-Value : 键值对

HashMap:

将键值对一起存入 ,可以通过键来查询对应的值

将连子情况作为Key ,权值分作为Value

1: 键不能重复,值可以重复

2: HashMap 存储优势是 查询时是O1的时间复杂度

3: HashMap 存储原理:

1: 用key来计算一个hash值 (当作唯一标识),hash值然后作为下标 ,然后将k-v存储在数组中对应下标位置
操作:

实例化: HashMap codeMap = new HashMap();
方法: code.put(key,value);/ value = code.get(key);

static HashMap codeMap = new HashMap<> ();
static int[][] codeArrray = new int[16][16]; //创建用来存储权值的二维数组

// 静态代码块
static{
    codeMap.put ("010", 50);
    codeMap.put ("0110", 150);
    codeMap.put ("01110", 500);
    codeMap.put ("011110", 3000);

    codeMap.put ("020", 50);
    codeMap.put ("0220", 150);
    codeMap.put ("02220", 500);
    codeMap.put ("022220", 3000);

    codeMap.put ("01", 30);
    codeMap.put ("011", 90);
    codeMap.put ("0111", 300);
    codeMap.put ("01111", 3000);

    codeMap.put ("02", 30);
    codeMap.put ("022", 90);
    codeMap.put ("0222", 300);
    codeMap.put ("02222", 3000);

    Integer integer = codeMap.get ("010");
    System.out.println (integer);

三、遍历表格计算权值

如图一个五子棋盘:image.png
尝试计算a、b两个空位处的权值大小,我们可以发现空位处的连接可以往上、下、左、右、左上、右上、左下、右下一共8个方向进行搜索,同时我们再规定一个空位的权值由八个方向的连接带来的权值简单相加得到(规则不唯一)。

对于a,往左的连接为01,权值30;往下的连接为01,权值30;往右下的连接010,权值50,故a处的权值为30+30+50=110

对于b,往左的连接为022,权值90;往上的连接为01,权值30;往左上的连接为011,权值90,故b处的权值为90+30+90=210

有了上面的举例,下面通过遍历计算每一个空位的权值

private static void getCodeArray(int[][] arr){

    for(int i = 0; i < arr.length; i++){
        for(int j = 0; j < arr[i].length; j++){
            int chessNum = arr[i][j];
            // 遍历所有的空格
            if(chessNum == 0){
                toRight (i, j, arr);    //往右走的权值
                toLeft(i,j,arr);
                toUp(i,j,arr);
                toDown(i,j,arr);
                toLeftUp(i,j,arr);  //往左上走的权值
                toRightup(i,j,arr);
                toLeftDown(i,j,arr);
                toRightDown(i,j,arr);
            }
        }
    }

上面的代码中往8个方向计算权值,但是方法还未定义,下面以往右和往左上为例

往右:

private static void toRight(int i, int j, int[][] chessArray){
    // 等于0
    int chessNum = chessArray[i][j];
    // 右边是0/墙 return
    if(j + 1 >= chessArray[i].length || chessArray[i][j + 1] == 0){
        return;
    }
    // 右边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i][j + 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 右边第二颗 0/与第一颗相同的/不同的/墙
    for(int m = j + 2; m < chessArray[i].length; m++){
        int chessNumRn = chessArray[i][m];
        if(chessNumRn != 0){
            if(chessNumR1 == chessNumRn){
                // 找到相同的就拼接一个棋子标识
                codeStr += chessNumR1;
            } else if(chessNumR1 != chessNumRn){
                // 找到不相同的就结束循环
                break;
            }
        } else{
            // 活连的结尾 就结束循环
            codeStr += "0";
            break;
        }

    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;

}

往左上:

private static void toLeftUp(int i, int j, int[][] chessArray) {
// 等于0
int chessNum = chessArray[i][j];
// 左上边是0/墙 return
if(i - 1 <= -1||j - 1<= -1|| chessArray[i - 1][j - 1] == 0){
return;
}
// 左上边第一个颗是1/2 记录下来
int chessNumR1 = chessArray[i - 1][j - 1];
String codeStr = "" + chessNum + chessNumR1;
// 左上边第二颗 0/与第一颗相同的/不同的/墙
for(int k = i - 2; k > -1; k--) {
for (int m = j - 2; m > -1; m--) {
int chessNumRn = chessArray[k][m];
if (chessNumRn != 0) {
if (chessNumR1 == chessNumRn) {
// 找到相同的就拼接一个棋子标识
codeStr += chessNumR1;
} else if (chessNumR1 != chessNumRn) {
// 找到不相同的就结束循环
break;
}
} else {
// 活连的结尾 就结束循环
codeStr += "0";
break;
}

        }
    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

这里无论是往哪个方向,计算出来的权值都需要累加到codeArray对应位置,codeArray是已经定义的存储权值的二维数组

完整代码:

package com.zsj0929;
import java.util.HashMap;

public class AI {// 会在类使用的时候初始化
static HashMap codeMap = new HashMap<> ();
static int[][] codeArrray = new int[16][16];

// 静态代码块
static{
    codeMap.put ("010", 50);
    codeMap.put ("0110", 150);
    codeMap.put ("01110", 500);
    codeMap.put ("011110", 3000);

    codeMap.put ("020", 50);
    codeMap.put ("0220", 150);
    codeMap.put ("02220", 500);
    codeMap.put ("022220", 3000);

    codeMap.put ("01", 30);
    codeMap.put ("011", 90);
    codeMap.put ("0111", 300);
    codeMap.put ("01111", 3000);

    codeMap.put ("02", 30);
    codeMap.put ("022", 90);
    codeMap.put ("0222", 300);
    codeMap.put ("02222", 3000);

    Integer integer = codeMap.get ("010");
    System.out.println (integer);
}

public static void main(String[] args){
    int[][] arr = {
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    };
    // 遍历计算所有可以下棋的地方的权值
    getCodeArray (arr);
    // 获取矩阵中权值最大的位置

    for(int i = 0; i < codeArrray.length; i++){
        for(int j = 0; j < codeArrray[i].length; j++){
            System.out.print (codeArrray[i][j] + "     ");
        }
        System.out.println ();
    }
}

private static void getCodeArray(int[][] arr){

    for(int i = 0; i < arr.length; i++){
        for(int j = 0; j < arr[i].length; j++){
            int chessNum = arr[i][j];
            // 遍历所有的空格
            if(chessNum == 0){
                toRight (i, j, arr);    //往右走的权值
                toLeft(i,j,arr);
                toUp(i,j,arr);
                toDown(i,j,arr);
                toLeftUp(i,j,arr);  //往左上走的权值
                toRightup(i,j,arr);
                toLeftDown(i,j,arr);
                toRightDown(i,j,arr);
            }
        }
    }

}

private static void toRightDown(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 右下边是0/墙 return
    if(i + 1 >= chessArray.length||j + 1>=chessArray.length || chessArray[i + 1][j + 1] == 0){
        return;
    }
    // 右下边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i + 1][j + 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 右下边第二颗 0/与第一颗相同的/不同的/墙
    for(int k = i + 2; k < chessArray.length; k++) {
        for (int m = j + 2; m < chessArray[i].length; m++) {
            int chessNumRn = chessArray[k][m];
            if (chessNumRn != 0) {
                if (chessNumR1 == chessNumRn) {
                    // 找到相同的就拼接一个棋子标识
                    codeStr += chessNumR1;
                } else if (chessNumR1 != chessNumRn) {
                    // 找到不相同的就结束循环
                    break;
                }
            } else {
                // 活连的结尾 就结束循环
                codeStr += "0";
                break;
            }

        }
    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

private static void toLeftDown(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 左下边是0/墙 return
    if(i + 1 >= chessArray.length||j - 1 <= -1 || chessArray[i + 1][j - 1] == 0){
        return;
    }
    // 左下边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i + 1][j - 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 左下边第二颗 0/与第一颗相同的/不同的/墙
    for(int k = i + 2; k < chessArray.length; k++) {
        for (int m = j - 2; m >= -1; m--) {
            int chessNumRn = chessArray[k][m];
            if (chessNumRn != 0) {
                if (chessNumR1 == chessNumRn) {
                    // 找到相同的就拼接一个棋子标识
                    codeStr += chessNumR1;
                } else if (chessNumR1 != chessNumRn) {
                    // 找到不相同的就结束循环
                    break;
                }
            } else {
                // 活连的结尾 就结束循环
                codeStr += "0";
                break;
            }

        }
    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

private static void toRightup(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 右上边是0/墙 return
    if(i - 1 <= -1||j + 1>=chessArray.length || chessArray[i - 1][j + 1] == 0){
        return;
    }
    // 右上边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i - 1][j + 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 右上边第二颗 0/与第一颗相同的/不同的/墙
    for(int k = i - 2; k > -1; k--) {
        for (int m = j + 2; m < chessArray[i].length; m++) {
            int chessNumRn = chessArray[k][m];
            if (chessNumRn != 0) {
                if (chessNumR1 == chessNumRn) {
                    // 找到相同的就拼接一个棋子标识
                    codeStr += chessNumR1;
                } else if (chessNumR1 != chessNumRn) {
                    // 找到不相同的就结束循环
                    break;
                }
            } else {
                // 活连的结尾 就结束循环
                codeStr += "0";
                break;
            }

        }
    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

private static void toLeftUp(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 左上边是0/墙 return
    if(i - 1 <= -1||j - 1<= -1|| chessArray[i - 1][j - 1] == 0){
        return;
    }
    // 左上边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i - 1][j - 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 左上边第二颗 0/与第一颗相同的/不同的/墙
    for(int k = i - 2; k > -1; k--) {
        for (int m = j - 2; m > -1; m--) {
            int chessNumRn = chessArray[k][m];
            if (chessNumRn != 0) {
                if (chessNumR1 == chessNumRn) {
                    // 找到相同的就拼接一个棋子标识
                    codeStr += chessNumR1;
                } else if (chessNumR1 != chessNumRn) {
                    // 找到不相同的就结束循环
                    break;
                }
            } else {
                // 活连的结尾 就结束循环
                codeStr += "0";
                break;
            }

        }
    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

private static void toDown(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 下边是0/墙 return
    if(i + 1 >= chessArray.length || chessArray[i + 1][j] == 0){
        return;
    }
    // 下边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i + 1][j];
    String codeStr = "" + chessNum + chessNumR1;
    // 下边第二颗 0/与第一颗相同的/不同的/墙
    for(int k = i + 2; k < chessArray.length; k++){
        int chessNumRn = chessArray[k][j];
        if(chessNumRn != 0){
            if(chessNumR1 == chessNumRn){
                // 找到相同的就拼接一个棋子标识
                codeStr += chessNumR1;
            } else if(chessNumR1 != chessNumRn){
                // 找到不相同的就结束循环
                break;
            }
        } else{
            // 活连的结尾 就结束循环
            codeStr += "0";
            break;
        }

    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;

}

private static void toUp(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 上边是0/墙 return
    if(i - 1 <= -1 || chessArray[i - 1][j] == 0){
        return;
    }
    // 上边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i - 1][j];
    String codeStr = "" + chessNum + chessNumR1;
    // 上边第二颗 0/与第一颗相同的/不同的/墙
    for(int k = i - 2; k > -1; k--){
        int chessNumRn = chessArray[k][j];
        if(chessNumRn != 0){
            if(chessNumR1 == chessNumRn){
                // 找到相同的就拼接一个棋子标识
                codeStr += chessNumR1;
            } else if(chessNumR1 != chessNumRn){
                // 找到不相同的就结束循环
                break;
            }
        } else{
            // 活连的结尾 就结束循环
            codeStr += "0";
            break;
        }

    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

private static void toLeft(int i, int j, int[][] chessArray) {
    // 等于0
    int chessNum = chessArray[i][j];
    // 左边是0/墙 return
    if(j - 1 <= -1 || chessArray[i][j - 1] == 0){
        return;
    }
    // 左边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i][j - 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 左边第二颗 0/与第一颗相同的/不同的/墙
    for(int m = j - 2; m > -1; m--){
        int chessNumRn = chessArray[i][m];
        if(chessNumRn != 0){
            if(chessNumR1 == chessNumRn){
                // 找到相同的就拼接一个棋子标识
                codeStr += chessNumR1;
            } else if(chessNumR1 != chessNumRn){
                // 找到不相同的就结束循环
                break;
            }
        } else{
            // 活连的结尾 就结束循环
            codeStr += "0";
            break;
        }

    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;
}

private static void toRight(int i, int j, int[][] chessArray){
    // 等于0
    int chessNum = chessArray[i][j];
    // 右边是0/墙 return
    if(j + 1 >= chessArray[i].length || chessArray[i][j + 1] == 0){
        return;
    }
    // 右边第一个颗是1/2 记录下来
    int chessNumR1 = chessArray[i][j + 1];
    String codeStr = "" + chessNum + chessNumR1;
    // 右边第二颗 0/与第一颗相同的/不同的/墙
    for(int m = j + 2; m < chessArray[i].length; m++){
        int chessNumRn = chessArray[i][m];
        if(chessNumRn != 0){
            if(chessNumR1 == chessNumRn){
                // 找到相同的就拼接一个棋子标识
                codeStr += chessNumR1;
            } else if(chessNumR1 != chessNumRn){
                // 找到不相同的就结束循环
                break;
            }
        } else{
            // 活连的结尾 就结束循环
            codeStr += "0";
            break;
        }

    }
    Integer codeValue = codeMap.get (codeStr);
    if(codeValue == null){
        return;
    }
    // 将权值分存入 一个 新的权值二维数组
    codeArrray[i][j] += codeValue;

}
相关文章
|
1月前
|
机器学习/深度学习 人工智能 算法
「AI工程师」算法研发与优化-工作指导
**工作指导书摘要:** 设计与优化算法,提升性能效率;负责模型训练及测试,确保准确稳定;跟踪业界最新技术并应用;提供内部技术支持,解决使用问题。要求扎实的数学和机器学习基础,熟悉深度学习框架,具备良好编程及数据分析能力,注重团队协作。遵循代码、文档和测试规范,持续学习创新,优化算法以支持业务发展。
40 0
「AI工程师」算法研发与优化-工作指导
|
11天前
|
机器学习/深度学习 人工智能 算法
AI入门必读:Java实现常见AI算法及实际应用,有两下子!
本文全面介绍了人工智能(AI)的基础知识、操作教程、算法实现及其在实际项目中的应用。首先,从AI的概念出发,解释了AI如何使机器具备学习、思考、决策和交流的能力,并列举了日常生活中的常见应用场景,如手机助手、推荐系统、自动驾驶等。接着,详细介绍了AI在提高效率、增强用户体验、促进技术创新和解决复杂问题等方面的显著作用,同时展望了AI的未来发展趋势,包括自我学习能力的提升、人机协作的增强、伦理法规的完善以及行业垂直化应用的拓展等...
95 3
AI入门必读:Java实现常见AI算法及实际应用,有两下子!
|
19天前
|
机器学习/深度学习 数据采集 人工智能
AI技术实践:利用机器学习算法预测房价
人工智能(Artificial Intelligence, AI)已经深刻地影响了我们的生活,从智能助手到自动驾驶,AI的应用无处不在。然而,AI不仅仅是一个理论概念,它的实际应用和技术实现同样重要。本文将通过详细的技术实践,带领读者从理论走向实践,详细介绍AI项目的实现过程,包括数据准备、模型选择、训练和优化等环节。
118 3
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
算法金 | 秒懂 AI - 深度学习五大模型:RNN、CNN、Transformer、BERT、GPT 简介
**RNN**,1986年提出,用于序列数据,如语言模型和语音识别,但原始模型有梯度消失问题。**LSTM**和**GRU**通过门控解决了此问题。 **CNN**,1989年引入,擅长图像处理,卷积层和池化层提取特征,经典应用包括图像分类和物体检测,如LeNet-5。 **Transformer**,2017年由Google推出,自注意力机制实现并行计算,优化了NLP效率,如机器翻译。 **BERT**,2018年Google的双向预训练模型,通过掩码语言模型改进上下文理解,适用于问答和文本分类。
85 9
|
20天前
|
机器学习/深度学习 人工智能 算法
深入了解AI算法及其实现过程
人工智能(AI)已经成为现代技术发展的前沿,广泛应用于多个领域,如图像识别、自然语言处理、智能推荐系统等。本文将深入探讨AI算法的基础知识,并通过一个具体的实现过程来展示如何将AI算法应用于实际问题。
90 0
|
1月前
|
机器学习/深度学习 数据采集 人工智能
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
算法金 | 没有思考过 Embedding,不足以谈 AI
**摘要:** 本文深入探讨了人工智能中的Embedding技术,解释了它是如何将高维数据映射到低维向量空间以简化处理和捕获内在关系的。文章介绍了词向量、图像嵌入和用户嵌入等常见类型的Embedding,并强调了其在自然语言处理、计算机视觉和推荐系统中的应用。此外,还讨论了Embedding的数学基础,如向量空间和线性代数,并提到了Word2Vec、GloVe和BERT等经典模型。最后,文章涵盖了如何选择合适的Embedding技术,以及在资源有限时的考虑因素。通过理解Embedding,读者能够更好地掌握AI的精髓。
22 0
算法金 | 没有思考过 Embedding,不足以谈 AI
|
1月前
|
机器学习/深度学习 人工智能 供应链
|
6天前
|
算法
基于模糊控制算法的倒立摆控制系统matlab仿真
本项目构建了一个基于模糊控制算法的倒立摆控制系统,利用MATLAB 2022a实现了从不稳定到稳定状态的转变,并输出了相应的动画和收敛过程。模糊控制器通过对小车位置与摆的角度误差及其变化量进行模糊化处理,依据预设的模糊规则库进行模糊推理并最终去模糊化为精确的控制量,成功地使倒立摆维持在直立位置。该方法无需精确数学模型,适用于处理系统的非线性和不确定性。
基于模糊控制算法的倒立摆控制系统matlab仿真
|
5天前
|
机器学习/深度学习 算法 定位技术
MATLAB - 遗传算法(GA)求解旅行商问题(TSP)
MATLAB - 遗传算法(GA)求解旅行商问题(TSP)
11 3

热门文章

最新文章