N子棋(外加双人对战)详解!推荐!!!

news2024/11/18 23:40:26

文章目录

  • 准备工作
    • 创建菜单
      • 进入游戏
        • 初始化棋盘、打印棋盘
          • 玩家下棋、电脑下棋、生成随机数
            • 判断输赢

大家好!时隔多天,我终于写博客了,真的是开心!这一次带来的是N子棋有双人对战和单人下棋,请认真看下去,我会竭尽所能讲清楚整个思路!如果还有疑问的话,我们可以进行探讨!
首先给大家展示代码:

这是test.c:

#define _CRT_SECURE_NO_WARNINGS


#include"game.h"


void game()
{
	char board[ROW][COL];
	char ret = 0;
	init_board(board, ROW, COL);
	print_board(board, ROW, COL);
	while (1)
	{
		player1_move(board, ROW, COL);
		print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		computer_move(board, ROW, COL);
		print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == '*')
		printf("玩家1赢了!\n");
	else if (ret == '#')
		printf("电脑赢了!\n");
	else if (ret == 'P')
		printf("平局!\n");
}

void menu()
{
	printf("    1. play    \n");
	printf("    0. exit    \n");
	printf("    please enter:");
}

void test()
{	
	srand((unsigned int) time(NULL));
	int i = 0;
	do
	{
		menu();
		scanf("%d", &i);
		switch (i)
		{
		case 1:
			game();
			break;
		case 0:
			printf("    quit game\n");
			break;
		default:
			printf("    please enter again!\n");
			break;
		}
	} while (i);
}



int main()
{
	test();
	return 0;
}

这是game.c:

#define _CRT_SECURE_NO_WARNINGS

#include"game.h"

void init_board(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

void print_board(char board[ROW][COL], int row, int col)

{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		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 < col; j++)
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");
	}
}

void player1_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家1请下棋:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x - 1 < row && y >= 1 && y - 1 < col)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("已被占用!");
			}
		}
		else
		{
			printf("非法输入!");
		}
	}
}

void computer_move(char board[ROW][COL], int row, int col)
{
	int x = rand() % 3;
	int y = rand() % 3;
	while (1)
	{
		printf("电脑请下棋:");
		scanf("%d %d", &x, &y);
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
}

static int  is_full(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}


char is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[i][j - 1] == board[i][j] && board[i][j - 1] != ' ')//
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)
			return board[i][j - 1];
	}
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[j][i] == board[j - 1][i] && board[j - 1][i] != ' ')
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)
			return board[j - 1][i];
	}
	int flag = 0;
	for (i = 1; i < row; i++)
	{
		
		if (board[i - 1][i - 1] == board[i][i] && board[i - 1][i - 1] != ' ')
			flag++;
		if (flag == KEY - 1)
			return board[i][i];
	}
	flag = 0;
	int j = col - 1;
	for (i = 1; i < row; i++)
	{
		
		if (board[i][j - 1] == board[i - 1][j] && board[i - 1][j] != ' ')
		{
			flag++;
			j--;
		}
		if (flag == KEY - 1)
			return board[i][0];
	}
	int ret = is_full(board, ROW, COL);
	if (ret)
		return 'P';
		return 'C';
}


这是game.h:

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 10
#define COL 10

#define KEY 5

void init_board(char board[ROW][COL], int row, int col);

void print_board(char board[ROW][COL], int row, int col);

void player1_move(char board[ROW][COL], int row, int col);

void computer_move(char board[ROW][COL], int row, int col);

char is_win(char board[ROW][COL], int row, int col);

准备工作

在进行设计一个游戏前,我们要思考游戏分为什么部分 ,根据模块逐个进行编程,并且写完一部分就要进行调试,看是否出错!

我们可以从简单入手,先设计一个三子棋,然后再进行扩展。

先创建文件,创建一个test.c 文件作为主函数的部分,然后创建游戏文件game.c 文件作为游戏主体的部分,最后创建一个game.h 文件作为声明函数的文件,如图:
注意:这里可以将<stdio.h>头文件放在game.h中,然后再test.c 和game.c 中引用game.h 文件,#include"stdio.h"。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建菜单

当创建完文件之后,就可以进行写代码了。首先进入一个游戏,映入眼帘的是菜单,玩还是不玩?所以先可以创建菜单了。

void menu()//菜单说明
{
	printf("    1. play    \n");
	printf("    0. exit    \n");
	printf("    please enter:");
}

void test()
{	
	int i = 0;//进行选择
	do
	{
		menu();//进行打印菜单
		scanf("%d", &i);
		switch (i)
		{
		case 1://选择1进行游戏
			game();//游戏主体部分
			break;
		case 0://选择0退出游戏
			printf("    quit game\n");
			break;
		default://选择其它数字就进行报错
			printf("    please enter again!\n");
			break;
		}
	} while (i);//为0跳出循环,退出游戏
}



int main()
{
	test();//测试部分
	return 0;
}
//这里用到do while 语句很合适,进入游戏,不管你玩不玩,游戏界面是一定
//要显示的,体现了do while 语句的先执行一次的特点!

进入游戏

那么创建完菜单之后,进行选择,选择1进入游戏。接下来进行游戏主体部分,我们把游戏中的各种函数定义放在game.c 中,放在test.c 中会显得臃肿,函数的声明放在game.h 中。

void game()//游戏主体
{
//那么创建一个棋盘变量。棋盘分为行列,所以我们可以用二维数组来作为棋盘,
//ROW代表行,COL代表列,我们进行宏定义ROW为3,COL为3,如下图:

	char board[ROW][COL];
}

宏定义ROW ,COL 为3,这样宏定义很方便,想要改变棋盘的大小,只要改变这里就行了,其它不用改变!在这里插入图片描述

初始化棋盘、打印棋盘

当我们进入游戏的时候,我们看到应该是棋盘,并且没有下棋的棋盘.如下图:

void game()//游戏主体
{//在这里调用函数,在game.c 中定义函数.
	char board[ROW][COL];//棋盘大小,ROW为行,COL为列
	init_board(board, ROW, COL);//初始化棋盘
	print_board(board, ROW, COL);//打印棋盘
}

我们要思考:如何设计一个棋盘?如何去初始化棋盘,让棋盘每一个位置都是空格?下图是一个模板:
在这里插入图片描述

初始化棋盘:我们直接用双层循环进行每个元素赋值为空格就行,如下图:

//记得要在game.h中声明该函数!
void init_board(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';//每个元素赋予空格
		}
	}
}

打印棋盘:我们可以将这个图案分为两个部分:

在这里插入图片描述

我们可以观察:无横线的部分中空格是有三个空格,因为下面有三个横线,那我们可以写双重循环,内层循环写无横线的部分,循环三列,外层循环写三行.如下图:

void print_board(char board[ROW][COL], int row, int col)

{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);//打印三个部分,中间放字符
		}
		printf("\n");
	}
}

这样打印结果就是如下:
在这里插入图片描述

第一个问题:我们可以看到在第三列不需要竖杠,只需要打印小于COL - 1 的列数,所以用一个if语句来执行,如果小于COL就打印竖杠,否则不打印!***
第二个问题:我们看到缺少了横线与竖杠,所以我们可以在内层循环结束后,进行打印横线与竖杠,但是最后一行不需要打印,所以要进行判断行小于ROW - 1 。***
所以解决途径如下:

void print_board(char board[ROW][COL], int row, int col)

{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		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 < col; j++)//循环3次,打印竖杠
			{
				printf("---");
				if (j < col - 1)
					printf("|");
			}
		}
		printf("\n");
	}
}

那么初始化棋盘,打印棋盘就完成了。

玩家下棋、电脑下棋、生成随机数

既然棋盘已经做完了,那么接下来就是下棋了。下棋分为玩家和电脑下棋。

玩家下棋:作为一个玩家,我们可以输入坐标在棋盘上显示符号,玩家输入坐标是大于等于1的,所以存入数组的时候要进行减一。

规则:输入坐标。首先判断坐标是否合法,什么是合法?合法就是要在棋盘的大小范围之内!然后判断坐标的位置是否为空格?意思就是这个坐标不能有棋子,有棋子就代表被占用了,不能下棋!这两个规则遵守了,就可以进行设计了!如下图:

void player1_move(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)//只有坐标合法并且正确才能跳出循环,否则继续输入坐标
	{
		printf("玩家1请下棋:");
		scanf("%d %d", &x, &y);//坐标一定要大于等于1
		if (x >= 1 && x - 1 < row && y >= 1 && y - 1 < col)//坐标合法的条件
		{
			if (board[x - 1][y - 1] == ' ')//坐标减一才能对应数组中的元素
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("已被占用!");//不是空格就说明
			}
		}
		else
		{
			printf("非法输入!");//坐标不合法就说明
		}
	}
}

电脑下棋:电脑下棋不需要那么麻烦,所以只需要生成的随机数作为坐标,然后判断是否被占用,不被占用就可以赋予符号并且跳出循环!

生成随机数:我之前在写猜数字游戏的时候讲了随机数的一些知识,不了解可以去看看,这是链接http://t.csdn.cn/IgYyi。把随机数当成坐标,但是随机数很随机,很可能不合法,所以我们可以%3,那么得到的结果只能小于3,就可以作为随机数了。

void computer_move(char board[ROW][COL], int row, int col)
{
	int x = rand() % 3;//srand可以放在void test()中,因为只需要生成一次就可以了!
	int y = rand() % 3;//记得引用头文件#include<stdlib.h>,放在game.h中。
	while (1{
		printf("电脑请下棋:";
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}

玩家下一个棋,是不是要打印一下棋盘,因为不打印棋盘,就不知道下了什么棋,所以要打印棋盘;电脑也是如此,如果电脑下完不显示,玩家就不能根据形势来下棋获得胜利了。

void game()//游戏主体
{
	char board[ROW][COL];//棋盘大小,ROW为行,COL为列
	char ret = 0;
	init_board(board, ROW, COL);//初始化棋盘
	print_board(board, ROW, COL);//打印棋盘
	while (1)//这里用到for循环是因为玩家和电脑下棋,总不可能下一次棋就结束了吧!
			//待会会讲到如何跳出循环
	{
		player1_move(board, ROW, COL);//玩家1下棋
		print_board(board, ROW, COL);
		computer_move(board, ROW, COL);//电脑下棋
		print_board(board, ROW, COL);
	}
}

当然这个电脑是有点人工智障的,它不会赌棋,让电脑赢反而成为了一种难度。

判断输赢

来到了我们的结束阶段了!
有三种情况:赢、平局、游戏继续。所以我们可以写一个判断输赢的函数,返回值为字符型。

返回值为C,则游戏继续;返回值为*,则跳出循环,并输出玩家赢了;返回值为#,则跳出循环,并输出电脑赢了;返回值为P,则跳出循环,并输出平局。

void game()//游戏主体
{
	char board[ROW][COL];//棋盘大小,ROW为行,COL为列
	char ret = 0;
	init_board(board, ROW, COL);
	print_board(board, ROW, COL);
	while (1)
	{
		player1_move(board, ROW, COL);//玩家1下棋
		print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);//判断是否赢了的函数
		if (ret != 'C')//返回值只要不是C,就要跳出循环,游戏结束。
		{
			break;
		}
		computer_move(board, ROW, COL);
		print_board(board, ROW, COL);
		ret = is_win(board, ROW, COL);//不管是玩家还是电脑都要判断赢了没有,必须出现在
									 //一个角色下了棋之后进行判断
		if (ret != 'C')
		{
			break;
		}
	}
	if (ret == '*')
		printf("玩家1赢了!\n");
	else if (ret == '#')
		printf("电脑赢了!\n");
	else if (ret == 'P')
		printf("平局!\n");
}

赢有四种方式:行、列、对角线、另一条对角线

第一种:行的判断!我们只需要判断同一行的每个元素相同就行了,当然不能等于空格!所以如下:

char is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{//连续两个数相等并且不等于空格
			if (board[i][j - 1] == board[i][j] && board[i][j - 1] != ' ')
				flag++;//作为标志
			if (flag == KEY - 1)//KEY代表玩什么棋
				break;
		}
		if (flag == KEY - 1)//假如为三子棋,flag只要为2就可以赢了!,三个连成一线要判断两次
			return board[i][j - 1];
	}
}

第二种:列的判断!列的判断类似于行的判断。列不变化,行在变化。如下:

char is_win(char board[ROW][COL], int row, int col)
{
	//行的判断
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[i][j - 1] == board[i][j] && board[i][j - 1] != ' ')//
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)//假如为三子棋,flag只要为2就可以赢了!,三个连成一线要判断两次
			return board[i][j - 1];
	}

	//列的判断
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[j][i] == board[j - 1][i] && board[j - 1][i] != ' ')
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)
			return board[j - 1][i];
	}

第三种:对角线!对角线是有规律的,其中一个是坐标相同,另一个是行列变化1。
先讲一个对角线:如下图:

char is_win(char board[ROW][COL], int row, int col)
{   //行的判断
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[i][j - 1] == board[i][j] && board[i][j - 1] != ' ')//
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)//假如为三子棋,flag只要为2就可以赢了!,三个连成一线要判断两次
			return board[i][j - 1];
	}
	//列的判断
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[j][i] == board[j - 1][i] && board[j - 1][i] != ' ')
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)
			return board[j - 1][i];
	}
	//对角线的判断
	int flag = 0;//这个flag放在里面就会重新定义为0,这样flag最大只能为1了,不能为2!
	for (i = 1; i < row; i++)
	{//flag在里面的话,会重新初始化为0,最大为1,不会返回符号,就没有
	//这个对角线很方便,横纵坐标都相同。
		if (board[i - 1][i - 1] == board[i][i] && board[i - 1][i - 1] != ' ')
			flag++;
		if (flag == KEY - 1)
			return board[i][i];
	}

第四种:另一种对角线!另一种对角线有两种方式:1. 右上到左下。2. 左下到右上。
我是第一种方式,如下:

char is_win(char board[ROW][COL], int row, int col)
{	//行的判断
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[i][j - 1] == board[i][j] && board[i][j - 1] != ' ')//
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)//假如为三子棋,flag只要为2就可以赢了!,三个连成一线要判断两次
			return board[i][j - 1];
	}
	//列的判断
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[j][i] == board[j - 1][i] && board[j - 1][i] != ' ')
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)
			return board[j - 1][i];
	}
	//对角线的判断
	int flag = 0;//这个flag放在里面就会重新定义为0,这样flag最大只能为1了,不能为2!
	for (i = 1; i < row; i++)
	{
		
		if (board[i - 1][i - 1] == board[i][i] && board[i - 1][i - 1] != ' ')
			flag++;
		if (flag == KEY - 1)
			return board[i][i];
	}
	//另一个对角线
	flag = 0;//这个跟上面的一样
	int j = col - 1;//j如果放在里面的话就发生其它位置的元素对比,不符合对角线原则
	for (i = 1; i < row; i++)
	{//j如果放在里面的话,进行第二次循环时,i = 2, j - 1 = 1,坐标2 1不符合对角线原则
		
		if (board[i][j - 1] == board[i - 1][j] && board[i - 1][j] != ' ')
		{
			flag++;
			j--;
		}
		if (flag == KEY - 1)
			return board[i][0];
	}

赢的方式判断完了,就要判断平局了,我们把这函数就放在is_win函数中,因为这个平局函数就是为is_win函数服务的,所以不用在game.h中声明了。

static int  is_full(char board[ROW][COL], int row, int col)
{//赋予static意思是只能在game.c 文件中看到,其它文件看不到,这个函数只是为is_win函数服务的,
 //所以没必要在game.h中进行声明。
	int i = 0;//这个函数返回值为整型,只要有一个为空格,就返回0,在is_win函数中设计一个if语句
			 //如果is_full函数返回值为真,就返回P,否则不执行。
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 0;
		}
	}
	return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[i][j - 1] == board[i][j] && board[i][j - 1] != ' ')//
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)//假如为三子棋,flag只要为2就可以赢了!,三个连成一线要判断两次
			return board[i][j - 1];
	}
	for (i = 0; i < row; i++)
	{
		int j = 0;
		int flag = 0;
		for (j = 1; j < col; j++)
		{
			if (board[j][i] == board[j - 1][i] && board[j - 1][i] != ' ')
				flag++;
			if (flag == KEY - 1)
				break;
		}
		if (flag == KEY - 1)
			return board[j - 1][i];
	}
	int flag = 0;//这个flag放在里面就会重新定义为0,这样flag最大只能为1了,不能为2!
	for (i = 1; i < row; i++)
	{
		
		if (board[i - 1][i - 1] == board[i][i] && board[i - 1][i - 1] != ' ')
			flag++;
		if (flag == KEY - 1)
			return board[i][i];
	}
	flag = 0;//这个flag也是一样。
	int j = col - 1;//j如果放在里面的话就发生其它位置的元素对比,不符合对角线原则
	for (i = 1; i < row; i++)
	{
		
		if (board[i][j - 1] == board[i - 1][j] && board[i - 1][j] != ' ')
		{
			flag++;
			j--;
		}
		if (flag == KEY - 1)
			return board[i][0];
	}
	int ret = is_full(board, ROW, COL);//判断平局函数
	if (ret)
		return 'P';//为真就返回P,平局
	return 'C';//上面情况都不符合,那么游戏只能继续
}

好了,这个N子棋就讲完了,我们可以在game.h中改变ROW,COL的大小,进而改变棋盘的大小;改变KEY的大小,进而决定玩什么棋,都由你决定!

双人对战只需要把电脑下棋的代码换成玩家的代码即可,然后改变一些名称,就大工完成了。

如果这个文章对你有所帮助的话,请你点个赞,谢谢!!!
^ _ ^

位卑未敢忘忧国,事定犹须待阖棺。—陆游《病起书怀》

上善若水

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/72477.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟人纷纷「出道」,社交泛娱乐场景如何迎接新顶流?

⬆️“政企数智办公行业研究报告及融云新品发布会”明天直播&#xff01; 本月 12 日&#xff0c;花房集团即将于香港上市。关注【融云全球互联网通信云】回复【融云】抽取高颜值大容量高端可乐保温杯哦~ 中国政企数智办公平台 在带货直播平台的赫赫之名下&#xff0c;娱乐直播…

Git —— 那些在工作中日常使用的操作

Git —— 那些在工作中日常使用的操作 《工欲善其事&#xff0c;必先利其器》—— 既然点进来了&#xff0c;麻烦你看下去&#xff0c;希望你有不一样的收获~ 一、同一项目关联不同平台的远程仓库 格式&#xff1a;git remote add 命名 仓库链接 git remote add github ssh:/…

六、排序算法介绍2

1、冒泡排序 1.1 基本介绍 冒泡排序&#xff08;Bubble Sorting&#xff09; 的基本思想是&#xff1a; 通过对待排序序列从前向后&#xff08;从下标较小的元素开始&#xff09;&#xff0c;依次比较相邻元素的值&#xff0c; 若发现逆序则交换&#xff0c; 使值较大的元素逐…

netcore接入钉钉扫码登录

netcore接入钉钉扫码登录一、首先官方文档预览二、登录钉钉开发者后台三、创建第三方登录授权应用1.新版打开方式2.旧版打开方式&#xff08;1&#xff09;先返回旧版页面&#xff08;2&#xff09;选择应用开发&#xff08;3&#xff09;编辑登录应用信息&#xff08;4&#x…

npm包是什么?如何发布npm包?

Node的组成 内置模块 自定义模块 第三方模块&#xff08;什么是包&#xff1f;&#xff09; npm包包括那些东西&#xff1f; package.json README.md 。。。.js 注册npm账号 细节 发布包 package.json README.md index.js date htmlEscape 层级结构 发布指令 N…

STC15 - C51 - Memory Models

文章目录STC15 - C51 - Memory Models概述笔记内存用量的优化思路ENDSTC15 - C51 - Memory Models 概述 在STC上测试呢, 想看看变量(不同类型的定义)被编译器分配在哪个内存范围(idata, pdata, xdata)? 同时, 总结一下降低内存用量的思路(如果像上位机那样内存管够, 就不用考…

Linux系统编程第五节——进程创建、终止、等待(通俗易懂快速上手版本)

目录 进程的创建 写时拷贝 进程的终止 进程的等待 状态参数status wait函数和waitpid函数 我们本节内容&#xff0c;主要来讲述进程控制有关的内容。 同样&#xff0c;我们会用通俗易懂、不同于教科书的讲授思路&#xff0c;来为大家讲解。 同时&#xff0c;本节内容板块…

你了解你的身体吗?- 基因社会

关于作者 本书的两位作者分别是以太•亚奈和马丁 • 菜凯尔&#xff0c;前者是哈佛大学髙级研究学者&#xff0c; 任职于纽约大学&#xff0c;是生物化学和分子药理 学的教授&#xff1b;后者是杜塞尔多夫海因西里•海 涅大学的生物信息学教授。两位作者从基 因之间合作和竞争…

[附源码]计算机毕业设计的4s店车辆管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

5款十分好用,但是没有什么知名度的软件

随着网络信息技术的发展&#xff0c;越来越多的人在办公时需要用到电脑了。如果你想提高办公效率&#xff0c;那么就少不了工具的帮忙&#xff0c;今天给大家分享5款办公必备的好软件。 1.数据可视化软件——Power BI Power BI是一款出色的业务分析软件。Power BI主要是用于在…

[Go] go基础4

1. 并发编程 1.1 并发和并行 并发: 多个线程在同个核心的CPU上运行.并发的本质是串行. 并行: 多个线程在多个核心的CPU上运行. 1.2 协程和线程 协程: 独立的栈空间,共享堆空间,调度由用户控制,本质上有点类似用户及线程,这些用户及线程的调度也是自己实现的. 线程: 一个线…

[附源码]JAVA毕业设计网络饮品销售管理系统(系统+LW)

[附源码]JAVA毕业设计网络饮品销售管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

全新社交电商模式来袭,消费增值结合共享经济完成消费升级

大家好&#xff0c;我是林工&#xff0c;不知道大家是否了解消费增值&#xff1f;这是一个消费储量为基础的理念&#xff0c;体现的是消费者的消费与回报问题&#xff0c;普遍的消费返利&#xff0c;消费全返渐渐地已经不能够满足目前的客户&#xff0c;也就有了一个满足与这部…

【嵌入式硬件芯片开发笔记】4-20mA DAC芯片AD5421配置流程

【嵌入式硬件芯片开发笔记】4-20mA DAC芯片AD5421配置流程 16位、串行输入、环路供电、4 mA至20 mA DAC 可用于HART协议相关电路 同AD5700配合使用 AD5421的SPI和普通的不一样 回读时要发两段 CS中间拉高一次 数据在SCLK上升沿逐个输出&#xff0c;而且在 SCLK下降沿有效 固CP…

使用方法丨艾美捷Caspase-1活性分析试剂盒介绍

如何动态检测活细胞内的Caspase-1的活性&#xff0c;做更真实的实验&#xff1f;艾美捷推荐Immunochemistry Tech&#xff08;ICT&#xff09;的FLICA系列科研工具&#xff0c;轻松检测活细胞Caspase-1 活性。 艾美捷Immunochemistry Caspase-1活性分析试剂盒原理&#xff1a…

Qt第三十四章:总结【隐藏标题栏边框、隐藏背景、窗体透明】

目录 隐藏标题栏边框 ①隐藏标题栏代码&#xff1a; ​编辑②自定义标题栏(可以直接Copy) 使用 隐藏背景 ①隐藏背景代码,此时背景上的样式都是无效的。 ②自定义背景,通过重写paintEvent事件来完成 中间绘制的部分是我们想要的&#xff0c;只需要将标题栏边框隐藏掉就可…

五、卷积神经网络CNN5(图像卷积与反卷积)

图像卷积 首先给出一个输入输出结果那他是怎样计算的呢&#xff1f; 卷积的时候需要对卷积核进行 180 的旋转&#xff0c;同时卷积核中心与需计算的图像像素对齐&#xff0c;输出结构为中心对齐像素的一个新的像素值&#xff0c;计算例子如下&#xff1a;这样计算出左上角(即第…

【畅购商城】内网穿透之EchoSite

目录 概述 注册用户 抢注域名 ​​​​​​​下载客户端 ​​​​​​​编写配置文件 ​​​​​​​启动 ​​​​​​​访问 ​​​​​​​概述 EchoSite一款收费的内网映射工具&#xff08;已下架&#xff09; 花生壳&#xff1a;内网穿透工具&#xff0c;免费版…

springboot集成Lombok、MybaitsPlus、SwaggerUI

springboot集成Lombok、MybaitsPlus、SwaggerUI 基础环境&#xff1a;JDK8或者JDK11版本 Maven3.5(采⽤默认) IDEA旗舰版 Mysql5.7以上版本 创建springboot项目 在线构建⼯具 https://start.spring.io/ 修改pom.xml中内容 <!-- 代码库 --> <repositories> &l…

如何提高量化策略回测的效率

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…