【c语言】五子棋(EasyX图形库+背景音乐)

news2024/9/24 2:22:14

大家好,有没有觉得写了好多c语言代码,面对的都是黑框框控制台,当我们学习了基础的c语言知识,和EasyX图形库后,终于可以和黑框框saygoodbye,今天要分享给大家的是小游戏五子棋,跟着小张一起学习吧


EasyX图形库安装

图形库链接

在这里插入图片描述
1.点击下载

在这里插入图片描述
2.安装你对应集成开发环境对应的安装包,我用的是vs2019

在这里插入图片描述
3.ok,我们使用库函数,加上头文件即可

棋盘的绘制

注意创建必须是.cpp,要不然图形库用不了

在这里插入图片描述棋盘大小我们搞成15*15的格子,每个格子长宽为30,每个棋子半径搞成13,棋盘格长450,宽450,为了防止边界下的棋子显示不完全,每个边在向外延申15,界面总大小为480×480
在这里插入图片描述

1.棋盘木板

initgraph(480, 480);//初始化一个窗口(窗口大小480*480);

此时窗口闪一下就消失了,尝试加一个while循环

#include<graphics.h>//包含图形库头文件
int main()
{
	initgraph(480, 480);
	while (1)
	{
	}


}

编译运行:在这里插入图片描述
这个并非控制台的黑框框

五子棋背景一般是棕色,我们需要自己画一个棕色背景图片贴上去,大小和界面大小480*480一样大请添加图片描述

IMAGE p;//定义一个图片变量
loadimage(&p, "./background.png", 480, 480);//加载图片函数,(参数1图片地址,参数2图片的位置,图片大小)

./为当前目录下,和.c文件放在一个目录下面
在这里插入图片描述

putimage(0, 0, &p);//贴图片到界面上去(参数1,2为图片从界面的哪个位置开始贴)

在这里插入图片描述

#include<graphics.h>//包含图形库头文件
IMAGE p;
int main()
{
	initgraph(480, 480);
	loadimage(&p, "./background.png", 480, 480);
	putimage(0, 0, &p);
	while (1)
	{
	}


}

在这里插入图片描述如果出现该问题,调试>属性>高级>字符集改为多字符集就行了

编译运行:在这里插入图片描述


2.开始画线

setlinecolor(BLACK);//设置线颜色的函数(黑线)
for (int x = 15; x < 480; x += 30)//循环画竖线
	{
		line(x, 15, x, 465);//画线函数,前两个参数为起始点x,y,后两个参数为终点x,y
	}
	for (int y= 15; y < 480; y+= 30)//循环画横线
	{
		line(15, y, 465,y);
	}
#include<graphics.h>//包含图形库头文件
IMAGE p;
int main()
{
	initgraph(480, 480);
	loadimage(&p, "./background.png", 480, 480);
	putimage(0, 0, &p);
	setlinecolor(BLACK);
	for (int x = 15; x < 480; x += 30)
	{
		line(x, 15, x, 465);
	}
	for (int y = 15; y < 480; y += 30)
	{
		line(15, y, 465, y);
	}
	while (1)
	{
	}


}

编译运行
在这里插入图片描述

3.专业棋盘好像有5个黑点点(圆)

在这里插入图片描述对应五个点的坐标

setfillcolor(BLACK);//设置圆的颜色
	fillcircle(15 + 3 * 30, 15 + 3 * 30, 3);前两个参数为圆的圆心坐标,第三个参数为圆的半径
	fillcircle(15 + 3 * 30, 15 + 11 * 30, 3);
	fillcircle(15 + 11 * 30, 15 + 3 * 30, 3);
	fillcircle(15 + 7 * 30, 15 + 7 * 30, 3);
	fillcircle(15 + 11 * 30, 15 + 11 * 30, 3);

编译运行
在这里插入图片描述

#include<graphics.h>//包含图形库头文件
IMAGE p;
int main()
{
	initgraph(480, 480);
	loadimage(&p, "./background.png", 480, 480);
	putimage(0, 0, &p);
	setlinecolor(BLACK);
	for (int x = 15; x < 480; x += 30)
	{
		line(x, 15, x, 465);
	}
	for (int y = 15; y < 480; y += 30)
	{
		line(15, y, 465, y);
	}
	setfillcolor(BLACK);
	fillcircle(15 + 3 * 30, 15 + 3 * 30, 3);
	fillcircle(15 + 3 * 30, 15 + 11 * 30, 3);
	fillcircle(15 + 11 * 30, 15 + 3 * 30, 3);
	fillcircle(15 + 7 * 30, 15 + 7 * 30, 3);
	fillcircle(15 + 11 * 30, 15 + 11 * 30, 3);
	while (1)
	{
	}


}

获取鼠标点击

ExMessage msg;//消息结构体变量
if (peekmessage(&msg, EX_MOUSE)) //偷瞄消息,第一个消息结构体地址,第二个参数,鼠标消息
		{
			switch (msg.message)   //鼠标消息
			{
			case WM_LBUTTONDOWN:                      //左键
				draw(msg.x, msg.y);//鼠标光标位置坐标
				break;
			
			}
		}

当鼠标左键按下时,将此时的鼠标在对应界面的坐标传递给draw函数,需要随时获取鼠标的消息,将上述代码放在循环里面

	while (1)
	{
		if (peekmessage(&msg, EX_MOUSE))              //偷瞄消息,第一个消息结构体地址,鼠标消息
		{
			switch (msg.message)                      //鼠标消息
			{
			case WM_LBUTTONDOWN:                      //左键
				draw(msg.x, msg.y);
				break;
			
			}
		}
		



	}

画棋子

将鼠标点击的坐标传到draw函数中来,定义一个全局变量num,判断是黑子,还是白子,num=1,黑子下,num=-1,白子下。

int num = 1;
void draw(int m, int n)
{
	if (num == -1)
	{
		setfillcolor(WHITE);//设置圆的填充色(白色)白棋
    }
	else if (num == 1)
	{
		setfillcolor(BLACK);//设置圆的填充色(黑色)黑棋
    }
    fillcircle(m - m % 30 + 15, n - n % 30 + 15, 13);//画圆,圆的x,y,半径,棋子的绘制
    num *= -1;//黑白棋轮着下,每次调用draw,改变num值,实现黑白黑白黑白


}

为什么棋子坐标是(m - m % 30 + 15, n - n % 30 + 15),因为鼠标不可能一点就是要下的坐标,只能鼠标点在某一个范围,就把该棋子落在离鼠标点的位置最近的位置,如果鼠标的坐标为48,48传给draw时,在这里插入图片描述
我们知道应该下在这个位置,经过处理后是45,45,刚好是要下的位置,避免棋子落在不该落的位置。

编译运行
在这里插入图片描述

解决棋子可以下在棋子上面的问题

在这里插入图片描述>在点一次黑色棋子被覆盖
我们可以定义一个二维数组,15*15,刚开始初始化为0,如果数组下标对应棋盘的地方有黑棋,把对应二维数组中的值放1,如果数组下标对应棋盘的地方有白棋,把对应二维数组中的值放-1;如果鼠标点击的位置有棋子的话,直接return掉,不进行绘制棋子

二维数组的初始化:

int arr[15][15];//全局变量好操作
void initboard()
{
	for (int i = 0; i < 15; i++)
	{
		for (int j = 0; j < 15; j++)
		{
			arr[i][j] = 0;//循环初始化二维数组
       }
       }
}
int full(int x, int y)
{
	if (arr[x][y] != 0)//如果不等于0,表示下过棋了return 0;
		return 0;
	else//如果等于0,表示没下过棋了,将该数组对应位置放num,return 1;
		arr[x][y] = num;
	     return 1;
}
void draw(int m,int n)
{
	if (num == -1)
	{       setfillcolor(WHITE);
	         
			
		
	}
	else if (num == 1)
	{       setfillcolor(BLACK);
			
		
	}
	
	
	int x;
	int y;y
	x = m / 30;//二维数组横坐标,m鼠标横坐标,如果m=48,x就是1,
	y = n / 30;//二维数组纵坐标n鼠标纵坐标,如果n=48,y就是1,
	if (full(x,y) == 0)//等于0表示下过棋了,直接return;跳出draw,如果=1,跳过这个条件判断语句,开始下棋
		return;


	fillcircle(m - m % 30 + 15, n - n % 30 + 15, 13);//下棋

	num *= -1;


}


此时不能下下过的位置

判断输赢

int check_over()
{
	for (int i = 0; i < 15; i++)
	{
		for (int j = 0; j < 15; j++)
		{
			if (arr[i][j] == 0)
				continue;
			if (check_five(i, j) == 1)
			{
				q = arr[i][j];
				return 1;
			}




		}


	}

}

因为二维数组记录了下棋的状况,对应位置为1则是黑棋,-1为白棋,0是未下,循环遍历每个数组元素,先是找到下过棋的位置,没下过棋的位置直接跳过,因为我们是通过这个函数将下过棋的坐标传给
check_five(int x, int y),然后根据下x,y坐标相邻的五个是否一样,如果没下的话直接跳过,防止五个相邻位置没下棋都是0,进入check_five(int x, int y),五个0也是一样,然后游戏就结束了

int check_five(int x, int y)
{//检查一个下过棋的坐标相邻五个是否一样
	
	if (arr[x][y] == arr[x - 1][y] && arr[x][y] == arr[x - 2][y] && arr[x][y] == arr[x + 1][y] && arr[x][y] == arr[x + 2][y])//横行判断
		return 1;
	if (arr[x][y] == arr[x][y-1] && arr[x][y] == arr[x][y-2] && arr[x][y] == arr[x][y+1] && arr[x][y] == arr[x][y+2])//纵行判断
		return 1;
	if (arr[x][y] == arr[x - 1][y-1] && arr[x][y] == arr[x - 2][y-2] && arr[x][y] == arr[x + 1][y+1] && arr[x][y] == arr[x + 2][y+2])以该坐标为中心,主对角线判断
		return 1;
	if (arr[x][y] == arr[x - 1][y+1] && arr[x][y] == arr[x+2][y-2] && arr[x][y] == arr[x + 1][y-1] && arr[x][y] == arr[x-2][y+2])以该坐标为中心,副对角线判断
		return 1;
//相同则返回1
//不同返回0
	
	return 0;
}

在check_over()中如果check_five(i, j) 返回一,则有五个连成,将该坐标对应二维数组中的值保存在q全局变量中,然后check_over()返回1

if (check_over() == 1)
		{
			outtextxy(180, 180, "游戏结束");//输出文字,参数一参数二为文字左上角坐标,参数三为文字内容
			//change();//消息盒子函数,提示谁赢了
			system("pause");//退出程序,头文件windows.h

		}

在调用之前必须

	settextstyle(40, 20, "隶书");//设置字体高度,宽度,字体的格式
	setbkmode(TRANSPARENT);//字体后面设置透明,背景模式

编译运行
在这里插入图片描述

提示输赢

void change()//消息盒子函数,提示谁赢了
{

	HWND hnd = GetHWnd();  //获取窗口句柄(相当于窗口的指针)
	SetWindowText(hnd, "五子棋"); //设置窗口标题
	int isok;
				if(q==1)//q获取的是赢家对应二维数组的消息,黑子为1											//
	       isok = MessageBox(NULL, "黑子胜", "提示", MB_OKCANCEL); //弹出消息盒子,提示用户操作
			else if(q==-1)
				isok = MessageBox(NULL, "白子胜", "提示", MB_OKCANCEL);
			

	if (IDOK== isok)                                             //返回点了哪里
	{                                                            //点了ok
		
	}
	else if (IDCANCEL == isok)                               //点了取消
	{
		
		

	}
}

编译运行
在这里插入图片描述
在这里插入图片描述

背景音乐函数

这里可以去看动态通讯录那一篇,加音乐有具体步骤

#include<graphics.h>//包含图形库头文件
#include<mmsystem.h>//包含多媒体设备接口头文件

#pragma comment(lib,"winmm.lib")//加载静态库
void bgm()
{    //打开音乐
	mciSendString("open ./music.MP3", 0, 0, 0);//后面参数不用管
	//播放音乐
	mciSendString("play ./music.MP3", 0, 0, 0);//后面参数不用管
}

整体代码展示


#include <windows.h>
#include<graphics.h>//包含图形库头文件
#include<mmsystem.h>//包含多媒体设备接口头文件

#pragma comment(lib,"winmm.lib")//加载静态库
IMAGE p;
int num = 1;
int q;
int arr[15][15];
void change()
{

	HWND hnd = GetHWnd();                                             //获取窗口句柄(相当于窗口的指针)
	SetWindowText(hnd, "五子棋"); 
	int isok;//设置窗口标题
				if(q==1)											//
	       isok = MessageBox(NULL, "黑子胜", "提示", MB_OKCANCEL); //弹出消息盒子,提示用户操作
			else if(q==-1)
				isok = MessageBox(NULL, "白子胜", "提示", MB_OKCANCEL);
			

	if (IDOK== isok)                                             //返回点了哪里
	{                                                            //点了ok
		
	}
	else if (IDCANCEL == isok)                               //点了取消
	{
		
		

	}
}
void bgm()
{    //打开音乐
	mciSendString("open ./music.MP3", 0, 0, 0);//后面参数不用管
	//播放音乐
	mciSendString("play ./music.MP3", 0, 0, 0);//后面参数不用管
}
void initboard()
{
	for (int i = 0; i < 15; i++)
	{
		for (int j = 0; j < 15; j++)
		{
			arr[i][j] = 0;




		}



	}
}
int full(int x, int y)
{
	if (arr[x][y] != 0)
		return 0;
	else
		arr[x][y] = num;
	     return 1;
}
void draw(int m,int n)
{
	if (num == -1)
	{       setfillcolor(WHITE);
	         
			
		
	}
	else if (num == 1)
	{       setfillcolor(BLACK);
			
		
	}
	
	
	int x;
	int y;
	x = m / 30;
	y = n / 30;
	if (full(x,y) == 0)
		return;


	fillcircle(m - m % 30 + 15, n - n % 30 + 15, 13);

	num *= -1;


}
int check_five(int x, int y)
{
	//if (x < 2 || y < 2 || x>12 || y>12)
		//return 0;
	if (arr[x][y] == arr[x - 1][y] && arr[x][y] == arr[x - 2][y] && arr[x][y] == arr[x + 1][y] && arr[x][y] == arr[x + 2][y])
		return 1;
	if (arr[x][y] == arr[x][y-1] && arr[x][y] == arr[x][y-2] && arr[x][y] == arr[x][y+1] && arr[x][y] == arr[x][y+2])
		return 1;
	if (arr[x][y] == arr[x - 1][y-1] && arr[x][y] == arr[x - 2][y-2] && arr[x][y] == arr[x + 1][y+1] && arr[x][y] == arr[x + 2][y+2])
		return 1;
	if (arr[x][y] == arr[x - 1][y+1] && arr[x][y] == arr[x+2][y-2] && arr[x][y] == arr[x + 1][y-1] && arr[x][y] == arr[x-2][y+2])
		return 1;

	
	return 0;
}
int check_over()
{
	for (int i = 0; i < 15; i++)
	{
		for (int j = 0; j < 15; j++)
		{
			if (arr[i][j] == 0)
				continue;
			if (check_five(i, j) == 1)
			{
				q = arr[i][j];
				return 1;
			}




		}


	}

}
int main()
{
	bgm();
	ExMessage msg;
	
	initgraph(480, 480);
	loadimage(&p,"./background.png",480,480);
	putimage(0, 0, &p);
	setlinecolor(BLACK);
	for (int x = 15; x < 480; x += 30)
	{
		line(x, 15, x, 465);
	}
	for (int y= 15; y < 480; y+= 30)
	{
		line(15, y, 465,y);
	}
	setfillcolor(BLACK);
	fillcircle(15 + 3 * 30, 15 + 3 * 30, 3);
	fillcircle(15 + 3 * 30, 15 + 11 * 30, 3);
	fillcircle(15 + 11 * 30, 15 + 3 * 30, 3);
	fillcircle(15 + 7 * 30, 15 + 7 * 30, 3);
	fillcircle(15 + 11 * 30, 15 + 11 * 30, 3);
	settextstyle(40, 20, "隶书");
	setbkmode(TRANSPARENT);
	





	while (1)
	{
		if (peekmessage(&msg, EX_MOUSE))              //偷瞄消息,第一个消息结构体地址,鼠标消息
		{
			switch (msg.message)                      //鼠标消息
			{
			case WM_LBUTTONDOWN:                      //左键
				draw(msg.x, msg.y);
				break;
			
			}
		}
		if (check_over() == 1)
		{
			outtextxy(180, 180, "游戏结束");
			change();
			system("pause");

		}



	}
}

效果展示

20230821_194813

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

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

相关文章

(四)Doceke安装MySQL镜像+Docker启动MySQL容器

Doceke安装MySQL镜像/Docker启动MySQL容器 一、doceke安装MySQL镜像 切换到root用户&#xff0c;su root 。 1、启动Docker 启动&#xff1a;sudo systemctl start docker 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 查看docker运行…

视频汇聚平台EasyCVR安防视频监控在地下停车场中的具体应用方案

一、背景 随着我国城市化进程的加快&#xff0c;汽车已成为人们生活中不可缺少的交通工具&#xff0c;但在许多城市中&#xff0c;买车容易&#xff0c;停车难的问题愈发突出。特别是在人群密集的商场、写字楼和地下停车场&#xff0c;车流量大、车况复杂。传统的人工判断方式耗…

go、java、.net、C#、nodejs、vue、react、python程序问题进群咨询

1、面试辅导 2、程序辅导 3、一对一腾讯会议辅导 3、业务逻辑辅导 4、各种bug帮你解决。 5、培训小白 6、顺利拿到offer

【网络基础实战之路】基于三层架构实现一个企业内网搭建的实战详解

系列文章传送门&#xff1a; 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 【网络基础实战之路】基于…

Lombok生成的Getter和Setter的名称对于“eMail”或“xAxis”等属性存在大小写转换异常

问题 最新开发中&#xff0c;遇到一个字段映射问题。我们先看问题案例&#xff1a; 明明代码中第二个字母是大写&#xff0c;结果测试接口时发现变成了小写字母。 分析 通过网上查询发现&#xff0c;这属于Lombok的bug。而且早在2015年就有人在GitHub上提出了issues。 Names o…

基于SpringBoot房产销售系统【附ppt|开题|万字文档(LW)和搭建文档】

主要功能 前台界面&#xff1a; ①首页、房源信息推荐、房源信息展示、查看更多等 ②房源信息、房源名称、房源户型、销售姓名等 ③购房、预约、点我收藏、评论等 ④个人中心、我的收藏、支付等 后台登录&#xff1a; ①首页、个人中心&#xff1a;修改密码、用户信息管理等 ②…

三角函数与圆,角度和弧度 (草稿,建设中)

目录 1 三角函数与圆&#xff0c;角度和弧度 1.1 三角形 1.2 圆形 2 角度 3 弧度 rad 4 角度&#xff0c;弧度的换算 2 三角函数 1 三角函数与圆&#xff0c;角度和弧度 1.1 三角形 角度弧长sin()cos()tan() 1.2 圆形 半径&#xff0c;周长&#xff0c;弧长半径面积 …

Linux面试笔试题(2)

27、按下( A ) 键能终止当前运行的命令 A. Ctrl-C B. Ctrl-F C. Ctrl-B D. Ctrl-D 28、下面哪个命令用来启动X Window ( C ) A. runx B. Startx C. startX D. xwin 29、用 “rm -i”,系统会提示什么来让你确认( B ) A.命令行的每个选项 B.是否真的删除 C.是否有写的权限 D…

计算机网络第2章(物理层)

计算机网络第2章&#xff08;物理层&#xff09; 2.1 物理层的基本概念2.2 物理层下面的传输媒体2.2.1 导引型传输媒体2.2.2 非导引型传输媒体 2.3 传输方式2.3.1 串行传输和并行传输2.3.2 同步传输和异步传输2.3.3 单向通信&#xff08;单工&#xff09;、双向交替通信&#x…

【Leetcode】105.从前序与中序遍历序列构造二叉树

一、题目 1、题目描述 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 示例1: 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]示例…

口腔牙科门诊挂号系统 微信小程序的设计与实现_1171u-

随着信息时代的来临&#xff0c;过去的“口腔助手”管理方式缺点逐渐暴露&#xff0c;现在对过去的“口腔助手”管理方式的缺点进行分析&#xff0c;采取计算机方式构建“口腔助手”小程序。本文通过阅读相关文献&#xff0c;研究国内外相关技术&#xff0c;提出了一种预约信息…

睿趣科技:抖音小店新人最适合卖什么产品

随着移动互联网的不断发展&#xff0c;短视频平台如今已经成为了人们日常生活中不可或缺的一部分。其中&#xff0c;抖音作为国内短视频平台的代表&#xff0c;不仅让用户可以欣赏到各种有趣、创意的短视频内容&#xff0c;同时也为创业者提供了一个广阔的创业机会——抖音小店…

【数据结构入门指南】二叉树顺序结构: 堆及实现(全程配图,非常经典)

【数据结构入门指南】二叉树顺序结构: 堆及实现&#xff08;全程配图&#xff0c;非常经典&#xff09; 一、前言&#xff1a;二叉树的顺序结构二、堆的概念及结构三、堆的实现&#xff08;本篇博客以实现小堆为例&#xff09;3.1 准备工作3.2 初始化3.3 堆的插入3.3.1 向上调…

【五子棋】

五子棋 文章目录 五子棋前言一、登录功能二.哈希表管理用户的会话和房间三.基于Websocket连接开发的功能1.匹配功能2.游戏房间3.挑战功能4.人机对战5.聊天功能 前言 这篇博客主要详细介绍我的五子棋项目的核心功能的实现细节&#xff0c;也就是详细介绍五子棋各个功能是如何实…

Java IO流(三)线程模型

传统阻塞I/O模式 其中黄色框表示对象,蓝色框表示线程,白色框表示API方法 特点 采用阻塞IO模式获取输入数据每个连接都需要独立的线程完成数据的输入,业务处理和处理结果数据返回 潜在问题 并发数很大时,需要对应每个连接请求创建一个线程,所以占用资源很大连接创建后,若当前…

CentOS系统环境搭建(十七)——elasticsearch设置密码

centos系统环境搭建专栏&#x1f517;点击跳转 elasticsearch设置密码 没有密码是很不安全的一件事&#x1f62d; 文章目录 elasticsearch设置密码1.设置密码2.登录elasticsearch3.登录kibana4.登录elasticsearch-head 1.设置密码 关于Elasticsearch的安装请看CentOS系统环境搭…

每天一道leetcode:1306. 跳跃游戏 III(图论中等广度优先遍历)

今日份题目&#xff1a; 这里有一个非负整数数组 arr&#xff0c;你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时&#xff0c;你可以跳到 i arr[i] 或者 i - arr[i]。 请你判断自己是否能够跳到对应元素值为 0 的 **任一** 下标处。 注意&#xff0c;不管是什…

【C++从0到王者】第二十二站:一文讲透多继承与菱形继承

文章目录 前言一、多继承二、菱形继承三、菱形虚拟继承四、菱形虚拟继承的底层原理五、菱形虚拟继承对于空间的优化六、多继承和菱形继承中的一些细节七、菱形继承在库里面的应用八、继承和组合九、继承总结 前言 在我们前面所说的继承其实在C中也叫做单继承 即一个子类只有一…

【Python爬虫案例】爬取大麦网任意城市的近期演出!

老规矩&#xff0c;先上结果&#xff1a; 含10个字段&#xff1a; 页码&#xff0c;演出标题&#xff0c;链接地址&#xff0c;演出时间&#xff0c;演出城市&#xff0c;演出地点&#xff0c;售价&#xff0c;演出类别&#xff0c;演出子类别&#xff0c;售票状态。 代码演示…

2023年清洁能源与智能电网国际会议(CCESG 2023)

会议简介 Brief Introduction 2023年清洁能源与智能电网国际会议(CCESG 2023) 会议时间&#xff1a;2023年 召开地点&#xff1a;中国南宁 大会官网&#xff1a;CCESG 2023-2023 International Joint Conference on Clean Energy and Smart Grid 由IASED主办&#xff0c; CoreS…