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

大家好,有没有觉得写了好多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;yx = 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
//不同返回0return 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;elsearr[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.rhkb.cn/news/99804.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

opencv-gpu版本编译(添加java支持,可选)实现硬解码

目录 opencv gpu版本编译&#xff0c;实现硬解码&#xff0c;加速rtsp视频流读取1、准备文件2、复制 NVCUVID 头文件到 cuda 安装目录 include3、安装相关依赖4、 执行cmake5、编译安装6、测试 opencv gpu版本编译&#xff0c;实现硬解码&#xff0c;加速rtsp视频流读取 前置条…

复习3-5天【80天学习完《深入理解计算机系统》】第七天

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

git创建分支和合并分支

1.创建分支 git创建分支只需要使用switch 命令就行&#xff1a; git switch -c 分支名 创建分支并切换到该分支 后面括号里面的内容发生改变就是修改了分支 。 然后想要合并分支就在 创建的分支中 进行提交修改的内容&#xff0c;还是通过&#xff1a;add 命令和commit命令…

6.链路追踪-Zipkin

链路追踪&#xff08;Distributed Tracing&#xff09;是一种用于监视分布式应用程序的技术&#xff0c;通过收集和展示分布式系统中不同组件之间的调用和交互情况&#xff0c;帮助开发人员和运维团队理解系统中的请求流程、性能瓶颈和异常情况。 1.Zipkin Zipkin 是一个开源的…

(三)行为模式:4、迭代器模式(Iterator Pattern)(C++示例)

1、迭代器模式&#xff08;Iterator Pattern&#xff09;含义 迭代器模式&#xff08;Iterator&#xff09;&#xff0c;提供一种方法顺序访问一个聚合对象中各个元素&#xff0c;而不暴露该对象的内部表示。【DP】 通过使用迭代器模式&#xff0c;可以将遍历算法与集合对象解耦…

C#程序变量统一管理例子 - 开源研究系列文章

今天讲讲关于C#应用程序中使用到的变量的统一管理的代码例子。 我们知道&#xff0c;在C#里使用变量&#xff0c;除了private私有变量外&#xff0c;程序中使用到的公共变量就需要进行统一的存放和管理。这里笔者使用到的公共变量管理库划分为&#xff1a;1)窗体&#xff1b;2)…

一“码”当先,PR大征集!2023 和RT-Thread一起赋能开源!

活动地址&#xff1a;https://club.rt-thread.org/ask/article/3c7cf7345ca47a18.html 活动介绍 「一“码”当先&#xff0c;PR大征集&#xff01;」是一项为了鼓励开发者积极参与开源软件开发维护的活动。 你可在Github RT-Thread&#xff08; https://github.com/RT-Thread …

Unity的TimeScale的影响范围分析

大家好&#xff0c;我是阿赵。 这期来说一下Unity的TimeScale。 一、前言 Unity提供了Time这个类&#xff0c;来控制时间。其实我自己倒是很少使用这个Time&#xff0c;因为做网络同步的游戏&#xff0c;一般是需要同步服务器时间&#xff0c;所以我比较多是在使用System.Date…

【MySQL】多表查询

文章目录 1、单表查询2、表结构2.1 一对多&#xff08;多对一&#xff09; 3、多表查询(一对多)3.1 内连接&#xff08;where 、inner join&#xff09;3.2 外连接&#xff08;left join、right join&#xff09;3.3 自连接(inner join)3.4 联合查询(union all 、union&#xf…

【UML】详解UML类图

目录 1.概述 2.权限 3.关系 3.1.连线关系 3.2.依赖 3.3.泛化&#xff08;继承&#xff09; 3.4.实现 3.5.关联 3.6.聚合 3.7.组合 1.概述 UML是什么&#xff1f;书面化一点的说法是&#xff1a; UML&#xff08;Unified Modeling Language&#xff09;&#xff0c;…

【MaxKey对接一】对接gitlab的oauth登录

MaxKey的Oauth过程 引导进入 GET http://{{maxKey_host}}/sign/authz/oauth/v20/authorize?client_idYOUR_CLIENT_ID&response_typecode&redirect_uriYOUR_REGISTERED_REDIRECT_URI 登录后回调地址 YOUR_REGISTERED_REDIRECT_URI/?code{{code}} 换取Access Token GET…

简单认识镜像底层原理详解和基于Docker file创建镜像

文章目录 一、镜像底层原理1.联合文件系统(UnionFS)2.镜像加载原理3.为什么Docker里的centos的大小才200M? 二、Dockerfile1.简介2.Dockerfile操作常用命令 三、创建Docker镜像1.基于已有镜像创建2.基于本地模板创建3.基于Dockerfile创建4.Dockerfile多阶段构建镜像 一、镜像底…

Leetcode Top 100 Liked Questions(序号53~74)

53. Maximum Subarray 题意&#xff1a;一个数组&#xff0c;找到和最大的子串 我的思路 我记得好像On的动态规划来做的&#xff1f;但是想不起来了&#xff0c;先死做&#xff0c;用的前缀和——TLE超时 那就只能想想dp怎么做了 假设dp[i]表示的是以 i 为右端点的最大的…

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

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

prometheus blackbox_exporter安装

目录 一、准备工作1.1 安装或关闭以下服务1.2 本次安装环境 二、安装blackbox_exporter2.1 下载并解压2.2配置2.3测试 三、配置blackbox_exporter3.1配置blackbox.yml3.2 开启blackbox_exporter3.3配置prometheus.yml 四、其他4.1server returned HTTP status 400 Bad Request …

webpack 和 ts 简单配置及使用

如何使用webpack 与 ts结合使用 新建项目 &#xff0c;执行项目初始化 npm init -y会生成 {"name": "tsdemo01","version": "1.0.0","description": "","main": "index.js","scripts&…

基于飞蛾扑火算法优化的BP神经网络(预测应用) - 附代码

基于飞蛾扑火算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于飞蛾扑火算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.飞蛾扑火优化BP神经网络2.1 BP神经网络参数设置2.2 飞蛾扑火算法应用 4.测试结果&#xff1a;5…

【docker】基于dockerfile编写LNMP

目录 一、基础环境准备 二、部署nginx&#xff08;容器IP为172.18.0.10&#xff09; 1、整个Dockerfile文件内容 2、配置nginx.conf文件 3、构建镜像 ​编辑 三、部署mysql 1、整个Docker文件内容 2、准备my.conf文件 3、生成镜像 4、启动镜像容器 5、验证mysql 四、PH…

应用层读取wfp防火墙阻断记录

前言 之前的文档中&#xff0c;描写了如何对WFP防火墙进行操作[链接在此]&#xff0c;这篇文档中&#xff0c;描述如何获取WFP防火墙进行阻断的操作记录。 需要注意的坑点 使用FWPM_NET_EVENT_TYPE获取防火墙日志时&#xff0c;需要注意&#xff0c;只有丢弃和内核丢弃&…

Php“牵手”淘宝商品详情页数据采集方法,淘宝API接口申请指南

淘宝天猫详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在电商平台的开发中&#xff0c;详情接口API是非常常用的 API&#xff0c;因此本文将详细介绍详情接口 API 的使用。 一、…