五子棋简易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;

}
相关文章
|
10天前
|
机器学习/深度学习 人工智能 算法
当AI提示词遇见精密算法:TimeGuessr如何用数学魔法打造文化游戏新体验
TimeGuessr融合AI与历史文化,首创时间与空间双维度评分体系,结合分段惩罚、Haversine距离计算与加权算法,辅以连击、速度与完美奖励机制,实现公平且富挑战性的游戏体验。
|
1月前
|
人工智能 算法 计算机视觉
只需完成手画线稿,让AI算法帮你自动上色
本文介绍了如何利用图像处理技术生成手绘风格图像及自动上色的方法。内容涵盖图像灰度化、梯度调整、虚拟深度实现手绘效果,以及使用 Python 编程实现相关算法。此外,还介绍了 AI 工具 Style2Paints V4.5,其可为线稿自动上色并支持多种线稿类型,如插画和手绘铅笔稿,适用于艺术创作与图像处理领域。
|
2月前
|
机器学习/深度学习 人工智能 编解码
AI视觉新突破:多角度理解3D世界的算法原理全解析
多视角条件扩散算法通过多张图片输入生成高质量3D模型,克服了单图建模背面细节缺失的问题。该技术模拟人类多角度观察方式,结合跨视图注意力机制与一致性损失优化,大幅提升几何精度与纹理保真度,成为AI 3D生成的重要突破。
171 0
|
2月前
|
机器学习/深度学习 人工智能 算法
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
|
2月前
|
机器学习/深度学习 人工智能 算法
AI-Compass RLHF人类反馈强化学习技术栈:集成TRL、OpenRLHF、veRL等框架,涵盖PPO、DPO算法实现大模型人类价值对齐
AI-Compass RLHF人类反馈强化学习技术栈:集成TRL、OpenRLHF、veRL等框架,涵盖PPO、DPO算法实现大模型人类价值对齐
 AI-Compass RLHF人类反馈强化学习技术栈:集成TRL、OpenRLHF、veRL等框架,涵盖PPO、DPO算法实现大模型人类价值对齐
|
2月前
|
人工智能 算法 搜索推荐
电商API的“AI革命”:全球万亿市场如何被算法重新定义?
AI+电商API正引领智能商业变革,通过智能推荐、动态定价与自动化运营三大核心场景,大幅提升转化率、利润率与用户体验。2025年,75%电商API将具备个性化能力,90%业务实现智能决策,AI与API的深度融合将成为未来电商竞争的关键基石。
|
3月前
|
机器学习/深度学习 人工智能 算法
巅峰对决,超三十万奖金等你挑战!第十届信也科技杯全球AI算法大赛火热开赛!
巅峰对决,超三十万奖金等你挑战!第十届信也科技杯全球AI算法大赛火热开赛!
|
3月前
|
传感器 数据采集 人工智能
AI是如何收集体育数据的?从摄像头到算法,揭秘赛场背后的“数字间谍网“!
⚽ 你是否好奇:AI如何知道哈兰德每秒跑多快?教练的平板为何比裁判还清楚谁偷懒?本文揭秘AI收集体育数据的“黑科技”:视觉追踪、传感器网络、数据清洗与高阶分析。从高速摄像机捕捉梅西肌肉抖动,到GPS背心记录姆巴佩冲刺速度;从表情识别判断装伤,到量子计算模拟战术可能,AI正让体育更透明、精准。未来已来,2030年世界杯或将实现AI替代球探、裁判甚至教练!你认为AI数据收集算侵犯隐私吗?最想统计哪些奇葩指标?留言互动吧!
|
4天前
|
边缘计算 人工智能 算法
AI在智慧能源管理中的边缘计算应用
AI在智慧能源管理中的边缘计算应用
52 13

热门文章

最新文章