Linux项目实战——五子棋(单机人人对战版)

2023-10-26

Linux操作系统项目实战——五子棋

GIF:

目录

           Linux操作系统项目——五子棋

一、问题导引:

二、实现要求:

三、五子棋原理:

1.落子数据信息保存载体:

2.落子思路:

3.判断“五子连珠”

四、项目实现步骤:

Ⅰ.创建目录及文件:

1.在Linux环境下创建名为Gobang的文件目录:

Ⅱ、输入Linux环境指令进入目录及文件:

Ⅲ、Linux环境编程实现:

1.顶层逻辑设计:

2.模块化设计:

3.联动模块组合封装:

        完整代码:

(1)game.c

(2)main.c

(3)game.h

(4)Makefile

 五、程序调试:

1.程序界面及说明:

2.测试用例:

六、程序功能扩展:

1.扩展思路:

2.扩展实现:

引入进度条:​

(1)更改代码:

(2)扩展效果演示:​

七、项目总结:

1.核心逻辑:

2.项目体现思想:

八、项目改编:

后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!                                                       ——By 作者:新晓·故知


一、问题导引:

在进行Linux入门学习后,通过运用Linux环境指令操作、Vim编辑器、学习五子棋的基本原理等,进行Linux环境下的简单的五子棋项目实现。

生活中的五子棋:

   

从上图可以看出,五子棋(这类棋)有先手、后手之分(当然也有禁手、俗手、妙手等),这里只进行简单的交互式、窗口化项目实现。(上图涉及GUI技术、图像渲染技术等,太过高深)

二、实现要求:

  • 熟悉Linux环境指令操作

  • Linux中相关开发工具的基本使用

  • 熟悉在Linux环境当中进行C编程

  • 掌握五子棋的基本原理

  • 编写五子棋程序的上层基本调用框架

  • 等等

说明:本篇博客采用VMware Workstation 16+CentOS7作为实现演示示例工具

三、五子棋原理:

1.落子数据信息保存载体:

需要记录每个玩家的落子位置,用来判断谁赢谁输。

可采用二维数组保存棋盘信息,棋盘上面的任何一个位置,里面可以放置三类信息:

  • 空(没有落子)

  • 玩家1的落子(黑子)

  • 玩家2的落子(白子)

2.落子思路:

1.如果下一步能赢,就走这一步

2.如果下一步会输,就阻止对方赢

3.统计棋子数决定在哪里落子。

其中 阻止对方赢,就是在对方能赢的点上落子,一般会有1到3个点。

3.判断“五子连珠”

下棋就是在二维数组中找对应的空位置,进行落子

落完子之后下来就要考虑该落子位置是否有”五子连珠“,进而进行输赢判定,每一次走棋,多会有四种情况:

  • 玩家1获胜

  • 玩家2获胜

  • 平局(棋盘满了等)

  • 未出结果(游戏继续)其中,“未出结果”游戏要继续,其他三种情况,游戏不用继续

四、项目实现步骤:

Ⅰ.创建目录及文件:

1.在Linux环境下创建名为Gobang的文件目录:

mkdir Gobang

(目录名随意,这里采用五子棋的英文命名目录)

2.创建多文本编辑:

touch Makefile

3.分别创建子文件:

touch game.h
touch game.c
touch main.c

 Ⅱ、输入Linux环境指令进入目录及文件:

Ⅲ、Linux环境编程实现:

1.顶层逻辑设计:

输入Linux指令:

(1)

vim Makefile

(2)

vim game.h

 (3)

vim game.c

(4)

vim main.c

2.模块化设计:

第一步. main构建游戏起始逻辑
第二步 . 构建游戏入口 Game() 函数

第三步 . 编写核心函数,定义全局游戏信息

第四步 . 编写 Makefifile ,完成第一步项目构建

第五步 . 实现游戏落子逻辑

第六步 . 实现游戏的显示逻辑

第七步 . 判定五子连珠然后判定游戏结果

3.联动模块组合封装:

完整代码:

(1)game.c

#include "game.h"

/*说明:
1.定义全局变量,保证代码逻辑尽可能简化,传参不那么复杂
2.代表玩家输入位置的最近的位置下标
3.不是说一定要定义成全局变量,而是为了减少传参等,降低复杂度*/
int x = 0;
int y = 0;

//按照x,y作为起点,按照特定的方向,求连续相对的最大格式
int ChessCount(int board[][COL], int row, int col, enum Dir d)
{
    int _x = x - 1;     //棋盘行标从1开始
    int _y = y - 1;     //棋盘列标从1开始
    //统计以当前棋子为起始位置8个方向的棋子数
    int count = 0;
    while (1) {
        switch (d) {
        case LEFT:
            _y--;
            break;
        case RIGHT:
            _y++;
            break;
        case UP:
            _x--;
            break;
        case DOWN:
            _x++;
            break;
        case LEFT_UP:
            _x--, _y--;
            break;
        case LEFT_DOWN:
            _x++, _y--;
            break;
        case RIGHT_UP:
            _x--, _y++;
            break;
        case RIGHT_DOWN:
            _x++, _y++;
            break;
        default:
            //Do Nothing
            break;
        }
        //坐标移动完成,一定要先保证没有越界
        if (_x < 0 || _x > row - 1 || _y < 0 || _y > col - 1) {
            break;
        }
        //合法
        //判断指定位置和原始位置的棋子是否相同,“连珠”就体现在这里
        if (board[x - 1][y - 1] == board[_x][_y]) {
            count++;
        }
        else {
            break;
        }
    }
    return count;
}
/*说明:IsOver的返回值有4种情况
1.NEXT:表明要继续
2.PLAYER1_WIN: 玩家1获胜
3.PLAYER2_WIN:玩家2获胜
4.DRAW: 平局*/
int IsOver(int board[][COL], int row, int col)
{
    /*棋子统计逻辑
    1.以落子位置作为起点,进行8个方向的相同玩家方棋子统计
      落子位置下标与方向统计有很强的关联性
    2.当玩家2落子,说明玩家1没有赢,因此需要先走一步就先判断一次,走到当前才有可能赢
    3.+1是统计被忽略的当前落子*/
    int count1 = ChessCount(board, row, col, LEFT) + ChessCount(board, row, col, RIGHT) + 1; 
    int count2 = ChessCount(board, row, col, UP) + ChessCount(board, row, col, DOWN) + 1; 
    int count3 = ChessCount(board, row, col, LEFT_UP) + ChessCount(board, row, col, RIGHT_DOWN) + 1; 
    int count4 = ChessCount(board, row, col, LEFT_DOWN) + ChessCount(board, row, col, RIGHT_UP) + 1; 
    //判断五子连珠 
    if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5) {
        //有五子连珠,则一定有人赢
        //x, y保存的是玩家最近一次落子
        if (board[x - 1][y - 1] == PLAYER1) {
            return PLAYER1_WIN;
        }
        else {
            return PLAYER2_WIN;
        }
        //这个if-else语句可换成 return board[x-1][y-1];
    }
    int i = 0;
    for (; i < row; i++) {
        int j = 0;
        for (; j < col; j++) {
            if (board[i][j] == 0) {
                return NEXT;
            }
        }
    }

    return DRAW;
}

void ShowBoard(int board[][COL], int row, int col)
{ 
    //C语言清屏,减少每次棋盘打印,实现原地刷新效果
   
    printf("\e[1;1H\e[2J");  //Linux环境下,C语言实现清屏
    printf("\n");
    //将数组内容,进行可视化
    printf("  "); //优化棋盘使其美观
    int i = 1;
    for (; i <= col; i++) {
        printf("%3d", i);
    }
    printf("\n");

    for (i = 0; i < row; i++) {
        int j = 0;
        printf("%2d ", i + 1);
        for (; j < col; j++) {
            if (board[i][j] == 0) {
                printf(" . ");
            }
            else if (board[i][j] == PLAYER1) {
                printf("● ");
            }
            else {
                printf("○ ");
            }
        }
        printf("\n");
    }
}

void PlayerMove(int board[][COL], int row, int col, int who)
{
    //判断玩家的落子位置:合法性、去重
    while (1) {
        printf("玩家[%d] 请输入你的落子坐标: ", who);
        scanf("%d %d", &x, &y);
        //判断输入坐标的合法性,行列
        if (x < 1 || x > row || y < 1 || y > col) {
            printf("位置错误!\n");
            continue;
        }
        //在数组当当中的下标值
        else if (board[x - 1][y - 1] != 0) {
            printf("此位置已被占用!\n");
            continue;
        }
        else {
            //合法性,去重
            board[x - 1][y - 1] = who;
            break;
        }
    }
}

void Game()
{ 
    int board[ROW][COL];   //在函数中定义数组,其实是一个随机数,需要清空以确定坐标数
    /*1.采用ROW,COL型的二维数组,进行游戏信息的保存
    2.全部清空有许多种做法:采用双循环,采用Init函数等                    
    3.注:memset按照字节为单位操作,menset内存设置
    4.使用memset清空,默认棋盘数据都是0*/
    memset(board, 0, sizeof(board));
    int result = NEXT;
    do {
        ShowBoard(board, ROW, COL);          //显示棋盘
        PlayerMove(board, ROW, COL, PLAYER1);//玩家1先走,也可以随机选择先走——“先手”
        result = IsOver(board, ROW, COL);    //判断游戏是否结束
        if (NEXT != result) {
            break;
        }
        ShowBoard(board, ROW, COL);
        PlayerMove(board, ROW, COL, PLAYER2);
        result = IsOver(board, ROW, COL);
        if (NEXT != result) {
            break;
        }
    } while (1);
    //Player1 win, Player2 win, Draw
    switch (result) {
         case PLAYER1_WIN:
            printf("恭喜玩家1获胜!\n");
            break;
         case PLAYER2_WIN:
            printf("恭喜玩家2获胜!\n");
             break;
         case DRAW:
            printf("游戏平局,和气生财!\n");
             break;
         default:
            //这种情况不会出现,do nothing!
            break;
    }
    //ShowBoard(board, ROW, COL);
}

(2)main.c

#include "game.h"
//游戏菜单
void Menu()
{
    printf("############################\n");
    printf("## 1. 开始        0. 退出 ##\n");
    printf("############################\n");
    printf("                 ————By 作者:新晓·故知\n");
    printf("请选择:");
}

int main()
{
    int quit = 0;                 //用来判断游戏是否退出
    int select = 0;
    //使得游戏可以多次进行
    while (!quit) {
        Menu();                  //游戏菜单
        scanf("%d", &select);
        switch (select) {        //根据用户选择,执行合适的游戏逻辑代码
        case 1:
            Game();
            break;
        case 0:
            quit = 1;
            printf("退出游戏,再见!\n");
            break;
        default:
            printf("输入错误,请重新输入!\n");
            break;
        }
    }
    return 0;
}

(3)game.h

#pragma once

#include <stdio.h>
#include <string.h>


//增强代码可维护性
#define ROW 10
#define COL 10

#define PLAYER1 1  //玩家1编号,默认棋盘数据是0,玩家1落子,该位置被改成1
#define PLAYER2 2  //玩家2编号,默认棋盘数据是0,玩家2落子,该位置被改成2

#define NEXT        0   //游戏继续
#define PLAYER1_WIN 1   
#define PLAYER2_WIN 2
#define DRAW        3

//使用枚举,代表方向
enum Dir {
    LEFT,
    RIGHT,
    UP,
    DOWN,
    LEFT_UP,
    LEFT_DOWN,
    RIGHT_UP,
    RIGHT_DOWN
};

void Menu();   //菜单功能声明
void Game();   //游戏功能声明

(4)Makefile

game:game.c main.c ProcBar.c                               
    gcc $^ -o $@ 
 
.PHONY:clean                                             
clean:                                                      
    rm -f game

 五、程序调试:

1.程序界面及说明:

(1)进入游戏主程序 

(2)默认玩家1为先手

 (3)输入玩家坐标

2.测试用例:

(1)输入错误坐标测试:

(2)输入已被占用坐标测试

(3)实现“五子连珠”判断:

六、程序功能扩展:

1.扩展思路:

1.引入进度条

2.尝试人机对战
3.功能扩展:颜色提示,步数记录,先手随机交换等
4.网络版本
5. 将走过的步骤保存在文件里,实现自动下棋,以及扩展至数据库

6.nucurses实现鼠标点击

等等

2.扩展实现:

引入进度条:

(1)更改代码:

这里我们需要像之前那样创建ProcBar的文件,这里就直接在Gobang目录下创建ProcBar项目:

touch ProcBar.h
touch ProcBar.c

编辑ProcBar内容:

vim ProcBar.h
vim ProcBar.c

 这个内容见博客链接:(在这篇博客的最后一项:Linux第一个小程序——ProcBar(进度条))<Linux常用开发工具使用(yum、vim、gcc/g++、gdb、make/Makefile等)>——《Linux》_新晓·故知的博客-CSDN博客

 

在Gobang的主程序里main.c 加入ProcBar的调用:

vim main.c

把process_bar();添加到 main.c。

#include "game.h"
//游戏菜单
void Menu()
{
    printf("############################\n");
    printf("## 1. 开始        0. 退出 ##\n");
    printf("############################\n");
    printf("                 ————By 作者:新晓·故知\n");
    printf("请选择:");
}

int main()
{
    int quit = 0;                 //用来判断游戏是否退出
    int select = 0;

    process_bar();

    //使得游戏可以多次进行
    while (!quit) {
        Menu();                  //游戏菜单
        scanf("%d", &select);
        switch (select) {        //根据用户选择,执行合适的游戏逻辑代码
        case 1:
            Game();
            break;
        case 0:
            quit = 1;
            printf("退出游戏,再见!\n");
            break;
        default:
            printf("输入错误,请重新输入!\n");
            break;
        }
    }
    return 0;
}

然后修改其他地方,进行联合编译:

Makefile: 

game:game.c main.c ProcBar.c
   gcc $^ -o $@

.PHONY : clean
clean :
    rm - f game

main.c:

#include "game.h"
#include "ProcBar.h"
//游戏菜单
void Menu()
{
    printf("############################\n");
    printf("## 1. 开始        0. 退出 ##\n");
    printf("############################\n");
    printf("请选择:");
}

(2)扩展效果演示:

七、项目总结:

1.核心逻辑:

1.基于二维数组保存数据信息

2.将二维数组可视化

3.每次落子存入数据都需要进行更新可视化

4.落子和判断是强相关的,换句话说,玩家1落子的时候说明上一步玩家二没有赢,每个玩家落子,立即判断输赢

2.项目体现思想:

从五子棋项目中体现出对大型项目先进行顶层逻辑设计,再将任务模块化,最后联动组合封装优化。

八、项目改编:

将Linux环境下的C语言项目改编在Windows环境下,实现运行!借助C语言的跨平台性,进行跨平台改动。

后记:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!
                                                                                    ——By 作者:新晓·故知

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux项目实战——五子棋(单机人人对战版) 的相关文章

  • `/dev/urandom` 适合模拟目的吗?

    似乎在类 Unix 系统中使用纯 C fread from dev urandom是提取高质量随机字节的最简单方法 我需要运行一个每秒需要大约 10k 32 位随机数的模拟 并且可能会运行几天 是 dev urandom可以用于此目的吗 当
  • 为什么我的 sed 命令在使用变量时失败?

    使用 bash 我尝试插入日期变量并搜索该日期的日志文件 然后将输出发送到文件 如果我像这样对日期进行硬编码 它会起作用 sed n Nov 22 2010 p file gt log file 但如果我这样做就会失败 date Nov 2
  • Ruby 脚本即服务

    嗯 标题说明了一切 我有一个 ruby 脚本 我想在我的 Linux 机器上作为一项服务 我可以启动和停止 运行 我找到了如何在 Windows 上执行此操作here https stackoverflow com questions 16
  • 如何在生产环境中运行 spring boot 可执行 jar?

    Spring Boot 的首选部署方法是通过内部包含 tomcat 的可执行 jar 文件 它是从一个简单的开始java jar myapp jar 现在 我想将该 jar 部署到 EC2 上的 Linux 服务器上 我是否遗漏了某些内容
  • 来自外部 .diff 文件的交互式补丁

    Linux 是否有命令或程序允许交互式地修补源代码 在屏幕上打印每个块并在将其应用到文件之前等待确认 就像是git add p 但是从另一个 diff 文件中进行更改 您始终可以在 shell ruby python 中编写脚本 逐行读取该
  • 安装pipenv导致pip3无法使用

    我安装了pipenv using pip3 install pipenv 这给了我错误ImportError cannot import name main 为了解决这个错误我遵循这些说明 https stackoverflow com q
  • find 命令的“exec”功能可以在后台启动程序吗?

    我想做这样的事情 find iname Advanced Linux Program exec kpdf 可能的 还有其他类似的方法吗 首先 它不会像你输入的那样工作 因为 shell 会将其解释为 find iname Advanced
  • 从该共享库中查找加载的共享库的位置?

    从共享库中的函数 在正在运行的进程 用 C 编写 内 我如何发现该共享库是从哪里加载的 我找到的所有答案都涉及使用诸如ldd在命令行中 或者通过查看 proc self maps 在 Win32 上 我只需使用GetModuleFileNa
  • Gnu 时间和格式化输出

    我想使用 gnu time 来测量一些小 c 程序的运行时间 人 中写道 f FORMAT format FORMAT Use FORMAT as the format string that controls the output of
  • 在 Linux 上的 makefile 和 Makefile 之间进行选择

    我想在一个目录中同时使用 Makefile 和 makefile 进行 make 默认情况下 它将执行makefile 我可以选择执行 Makefile 吗 提前致谢 最简单的选择是使用 f make f Makefile From man
  • Linux环境下串口数据转换为TCP/IP

    我需要从Linux系统的串口获取数据并将其转换为TCP IP发送到服务器 这很难做到吗 我有一些基本的编程经验 但对 Linux 的经验不多 有没有开源应用程序可以做到这一点 在 Linux 中您不需要编写程序来执行此操作 只是pipe h
  • 你能在 MS Windows 上用 Python 将 stdin 作为文件打开吗?

    在 Linux 上 我使用 subbprocess Popen 来运行应用程序 该应用程序的命令行需要输入文件的路径 我了解到我可以将路径 dev stdin 传递到命令行 然后使用 Python 的 subproc stdin write
  • 堆内存和Slab分配

    我很困惑heap and free list 我有几个问题 我对C中malloc的工作原理有自己的理解 如果我错了 请纠正我 堆内存是否被组织为数据的链表 空闲列表 块 堆内存和空闲列表有区别吗 我对存储分配的理解 有待改进 当我们调用ma
  • 如何重新安装最新的cmake版本?

    我想在Linux环境下安装cmake的最新版本 我安装了 cmake 3 5 版 但某些应用程序不支持 我尝试通过卸载当前版本来升级它 但是当我使用 sudo apt get install cmake 重新安装时 我重新安装了相同的版本
  • 如何取消 Vim 中的粘贴操作?

    每当我不小心在 Putty 中右键单击 打开 Vim 时 我的剪贴板上就有相当多的文本 并且 Vim 启动了粘贴操作 该操作已经持续了大约十分钟 我不想丢失未保存的工作 有没有办法指示 Vim 停止粘贴文本 If you re in nor
  • Shell 脚本对文件进行计数,然后删除最旧的文件

    我是 shell 脚本新手 所以我需要一些帮助 我有一个充满备份的目录 如果我有超过 10 个备份文件 我想删除最旧的文件 以便仅留下 10 个最新的备份文件 到目前为止 我知道如何计算文件数 这看起来很简单 但是如果计数超过 10 我该如
  • linux命令行:如何简单地将任意字符串输入管道?

    我正在寻找一个非常简单的技巧 假设文件中error txt 有一个很长的字符串 errorMessage key1 some message key2 message 2 由于它的格式不适合读者 如果我想在终端中以格式良好的形式查看它 我可
  • 在 Alpine Docker 容器上安装 OpenSSH

    第一次运行 alpine docker 容器并尝试 openssh 安装时 会发生以下情况 ole T docker run it rm alpine bin ash apk add openssh WARNING Ignoring APK
  • x86 平台中的 KVM 影子页表处理

    据我了解 在没有硬件支持来宾虚拟到主机物理地址转换的处理器上 KVM 使用影子页表 当来宾操作系统修改其页表时 会构建和更新影子页表 硬件中有没有专门的指令 以x86为参考 来修改页表 除非有特殊说明 否则不会对VMM 造成陷阱 Linux
  • 检查 VT-x 是否已激活而无需在 Linux 中重新启动?

    我有一台配备 Intel Core i5 M 450 2 40GHz 的笔记本电脑 显然有 VT x 但没有 VT d 我有 Ubuntu 12 04 32 位 但希望在其上运行基于虚拟 64 位终端的 Linux 我如何知道 BIOS 是

随机推荐

  • 虚拟机配置

    1 Finalshell下载 Mac http www hostbuf com downloads finalshell install pkg Windows http www hostbuf com downloads finalshe
  • clang static analyzer源码分析(二)

    引子 在clang static analyzer源码分析 一 中我们简单介绍了 AnalysisConsumer 这个类以及基于AST树的语法层级的代码检查 今天简单介绍下 PathSensitiveChecks 的概念 以及如何对cla
  • STL:vectoer

    首先包含头文件 include
  • 重参数化技巧:高斯分布采样

    1 高斯分布采样 我们现在得到了有样本X得到的分布X N mu sigma 2 通过采样我们得到确定的隐变量向量 从而作为解码器的输入 采样这个操作本身是不可导的 但是我们可以通过重参数化技巧 将简单分布的采样结果变换到特定分布中
  • Fabric上搭建Hyperledger caliper进行性能测试

    Fabric介绍 推荐文章 Hyperledger 超级账本 是Linux基金会旗下的项目 Fabric是Hyperledger项目里最早也是目前应用最广泛的区块链项目 最初由IBM开发 后来捐助给基金会 是一个开源的企业级需要许可的分布式
  • Git Gui客户端软件连接及上传文件

    1 下载客户端软件 2 上传那个文件就在哪个文件下 git gui here 之后选择当前的目录创建仓库 3 关于操作在一下连接有 https blog csdn net qq 15509267 article details 836170
  • 关于mybatis使用pageHelper分页插件问题

    关于mybatis使用PageHelper分页插件冲突以及解决方案 分页插件其实 可以提高我们的开发效率 如果我们自己手写 1会嫌麻烦 2需要写两条一条写count一条写list 虽然他底层也是这么实现的 但是不需要我们手动来写 好的工具能
  • 大数据的入门级学习

    大数据方向的工作目前分为三个主要方向 01 大数据工程师 02 数据分析师 03 大数据科学家 04 其他 数据挖掘本质算是机器学习 不过和数据相关 也可以理解为大数据的一个方向吧 由于本人曾是大数据工程师的角色 我就这个方向做一些介绍 本
  • 从0开始使用vue-element-admin

    目录 安装node js及npm 安装nrm 安装vscode 汉化 推荐安装一些好用的扩展 安装vue element admin 框架登陆原理简单分析 本教程经亲测支持最新版4 0 1vue element admin 安装node j
  • RabbitMQ宕机后,消息100%不会丢失吗

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 这篇文章 给不太熟悉MQ技术的同学 介绍一个生产环境中可能会遇到的问题 目前为止 你的RabbitMQ部署在线上服务器了 对吧 然后订单服务和仓储服务都可以基于Rab
  • 统计学习方法笔记(二)感知机

    感知机于1957年由Rosenblatt提出 是一种线性分类模型 属于判别模型 直接学习判别函数 是神经网络和支持向量机的基础 对于感知机的学习推导首先要知道他的模型是什么 然后是学习策略 损失函数 最后是学习算法 1 感知机的模型 假设空
  • vue设置全局时间格式化

    vue前台需要用户能看得懂的时间格式如常见的 2021 03 10 12 02 35 但是后台数据库则需要时间格式如LocalDateTime 2021 03 10T15 31 01 或者Date类型的 如果数据不经过处理 直接显示 肯定可
  • 如何在Windows上搭建web站点,并发布到公网?1-1

    系列文章 Windows用户如何安装使用cpolar内网穿透工具 如何在Windows上搭建web站点 并发布到公网 1 1 如何在Windows上搭建web站点 并发布到公网 2 2 如何在Windows下搭建WordPress博客站点
  • maven 引入qrcode.jar

    mvn install install file Dfile e QRCode jar DgroupId QRCode DartifactId QRCode Dversion 3 0 Dpackaging jar 3 在pom xml中增加
  • 逆变器STM32储能逆变器 BOOST 全桥 基于STM32F103设计,具有并网充电、放电

    逆变器STM32储能逆变器 BOOST 全桥 基于STM32F103设计 具有并网充电 放电 并网离网自动切换 485通讯 在线升级 风扇智能控制 提供过流 过压 短路 过温等全方位保护 基于arm的方案区别于dsp 有PCB 原理图及代码
  • 图像质量评估指标——SSIM介绍及计算方法

    图像质量评估指标 SSIM介绍及计算方法 SSIM全称为Structural Similarity 即结构相似性 用于评估两幅图像相似度的指标 常用于衡量图像失真前与失真后的相似性 也用于衡量模型生成图像的真实性 如图像去雨 图像去雾 图像
  • vue 集成ag-grid 组件,通过筛选条件操作列显示与隐藏

    关键代码 this columnApi setColumnVisible item false 此处item的位置 为ag grid列数据里面的colid 如无此项 可以用field的值来代替
  • 使用IBM SPSS Modeler进行随机森林算法预测

    IBM SPSS产品系列最主要的两款软件为IBM SPSS Statistics和IBM SPSS Modeler IBM SPSS Statistics主要用于统计分析 如均值比较 方差分析 相关分析 回归分析 聚类分析 因子分析 非参数
  • GDB交叉编译与问题解决

    GDB使用 交叉编译 Program received signal SIGILL Illegal instruction Program received signal SIGPIPE Broken pipe 交叉编译 bin bash
  • Linux项目实战——五子棋(单机人人对战版)

    Linux操作系统项目实战 五子棋 GIF 目录 Linux操作系统项目 五子棋 一 问题导引 二 实现要求 三 五子棋原理 1 落子数据信息保存载体 2 落子思路 3 判断 五子连珠 四 项目实现步骤 创建目录及文件 1 在Linux环境