文章目录

  • 前言
  • 一、源代码
  • 二、整体框架分析
    • 1.初始化棋盘
    • 2.进行对局
    • 3.寻找最佳下子位置
    • 4.实时判断棋局状况
  • 三、 总结

前言

近期在准备计算机博弈大赛,前两天把沈阳航空航天大学2017年的全国计算机博弈大赛五子棋的代码找了出来,研究了一下,觉得还是学到了很多东西的,以下是我自己的一些对于这套代码的理解,如有不对的地方,欢迎斧正!


一、源代码

代码下载地址:github: 五子棋源代码.
(源代码有些地方过于冗长,代码稍有改动)

#include "stdio.h"
#include "math.h"
#include "windows.h"
#include "time.h"//使用当前时钟做种子
#include "conio.h"#define N 15       //定义棋盘大小
#define M N+8      //定义数据棋盘大小int  chess[N][N];//棋盘,用于储存下子位置
int  count[M][M];//数据棋盘,用于储存下子位置和盘外数据
char buffer[N * 2 - 1][N * 4 - 3];//缓冲器,用于储存下子位置,盘外数据,和棋盘符号
long sum[M][M] = { {0} };//得分棋盘,储存得分情况
int  p[20][5];//储存该位置的所有可能的五连珠情况int  player = 1, ai = 2, error = -1;
int  num;//双方回合总数
int  now;//设置下棋标志
int  flag0;//确定己方已下子
int  gs;//游戏结束标志// 基础函数
void RunGame();//进行整个对局
int  Menu();//设置开始菜单
void Initialize();//初始化棋盘,数据棋盘,和缓冲器
void Print(int x, int y);//将数据写入数据棋盘,和缓冲器
void Buf_Display();//利用双缓冲将缓冲器数据输出到屏幕
int  Judge_Display();//输出胜负情况
//双方对局函数
void PGame();//玩家对局函数
void CGame();//电脑对局函数
//输入函数
void Input(int *x, int *y);//键盘方向键控制,空格键输入
void Mark(int x0, int y0, int x, int y);//标记下子位置
//电脑判断函数
int  Basic_condition(int x, int y);//判断下子位置是否出界
void Find_point(int *pp, int *qq);//找到最佳性最优的下子位置
int  JUDGE(int x, int y);//判断胜负
void Grade();//计算所有位置的得分
void Base(int i, int j);//坐标为(i-4,j-4)的所有五连珠情况
long Assessment(int num1, int num2);//评分标准//主程序
int main()
{system("title 简易五子棋");//设置标题system("mode con cols=58 lines=29");//设置窗口大小system("color E0");//设置颜色Initialize();//初始化棋盘,数据棋盘,和缓冲器RunGame();//进行整个对局return 0;
}/***********************************************************************************************************************************************************/
void RunGame()//进行整个对局
{switch (Menu()){case 1:while (1){PGame();//玩家对局函数if (Judge_Display()){break;//对局结束}CGame();//电脑对局函数if (Judge_Display()){break;//对局结束}}//whilebreak;case 2:now = ai;count[N / 2 + 4][N / 2 + 4] = now; chess[N / 2][N / 2] = now;Print(N / 2, N / 2);//将数据写入数据棋盘,和缓冲器num++;while (1){PGame();//玩家对局函数if (Judge_Display()){break;//对局结束}CGame();//电脑对局函数if (Judge_Display()){break;//对局结束}}//whilebreak;case 3:now = 1;count[N / 2 + 4][N / 2 + 4] = now; chess[N / 2][N / 2] = now;Print(N / 2, N / 2);//将数据写入数据棋盘,和缓冲器num++;while (1){CGame();//电脑对局函数if (Judge_Display()){break;//对局结束}}break;default:;}
}
/***********************************************************************************************************************************************************/int Menu()//设置开始菜单
{int x;printf("方向键移动,空格键确定\n");printf("1、玩家先手\n");printf("2、玩家后手\n");printf("3、电脑自对弈\n");scanf("%d", &x);return x;
}void Initialize()//初始化棋盘,数据棋盘,和缓冲器
{int i, j;//初始化数据棋盘for (i = 0; i < M; i++){for (j = 0; j < M; j++){if ((i < 4 || i >= M - 4) && (j < 4 || j >= M - 4)){count[i][j] = error;}}}//初始化缓冲器for (i = 0; i < N * 2 - 1; i++){for (j = 0; j < N * 4 - 3; j++){if (i == 0 && j == 0)//以下为边缘棋盘样式buffer[i][j] = 'a';//"┏";else if (i == 0 && j == (N * 4 - 3) - 1)buffer[i][j] = 'b';//"┓";else if (i == (N * 2 - 1) - 1 && j == (N * 4 - 3) - 1)buffer[i][j] = 'c';//"┛";else if (i == (N * 2 - 1) - 1 && j == 0)buffer[i][j] = 'd';//"┗";else if (i == 0 && j % 4 == 0)buffer[i][j] = 'e';//"┯";else if (i == (N * 2 - 1) - 1 && j % 4 == 0)buffer[i][j] = 'f';//"┷";else if (i % 2 == 0 && j == 0)buffer[i][j] = 'g';//"┠";else if (i % 2 == 0 && j == (N * 4 - 3) - 1)buffer[i][j] = 'h';//"┨";else if ((i == 0 || i == (N * 2 - 1) - 1) && (j / 2) % 2 != 0)buffer[i][j] = 'i';//"━";else if (i != 0 && i != (N * 2 - 1) - 1 && i % 2 == 0 && (j / 2) % 2 != 0)buffer[i][j] = 'j';//"—";else if (i % 2 != 0 && (j == 0 || j == (N * 4 - 3) - 1))buffer[i][j] = 'k';//"┃";else if (i % 2 != 0 && j != 0 && j != (N * 4 - 3) - 1 && j % 4 == 0)buffer[i][j] = 'l';//"│";else if (i != 0 && j != 0 && i != (N * 2 - 1) - 1 && j != (N * 4 - 3) - 1 && i % 2 == 0 && j % 4 == 0)buffer[i][j] = 'm';//中间的空位"┼"}}
}void Print(int x, int y)//将数据写入数据棋盘,和缓冲器
{count[x + 4][y + 4] = chess[x][y];buffer[x * 2][y * 4] = chess[x][y] + 48;//将整型数据转化为字符型数据
}
void PGame()//玩家对局函数
{static int Px0 = N / 2, Py0 = N / 2, Px = N / 2, Py = N / 2;now = 1;do {Mark(Px0, Py0, Px, Py);//标记下子位置Buf_Display();//将缓冲器数据输出到屏幕Px0 = Px; Py0 = Py;Input(&Px, &Py);} while (!(chess[Px][Py] && flag0 == 1));Print(Px, Py);//将数据写入数据棋盘,和缓冲器num++;gs = JUDGE(Px + 4, Py + 4);
}
void CGame()//电脑对局函数
{static int Cp = N / 2, Cq = N / 2, Cp0, Cq0;Buf_Display();//将缓冲器数据输出到屏幕Grade();//计算所有位置的得分Cp0 = Cp; Cq0 = Cq;//记录上一次电脑下子位置Find_point(&Cp, &Cq);//找到最佳性最优的下子位置now = 3 - now;chess[Cp - 4][Cq - 4] = now;Mark(Cp0 - 4, Cq0 - 4, Cp - 4, Cq - 4);//标记下子位置Print(Cp - 4, Cq - 4);//将数据写入数据棋盘,和缓冲器num++;gs = JUDGE(Cp, Cq);
}
void Input(int *x, int *y)//键盘方向键控制,空格键输入
{int input;flag0 = 0;input = _getch();//获得第一次输入信息if (input == 0x20 && !chess[*x][*y])//判断移动光标后,玩家是否下子{chess[*x][*y] = player;flag0 = 1;}else if (input == 0xE0)//如果按下的是方向键,会填充两次输入,第一次为0xE0表示按下的是控制键{input = _getch();//获得第二次输入信息switch (input)//判断方向键方向并移动光标位置{case 0x48: (*x)--; break;case 0x4B: (*y)--; break;case 0x50: (*x)++; break;case 0x4D: (*y)++; break;}//switchif (*x < 0)   (*x) = N - 1;//如果光标位置越界则移动到对侧if (*y < 0)   (*y) = N - 1;if (*x > N - 1) (*x) = 0;if (*y > N - 1) (*y) = 0;}
}void Mark(int x0, int y0, int x, int y)//标记己方下子位置
{x0 = x0 * 2; y0 = y0 * 4;buffer[x0 - 1][y0 - 2] = ' ';buffer[x0 - 1][y0 + 2] = ' ';buffer[x0 + 1][y0 + 2] = ' ';buffer[x0 + 1][y0 - 2] = ' ';x = x * 2; y = y * 4;buffer[x - 1][y - 2] = 'a';buffer[x - 1][y + 2] = 'b';buffer[x + 1][y + 2] = 'c';buffer[x + 1][y - 2] = 'd';if (y == (N * 4 - 3) - 1)//解决“当光标移动到最右侧时,光标发生错位”{buffer[x - 1][y + 2] = ' ';buffer[x + 1][y + 2] = ' ';}
}int Basic_condition(int x, int y)//判断下子位置是否出界
{if (x >= 4 && x < M - 4 && y >= 4 && y < M - 4){return 1;}else{return 0;}
}void Find_point(int *pp, int *qq)//找到最佳性最优的下子位置
{int i, j, flag = 0;//flag为结束标志long t = 0;int r, c = 0, sumed[N*N][2];//寻找第一个未下子位置对应的sum值for (i = 4; i < M - 4 && flag == 0; i++){for (j = 4; j < M - 4 && flag == 0; j++){if (!chess[i - 4][j - 4]){t = sum[i][j];flag = 1;}}}//for//寻找最大的sum值for (i = 4; i < M - 4; i++){for (j = 4; j < M - 4; j++){if (!chess[i - 4][j - 4] && sum[i][j] > t){t = sum[i][j];}}}//for//等于怎么办//存储所有的最大sum值for (i = 4; i < M - 4; i++){for (j = 4; j < M - 4; j++){if (!chess[i - 4][j - 4] && sum[i][j] == t){sumed[c][0] = i;sumed[c][1] = j;c++;}}}//forsrand((unsigned)time(NULL)); //初始化随机数//随机选用最大sum值中的一组数据r = rand() % c;*pp = sumed[r][0];*qq = sumed[r][1];
}int JUDGE(int x, int y)//判断胜负,返回1赢,返回0无
{int a = 1, b = 1, c = 1, d = 1, i;//累计横竖正斜反斜四个方向的连续相同棋子数目for (i = 1; i < 5; i++)if (y + i < M - 4 && count[x][y + i] == now)a++; else break;//向下检查for (i = 1; i < 5; i++)if (y - i >= 4 && count[x][y - i] == now)a++; else break;//向上检查if (a >= 5)return now;//若达到5个则判断当前走子玩家为赢家for (i = 1; i < 5; i++)if (x + i < M - 4 && count[x + i][y] == now)b++; else break;//向右检查for (i = 1; i < 5; i++)if (x - i >= 4 && count[x - i][y] == now)b++; else break;//向左检查if (b >= 5)return now;//若达到5个则判断当前走子玩家为赢家for (i = 1; i < 5; i++)if (x + i < M - 4 && y + i < M - 4 && count[x + i][y + i] == now)c++; else break;//向右下检查for (i = 1; i < 5; i++)if (x - i >= 4 && y - i >= 4 && count[x - i][y - i] == now)c++; else break;//向左上检查if (c >= 5)return now;//若达到5个则判断当前走子玩家为赢家for (i = 1; i < 5; i++)if (x + i < M - 4 && y - i >= 4 && count[x + i][y - i] == now)d++; else break;//向右上检查for (i = 1; i < 5; i++)if (x - i >= 4 && y + i < M - 4 && count[x - i][y + i] == now)d++; else break;//向左下检查if (d >= 5)return now;//若达到5个则判断当前走子玩家为赢家return 0;//若没有检查到五连珠,则返回0表示还没有玩家达成胜利
}void Grade()//计算所有位置的得分
{int i, j, m, n;int num1, num2;for (i = 4; i < M - 4; i++){for (j = 4; j < M - 4; j++){if (!chess[i - 4][j - 4]){sum[i][j] = 0;//循环初始化sum[i][j]Base(i, j);//坐标为(i-4,j-4)的所有五连珠情况for (m = 0; m < 20; m++){num1 = 0; num2 = 0;for (n = 0; n < 5; n++){if (p[m][n] == now)num1++;else if (p[m][n] == 3 - now)num2++;else if (p[m][n] == error){num1 = error; num2 = error;break;}}sum[i][j] += Assessment(num1, num2);}}}}
}void Base(int i, int j)//坐标为(i-4,j-4)的所有五连珠情况
{//左上->右下p[0][0] = count[i - 4][j - 4]; p[0][1] = count[i - 3][j - 3]; p[0][2] = count[i - 2][j - 2]; p[0][3] = count[i - 1][j - 1]; p[0][4] = count[i][j];p[1][0] = count[i - 3][j - 3]; p[1][1] = count[i - 2][j - 2]; p[1][2] = count[i - 1][j - 1]; p[1][3] = count[i][j]; p[1][4] = count[i + 1][j + 1];p[2][0] = count[i - 2][j - 2]; p[2][1] = count[i - 1][j - 1]; p[2][2] = count[i][j]; p[2][3] = count[i + 1][j + 1]; p[2][4] = count[i + 2][j + 2];p[3][0] = count[i - 1][j - 1]; p[3][1] = count[i][j]; p[3][2] = count[i + 1][j + 1]; p[3][3] = count[i + 2][j + 2]; p[3][4] = count[i + 3][j + 3];p[4][0] = count[i][j]; p[4][1] = count[i + 1][j + 1]; p[4][2] = count[i + 2][j + 2]; p[4][3] = count[i + 3][j + 3]; p[4][4] = count[i + 4][j + 4];//上->下p[5][0] = count[i - 4][j]; p[5][1] = count[i - 3][j]; p[5][2] = count[i - 2][j]; p[5][3] = count[i - 1][j]; p[5][4] = count[i][j];p[6][0] = count[i - 3][j]; p[6][1] = count[i - 2][j]; p[6][2] = count[i - 1][j]; p[6][3] = count[i][j]; p[6][4] = count[i + 1][j];p[7][0] = count[i - 2][j]; p[7][1] = count[i - 1][j]; p[7][2] = count[i][j]; p[7][3] = count[i + 1][j]; p[7][4] = count[i + 2][j];p[8][0] = count[i - 1][j]; p[8][1] = count[i][j]; p[8][2] = count[i + 1][j]; p[8][3] = count[i + 2][j]; p[8][4] = count[i + 3][j];p[9][0] = count[i][j]; p[9][1] = count[i + 1][j]; p[9][2] = count[i + 2][j]; p[9][3] = count[i + 3][j]; p[9][4] = count[i + 4][j];//右上->左下p[10][0] = count[i - 4][j + 4]; p[10][1] = count[i - 3][j + 3]; p[10][2] = count[i - 2][j + 2]; p[10][3] = count[i - 1][j + 1]; p[10][4] = count[i][j];p[11][0] = count[i - 3][j + 3]; p[11][1] = count[i - 2][j + 2]; p[11][2] = count[i - 1][j + 1]; p[11][3] = count[i][j]; p[11][4] = count[i + 1][j - 1];p[12][0] = count[i - 2][j + 2]; p[12][1] = count[i - 1][j + 1]; p[12][2] = count[i][j]; p[12][3] = count[i + 1][j - 1]; p[112][4] = count[i + 2][j - 2];p[13][0] = count[i - 1][j + 1]; p[13][1] = count[i][j]; p[13][2] = count[i + 1][j - 1]; p[13][3] = count[i + 2][j - 2]; p[13][4] = count[i + 3][j - 3];p[14][0] = count[i][j]; p[14][1] = count[i + 1][j - 1]; p[14][2] = count[i + 2][j - 2]; p[14][3] = count[i + 3][j - 3]; p[14][4] = count[i + 4][j - 4];//左->右p[15][0] = count[i][j - 4]; p[15][1] = count[i][j - 3]; p[15][2] = count[i][j - 2]; p[15][3] = count[i][j - 1]; p[15][4] = count[i][j];p[16][0] = count[i][j - 3]; p[16][1] = count[i][j - 2]; p[16][2] = count[i][j - 1]; p[16][3] = count[i][j]; p[16][4] = count[i][j + 1];p[17][0] = count[i][j - 2]; p[17][1] = count[i][j - 1]; p[17][2] = count[i][j]; p[17][3] = count[i][j + 1]; p[17][4] = count[i][j + 2];p[18][0] = count[i][j - 1]; p[18][1] = count[i][j]; p[18][2] = count[i][j + 1]; p[18][3] = count[i][j + 2]; p[18][4] = count[i][j + 3];p[19][0] = count[i][j]; p[19][1] = count[i][j + 1]; p[19][2] = count[i][j + 2]; p[19][3] = count[i][j + 3]; p[19][4] = count[i][j + 4];
}long Assessment(int num1, int num2)//评分标准
{if (num2 == 0)//判断电脑五元组得分{switch (num1){case 0: return 7;case 1: return 35;case 2: return 800;case 3: return 15000;case 4: return 800000;}}if (num2 != 0 && num1 == 0)//判断玩家五元组得分{switch (num2){case 1: return 15;case 2: return 400;case 3: return 1800;case 4: return 100000;}}return 0;
}void Buf_Display()//利用双缓冲将缓冲器数据输出到屏幕
{int i, j;//创建屏幕缓冲区HANDLE hNewConsole = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ,0,NULL,CONSOLE_TEXTMODE_BUFFER,NULL);//隐藏光标CONSOLE_CURSOR_INFO cci = { 1, 0 };SetConsoleCursorInfo(hNewConsole, &cci);//设置窗口的缓冲区大小COORD cdBufferSize = { 58, 29 };SetConsoleScreenBufferSize(hNewConsole, cdBufferSize);//然后我们输出这个数组看看for (i = 0; i < N * 2 - 1; i++){for (j = 0; j < N * 4 - 3; j++){COORD cdCursorPos = { j, i };const char *p = NULL;//          printf("%c", buffer[i][j]);switch (buffer[i][j]){case '1': p = "●"; j++; break;//j++可省case '2': p = "○"; j++; break;//j++可省case 'a': p = "┏"; break;case 'b': p = "┓"; break;case 'c': p = "┛"; break;case 'd': p = "┗"; break;case 'e': p = "┯"; break;case 'f': p = "┷"; break;case 'g': p = "┠"; break;case 'h': p = "┨"; break;case 'i': p = "━"; break;//上下的横线更粗case 'j': p = "—"; j++; break;//中间的横线更细//j++;由于输出"—"时占两个字符,j++可以避开输出下一个的空格case 'k': p = "┃"; break;//左右的竖线更粗case 'l': p = "│"; break;//中间的竖线更粗case 'm': p = "┼"; break;case ' ': p = " "; break;default: p = &buffer[i][j];}//switch,forif (!p) continue;SetConsoleCursorPosition(hNewConsole, cdCursorPos);WriteConsole(hNewConsole, p, strlen(p), NULL, NULL);}//      printf("\n");}//for//把绘制好的东西都显示出来SetConsoleActiveScreenBuffer(hNewConsole);
}int  Judge_Display()//输出胜负情况
{if (num == N * N){Buf_Display();//将缓冲器数据输出到屏幕printf("平局!\n");return 1;//对局结束}if (gs == 1){Buf_Display();//将缓冲器数据输出到屏幕printf("黑棋赢!");return 1;//对局结束}if (gs == 2){Buf_Display();//将缓冲器数据输出到屏幕printf("白棋赢!\n");return 1;//对局结束}return 0;}

二、整体框架分析

1.初始化棋盘

通过初始化数据棋盘和缓冲数据来初始化棋盘。

2.进行对局

通过用户输入的数据来判断对局方式:玩家先行、电脑先行、电脑进行自博弈。

当玩家选择后,进入对局页面,此时调用绘制页面函数,棋子初始化位置为棋盘中心。每下一个棋子,棋盘的相关数据就会更新,棋盘页面也通过缓冲数据来迅速更新页面,重新绘制。

3.寻找最佳下子位置

  1. 分析全局棋盘状况,获得棋盘上每个空缺位置的五连珠情况,通过对应相应得分,来获得空缺位置的总得分情况。
  2. 通过比对每个空缺位置的得分,找到得分最高的空缺位置,此位置即为最佳下子位置。

4.实时判断棋局状况

不管是玩家还是电脑,每下子一次,都要判断所有棋子是否构成五子连珠的情况,如若构成,棋局结束,显示获胜者,如若不然,继续对局。


棋局结束共有三种情况:

  1. 白棋五子连珠
  2. 黑棋五子连珠
  3. 棋盘下满,双方平局

三、 总结

从全篇代码来看,算法难度并不大,使用的算法属于比较基础的难度,所以这套代码的搜索深度也比较浅。但我觉得沈航从0到1来创造出这套代码也是相当不易的,从算法的分析与设计到实现,这都是需要不断的思考和尝试的。接下来我会接着学习五子棋的相关博弈算法,希望可以把这套代码给不断的改进,提高它的棋力。如果时间可以,通过后期的不断学习,加入神经网络后,我相信棋力会有大幅度的提升!

最后今天是五四青年节,不念过往,不畏将来,活在当下,冲冲冲!

五子棋——沈航2017年计算机博弈国赛代码解析相关推荐

  1. 计算机二级c语言考点解析,2017年计算机二级C语言考点解析

    2017年计算机二级C语言考点解析 C语言是一个有结构化程序设计.具有变量作用域(variable scope)以及递归功能的过程式语言.下面是小编整理的关于计算机二级C语言考点解析,希望大家认真阅读 ...

  2. 一级计算机考试word知识点,2017年计算机一级考试MSOffice考点解析:Word窗口及其组成...

    3.1.2Word窗口及其组成 Word窗口由标题栏.快速访问工具栏.文件选项卡.功能区.工作区.状态栏.文档视图工具栏.显示比例控制栏.滚动条.标尺等部分组成.在Word窗口的工作区中可以对创建或打 ...

  3. 如何用计算机完成一片文稿制作,2017年计算机一级考试MSOffice考点解析:演示文稿制作实例1...

    5.9.1实例 1.按下列要求创建演示文稿.并以yswg-1.pptx保存. (1)建立一个含有5张幻灯片的演示文稿. 版式和内容如下: 第一张幻灯片:版式为"标题幻灯片",主标题 ...

  4. 全国计算机一级考试照片底色,2017年计算机一级考试MSOffice考点解析:幻灯片背景的设置...

    5.4.2幻灯片背景的设置 幻灯片的背景对幻灯片放映的效果起重要作用,为此,可以对幻灯片背景的颜色.图案和纹理等进行调整.有时用特定图片作为幻灯片背景,能达到意想不到的效果.如果对幻灯片背景不满意,可 ...

  5. 【蓝桥杯】第十三届蓝桥杯单片机国赛 代码程序

    第十三届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这 ...

  6. 第十届蓝桥杯单片机国赛代码实现

    代码如下: #include <STC15F2K60S2.H> #include "iic.h" #include "onewire.h" #inc ...

  7. 【蓝桥杯】第九届蓝桥杯单片机国赛 代码程序

    第九届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这里 ...

  8. 蓝桥杯------2017 Java B组 国赛:第二题 生命游戏

    题目描述: 康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机.   这个游戏在一个无限大的2D网格上进行. 初始时,每个小方格中居住着一个活着或死了的细胞. 下一时刻每个细胞的状态 ...

  9. 蓝桥杯单片机类第十一届国赛代码(国二)

    //复习的都没考,感觉没有区分度,靠选择题拿分,总体来说比较简单,跟省赛差不多,结果是国二 #include "tim.h" #include "seg.h" ...

最新文章

  1. hdu4642博弈(矩阵)
  2. k8s部署zkui 2.0
  3. sphinx (coreseek)——2、区段查询实例
  4. B - Frogger(最短路之多条最短路径中最大权值的最小值)
  5. linux开发之uboot移植 -- uboot简介
  6. 事实上,在你不知道的地方,还有一个世界杯!
  7. JavaWeb(HTML +css+js+Servlet....)
  8. 您的组织策略阻止我们为您完成此操作。有关详细信息,请联系技术支持。
  9. Office2021版安装出错
  10. [Java学习笔记]-数组
  11. 设置win7一直以管理员身份运行
  12. Android推送技术总结
  13. Oracle EBS WIP任务单批量发料功能开发
  14. 毕业论文答辩の七个原则(硕士)
  15. LeetCode: 44. Wildcard Matching
  16. webupload 被动触发上传
  17. wpa_cli 操作指令使用指南
  18. 贷后中登监控 伪代码梳理
  19. 常用php类库、资源
  20. 云计算专业和计算机专业哪个好就业?

热门文章

  1. Ubuntu下Hadoop以及Spark配置
  2. YubiKey USB安全密钥也出现臭虫可免费换新
  3. SUTD提出:基于不同数据模态的行为识别最新综述!381篇文献
  4. 公式穿搭法则,让你穿搭更简单
  5. 中小型创业者要有长远观
  6. 数字图像处理复习(part3)
  7. 51单片机学习笔记_11 蜂鸣器,识简谱,根据简谱编写蜂鸣器代码
  8. 互联网营销如何发展品牌形象设置跟踪功能
  9. JAVA如何实现窗口化,毕设窗口如何用JAVA实现!
  10. axure 9 元件库百度地址