C语言之三字棋的简单实现及扩展
C语言之三字棋的简单实现及扩展
在我们学习完数组之后,我们完全可以利用数组相关知识来写一个微小型的游戏,比如说今天所说的——三子棋。
大纲:
文件组成
实现
完整代码展示
扩展
即:
一.文件组成:
在我们学习的过程中,我们要逐渐习惯多文件的书写方式,也就是模块化书写。
在本文中,笔者分为了三个文件来写,分别是:
1.game.h——实现游戏函数的声明
2.game.c——游戏函数的实现
3.test.c —— 测试及游戏函数的调用
二.实现
0.文件的初始化
在这里我们分别在我们所创建的 test.c 和 game.c 包含我们的头文件——game.h
1.菜单的实现
在菜单中,我们设置玩家可以选择的模式,play and quit
以及,菜单怎么样多次循环选择,菜单的容错处理。这里,我们利用 do-while 来实现。
#define _CRT_SECURE_NO_WARNINGS 1//加这一句话是因为笔者采用的是 VS 编译器,为了防止一些不必要的错误出现 #include "game.h" void menu()//列出可供玩家选择的模式
{
printf("**************************************************************\n");
printf("***************** 1.play ****************\n");
printf("***************** 0.exit ****************\n");
printf("**************************************************************\n");
} void play()
{ } int main()
{
int input;//在这里,我们利用玩家选择的模式来控制循环的终止
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
switch (input)
{
case 1://play
play();
break;
case 0://退出
printf("欢迎下次再来!\n");
break;
default://当玩家输入了非法字符,让其重新选择
printf("输入错误,请重新输入!\n");
}
} while (input);//当input为0时,停止循环 return 0;
}
运行效果:
现在,我们的菜单已经做好了,接下来要做的就是来打印我们的棋盘。
2.棋盘的打印
这里我们把打印函数的声明放在 game.h 文件里,把实现放在game.c 文件中。
在写代码之前,我们先来想一想在棋盘打印中,我们能不能直接打印空格——这肯定是不能的,因为这样,我们在屏幕上什么都看不见 (≧∇≦)ノ
game.c:
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void InitBoard(char board[3][3], int row, int col)//棋盘初始化
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
} void DisplayBoard(char board[3][3], int row, int col)//棋盘打印函数
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");//分割列
}
}
printf("\n"); if (i < row - 1)
{
for (j = 0; j < 3; j++)
{
printf("---");//分割行
if (j < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
注:
为了避免文章赘余,test.c 以及 game.h不再表示
运行结果:
但是,我们这么写,会不会有问题?
值得注意的是,在这有人会把棋盘打印写成这个样子
void DisplayBoard(char board[3][3], int row, int col)//棋盘打印函数
{
for (int i = 0; i < 3; i++)
{
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i < 2)
{
printf("---|---|---\n");//分割行
}
}
}
这样,无非还是上面那个问题,代码写死,无法扩展
所以,我们在这利用宏来实现,棋盘的大小随我们的宏来改变
因此在这我们给出头文件的部分
#pragma once #include<stdio.h> #define ROW 3//利用宏来实现棋盘的大小
#define COL 3 void InitBoard(char board[ROW][COL], int row, int col);//棋盘初始化 void DisplayBoard(char board[ROW][COL],int row, int col);//棋盘打印函数
3.棋盘下子
1.玩家下子
在这里我们一共要注意几点:
1.在下子之前,我们要判断玩家所要下的位置是否在棋盘内
2.检测玩家要下的位置是否已有了棋子
3.下子之后,检查棋盘的输赢状况 (这个我们后面再说)
void PlayerMove(char board[ROW][COL], int row, int col)//玩家下棋
{
int x, y;
printf("玩家走:\n");
printf("请输入你所要落子的坐标:");
scanf("%d%d", &x, &y);
if (board[x - 1][y - 1]!=' ')//坐标被占用
{
printf("该坐标已被占用,请重新下子!\n");
}
else if (!((x > 0 && x <= row) && (y > 0 && y <= col)))
{
printf("该坐标为非法坐标,请重新输入!\n");//坐标非法
}
else
{
board[x - 1][y - 1] = '*';//玩家落子,暂时用 * 来表示
}
}
2.电脑下子
再这里我们暂不深究,使用随机函数来生成一个坐标来下子
void ComputerMove(char board[ROW][COL], int row, int col)//电脑下棋
{
int x, y;
printf("电脑走:");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';//这里我们用 # 来表示电脑下棋
break;
}
}
}
4.胜负的判定
在这里,我们用一个函数的返回值来表示输赢的各个情况。
#-----电脑赢
*-----玩家赢
C-----继续下子
F-----和局
int ISFULL(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
} char ISWIN(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col - 2; j++)
{
//判断横行
if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
return board[i][j];
//判断主对角线
else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] != ' ')
return board[i][j];
//判断副对角线
else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 1 - i][j] != ' ')
return board[col - 1 - i][j];
}
}
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col; j++)
{
//判断竖行
if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] != ' ')
return board[i][j];
}
}
//判断是否满盘---放在最后是因为最后一步的判断
if (1 == ISFULL(board, row, col))
{
return 'F';
}
return 'C';
}
到这,我们的三子棋似乎已经编完了,先看一下运行结果:
在这个过程中,我们会发现电脑下的特别快(当然,这跟我们的懒惰有关……)所以我们在电脑下的步骤中加一个Sleep()函数来延长电脑所用时间
已即,我们可以下一次子就清一下屏,这样看起来比较舒服
所以
最后的代码部分:
#pragma once #include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h> #define ROW 3//利用宏来实现棋盘的大小
#define COL 3 void InitBoard(char board[ROW][COL], int row, int col);//棋盘初始化 void DisplayBoard(char board[ROW][COL], int row, int col);//棋盘打印函数 void PlayerMove(char board[ROW][COL], int row, int col);//玩家下棋 void ComputerMove(char board[ROW][COL], int row, int col);//电脑下棋 char ISWIN(char board[ROW][COL], int row, int col);//判断输赢 int ISFULL(char board[ROW][COL], int row, int col);//判断棋盘是否已满
game.h
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void InitBoard(char board[ROW][COL], int row, int col)//棋盘初始化
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
} //void DisplayBoard(char board[3][3], int row, int col)//棋盘打印函数
//{
// for (int i = 0; i < 3; i++)
// {
// printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
// if (i < 2)
// {
// printf("---|---|---\n");
// }
// }
//} void DisplayBoard(char board[ROW][COL], int row, int col)//棋盘打印函数
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");//分割列
}
}
printf("\n"); if (i < row - 1)
{
for (j = 0; j < 3; j++)
{
printf("---");//分割行
if (j < col - 1)
{
printf("|");
}
}
}
printf("\n");
}
} void PlayerMove(char board[ROW][COL], int row, int col)//玩家下棋
{
int x, y;
printf("玩家走:\n");
while (1)
{
printf("请输入你所要落子的坐标:");
scanf("%d%d", &x, &y);
if (!((x > 0 && x <= row) && (y > 0 && y <= col)))
{
printf("该坐标为非法坐标,请重新输入!\n");//坐标非法
}
else if (board[x - 1][y - 1] != ' ')//坐标被占用
{
printf("该坐标已被占用,请重新下子!\n");
}
else
{
board[x - 1][y - 1] = '*';//玩家落子,暂时用 * 来表示
break;
}
}
system("cls");
} void ComputerMove(char board[ROW][COL], int row, int col)//电脑下棋
{
int x, y;
printf("电脑走:\n");
Sleep(1000);
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';//这里我们用 # 来表示电脑下棋
break;
}
}
system("cls");
} int ISFULL(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
} char ISWIN(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0; for (i = 0; i < row; i++)
{
for (j = 0; j < col - 2; j++)
{
//判断横行
if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
return board[i][j];
//判断主对角线
else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] != ' ')
return board[i][j];
//判断副对角线
else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 1 - i][j] != ' ')
return board[col - 1 - i][j];
}
}
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col; j++)
{
//判断竖行
if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] != ' ')
return board[i][j];
}
} //判断是否满盘---放在最后是因为最后一步的判断
if (1 == ISFULL(board, row, col))
{
return 'F';
}
return 'C';
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1//加这一句话是因为笔者采用的是 VS 编译器,为了防止一些不必要的错误出现 #include "game.h" void menu()//列出可供玩家选择的模式
{
printf("**************************************************************\n");
printf("***************** 1.play ****************\n");
printf("***************** 0.exit ****************\n");
printf("**************************************************************\n");
} void play()
{
int ret;
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = ISWIN(board, ROW, COL);
{
if (ret != 'C')
break;
} ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = ISWIN(board, ROW, COL);
{
if (ret != 'C')
break;
}
}
switch (ret)
{
case 'F':
printf("和局!\n");
system("pause");
system("cls");
break;
case '#':
printf("电脑赢!\n");
system("pause");
system("cls");
break;
case '*':
printf("玩家赢!\n");
system("pause");
system("cls");
break;
default:
break;
}
} int main()
{
srand((unsigned)time(NULL));//随机种子的初始化
int input;//在这里,我们利用玩家选择的模式来控制循环的终止
do
{
menu();
printf("请输入你的选择:");
scanf("%d", &input);
switch (input)
{
case 1://play
system("cls");
play();
break;
case 0://退出
printf("欢迎下次再来!\n");
break;
default://当玩家输入了非法字符,让其重新选择
system("cls");
printf("输入错误,请重新输入!\n");
}
} while (input);//当input为0时,停止循环 return 0;
}
test.c
三.扩展
1.五子棋的实现
五子棋的实现仅仅只改变了判断规则,其它方式都没变。
判断代码:
char ISWIN(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0; for (i = 0; i < col; i++)
{
for (j = 0; j < col - 4; j++)
{
//判断横行
if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4] && board[i][j] != ' ')
return board[i][j];
//判断对角线
else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4] && board[i][j] != ' ')
return board[i][j];
else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 4 - i][j + 3] == board[col - 2 - i][j + 1] && board[col - 5 - i][j + 4] == board[col - 2 - i][j + 1] && board[col - 1 - i][j] != ' ')
return board[col - 1 - i][j];
}
}
for (i = 0; i < col - 4; i++)
{
for (j = 0; j < col ; j++)
{
//判断竖行
if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j] && board[i][j] != ' ')
return board[i][j];
}
}
//判断是否满盘
if (1 == ISFULL(board, row, col))
{
return 'f';
} return 'c';
}
2.玩家对战玩家
只需将电脑下子的部分,替换成玩家下子即可
完整五子棋-人人对战代码:
#pragma once
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h> #define ROW 10
#define COL 10 //初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col); //玩家走
void Player1Move(char board[ROW][COL],int row, int col); //玩家2走
void Player2Move(char board[ROW][COL], int row, int col); //电脑走
void ComputerMove(char board[ROW][COL], int row, int col); //判断输赢
char ISWIN(char board[ROW][COL], int row, int col); //判断棋盘是否已满
int ISFULL(char board[ROW][COL], int row, int col);
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h" void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
} void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < col; i++)
printf(" %d", i + 1);
printf("\n");
for (i = 0; i < row; i++)
{
printf("%2d", i + 1);
for (j = 0; j < col; j++)
{
printf(" %c ",board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n"); //打印分割行
if (i < row - 1)
{
printf(" ");
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
} void Player1Move(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
while (1)
{
printf("请输入玩家1要下的棋的坐标:");
scanf("%d%d", &i, &j);
//检查是否越界
if (1 <= i && i <= row && j >= 1 && j <= col)
{
if (board[i-1][j-1] != ' ')
printf("此坐标已被占用!\n");
else
{
board[i-1][j-1] = '*';
break;
}
}
else
printf("坐标非法访问!\n");
}
system("cls");
} void Player2Move(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
while (1)
{
printf("请输入玩家2要下的棋的坐标:");
scanf("%d%d", &i, &j);
//检查是否越界
if (1 <= i && i <= row && j >= 1 && j <= col)
{
if (board[i - 1][j - 1] != ' ')
printf("此坐标已被占用!\n");
else
{
board[i - 1][j - 1] = '#';
break;
}
}
else
printf("坐标非法访问!\n");
}
system("cls");
} //void ComputerMove(char board[ROW][COL], int row, int col)
//{
// int i = 0, j = 0;
// printf("电脑走:\n");
// while (1)
// {
// i = rand() % row;
// j = rand() % col;
// if (board[i][j] == ' ')
// {
// board[i][j] = '#';
// break;
// }
// }
// Sleep(1000);
// system("cls");
//} int ISFULL(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
} char ISWIN(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0; for (i = 0; i < col; i++)
{
for (j = 0; j < col - 4; j++)
{
//判断横行
if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4] && board[i][j] != ' ')
return board[i][j];
//判断对角线
else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4] && board[i][j] != ' ')
return board[i][j];
else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 4 - i][j + 3] == board[col - 2 - i][j + 1] && board[col - 5 - i][j + 4] == board[col - 2 - i][j + 1] && board[col - 1 - i][j] != ' ')
return board[col - 1 - i][j];
}
}
for (i = 0; i < col - 4; i++)
{
for (j = 0; j < col ; j++)
{
//判断竖行
if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j] && board[i][j] != ' ')
return board[i][j];
}
}
//判断是否满盘
if (1 == ISFULL(board, row, col))
{
return 'f';
} return 'c';
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h" void menu()
{
printf("*********************************************\n");
printf("******* 1.play *********\n");
printf("******* 0.quit *********\n");
printf("*********************************************\n");
} int choice()
{
int input = 0;
printf("请输入你的选择:");
scanf("%d", &input);
return input;
} void game()
{
char ret;
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
Player1Move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = ISWIN(board, ROW, COL);
{
if (ret != 'c')
break;
} Player2Move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = ISWIN(board, ROW, COL);
{
if (ret != 'c')
break;
}
}
switch (ret)
{
case 'f':
printf("和局!\n");
break;
case '#':
//printf("电脑赢!\n");
printf("玩家2赢!\n");
break;
case '*':
printf("玩家1赢!\n");
break;
default:
break;
}
} void play()
{
int input;
do
{
menu();
input = choice();
system("cls");
switch (input)
{
case 1:
game();
break;
case 0:
printf("谢谢使用,欢迎下次再来!\n");
break;
default:
system("cls");
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
} int main()
{
play();
return 0;
}
test.c
3.电脑下棋的探究
对此我们的算法肯定是需要极大的改进的
建议:
1.不在用随机函数代替机器大脑
2.电脑根据情况堵截
关于三子棋的讲解便到此为止。
笔者水平有限,若有错误之处,还望多多指正。
C语言之三字棋的简单实现及扩展的更多相关文章
- C语言实现简单php自定义扩展
1.下载php源码 下载地址:http://cn2.php.net/get/php-5.6.29.tar.gz/from/this/mirror 传到/usr/local/src/下 上传命令:rz ...
- GO语言练习:实现最简单的http helloword 服务器
用Go语言实现一个最简单的http服务器端,主要用到了package io, log, net/http 这个3个库. 用到的函数包括: http.Handle() http.HandlerFunc( ...
- C语言开发CGI程序的简单例子
这年头用C语言开发cgi的已经不多,大多数的web程序都使用java.php.python等这些语言了. 但是本文将做一些简单的cgi实例. 首先配置环境 #这里是使用的apache AddHandl ...
- 【笔记】嵩天.Python语言程序设计.完成两个简单实例(温度转换和绘图)
[博客导航] [Python相关] 目标 使用PyCharm,完成两个小实例的编写和运行.一个是温度转换,一个是蟒蛇图形绘制. 过程 1.先设置project目录,虽然命名不是很正式,主要不太习惯软件 ...
- 函数式语言(Functional language)简单介绍
函数式语言(functional language)一类程序设计语言,是一种非冯·诺伊曼式的程序设计语言.函数式语言主要成分是原始函数.定义函数和函数型. 函数式语言有:Haskell,Clean,M ...
- C语言程序设计(三) 简单的算术运算和表达式
第三章 简单的算术运算和表达式 算数运算符:一元.二元.三元(条件运算符) 1/2是整型除法,1.0/2是浮点数除法 求余运算(%)限定参与运算的两个操作数必须为整数,不能对两个实型数据进行求余运算 ...
- 适合刚刚学习编程的萌新:C语言编程学习制作超简单又好玩的报数游戏!
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- C语言中如何写一个简单可移植而又足够随机的随机数生成器
在C语言中标准库中的随机数产生函数的返回可能不是最优的,因为有些随机数生成器的低位并不随机,而另一些返回随机数的函数实现上又太复杂鸟.所以rand()%N并不是一个好方法,牛人给出的建议是使用: ra ...
- 用c语言实现三子棋
1 game.c://实现三子棋的.c文件 #define _CRT_SECURE_NO_WARNINGS #include"game.h" void init_board(cha ...
随机推荐
- Codeforces Round #529 (Div. 3) F. Make It Connected (贪心,最小生成树)
题意:给你\(n\)个点,每个点都有权值,现在要在这\(n\)个点中连一颗最小树,每两个点连一条边的边权为两个点的点权,现在还另外给了你几条边和边权,求最小权重. 题解:对于刚开始所给的\(n\)个点 ...
- Python 分析热卖年货,今年春节大家都在送啥?
今年不知道有多少小伙伴留在原地过年,虽然今年过年不能回老家,但这个年也得过,也得买年货,给家人长辈送礼.于是我出于好奇心的想法利用爬虫获取某宝数据,并结合 Python 数据分析和第三方可视化平台来分 ...
- PAT l2-018 多项式A除以多项式B 【多项式+模拟】
这仍然是一道关于A/B的题,只不过A和B都换成了多项式.你需要计算两个多项式相除的商Q和余R,其中R的阶数必须小于B的阶数. 输入格式: 输入分两行,每行给出一个非零多项式,先给出A,再给出B.每行的 ...
- React Portal All In One
React Portal All In One react multi root https://reactjs.org/docs/portals.html https://zh-hans.react ...
- 前端架构模式 All In One
前端架构模式 All In One 架构模式 同构 异构 微前端 Web Components 组件化 无框架 去框架 前后端分离 前端架构图 Clean Architecture https://b ...
- how to read the system information by using the node cli tool?
how to read the system information by using the node cli tool? node cli & get system info demos ...
- Python Web Frameworks
Python Web Frameworks top 10 Python web frameworks Django (Full-stack framework) Flask (Micro framew ...
- holy shit CSDN
holy shit CSDN 垃圾 CSDN 到处都是垃圾文章, 无人子弟 到处都是垃圾广告,看的恶心 毫无底线,窃取别人的知识成果,毫无版权意识 垃圾爬虫,垃圾小号 ...等等 Google Sea ...
- foreign language learning
foreign language learning free online learning websites 多邻国 https://www.duolingo.com 忆术家 https://www ...
- js repeatify & no for loop
js repeatify & no for loop js repeatify https://www.sitepoint.com/5-typical-javascript-interview ...