EasyX见缝插针

简介: 这篇博客介绍了如何使用C++和EasyX图形库来实现一个见缝插针的小游戏,包括绘制圆盘和针、实现旋转、发射针、判断游戏输赢以及绘制分数等功能。

话不多说,先上图

EasyX见缝插针

如何实现一个见缝插针游戏??

  1. 如何绘制圆盘与针
  2. 如何实现旋转
  3. 如何按下空格发射针
  4. 如何判定游戏输赢

1.绘制圆盘以及一根针

#include<graphics.h>
#include<conio.h>
#define WIDTH 800  //窗口的宽
#define HEIGHT 600  //窗口的高

int main()
{
    initgraph(WIDTH, HEIGHT);       //初始化窗口
    setbkcolor(RGB(255, 255, 255)); //设置背景色为白色
    cleardevice();    //清屏
    //画针
    setlinestyle(PS_SOLID, 3);  //实线 线宽为3
    setlinecolor(RGB(0, 0, 0)); //设置线颜色为黑色
    line(WIDTH / 2, HEIGHT / 2, WIDTH / 2 + 160, HEIGHT / 2);

    //绘制圆盘
    setlinecolor(HSVtoRGB(0,0.9,0.8));
    circle(WIDTH / 2, HEIGHT / 2, 60);
    _getch();

    closegraph();  //关闭窗口
    system("pause");
    return 0;
}

在这里插入图片描述

2.实现针的旋转

  • 实现旋转时,注意此时的二维坐标系的Y轴与我们平时使用的二维坐标系是相反的

  • 实现顺时针旋转使用sin(角度)

  • 实现逆时针旋转使用sin(-角度)
    在这里插入图片描述

  • 实现A到B为顺时针旋转
    则Y轴坐标为圆心Y坐标+Rsin(角度)

  • 实现B到A为逆时针旋转
    则Y轴坐标为圆心Y坐标+Rsin(-角度)

  • X轴cos(-角度)或者cos(角度)正负均可

  • 双缓冲绘图(批量绘图),解决循环绘图出现的闪屏现象

#include<graphics.h>
#include<conio.h>
#include<math.h>
#define WIDTH 800  //窗口的宽
#define HEIGHT 600  //窗口的高
#define PI 3.1415926

int main()
{
    initgraph(WIDTH, HEIGHT);
    float lineLength = 160;                //针的长度
    float xEnd = (WIDTH / 2) + lineLength;  //针的末端x坐标
    float yEnd = HEIGHT / 2;                 //针的末端y坐标
    float angle = 0;                      //针的旋转角度
    float rotateSpeed = PI / 360;        //旋转的速度
    setbkcolor(RGB(255, 255, 255));    //设置背景色为白色
    cleardevice();    //清屏
    while (1)
    {
        //加双缓冲绘图防止闪屏
        BeginBatchDraw();
        cleardevice();
        angle += rotateSpeed;        //增加角度
        if (angle > PI * 2)          //防止angle无限增加而导致越界
            angle -= 2 * PI;
        xEnd = lineLength * cos(-angle) + WIDTH / 2;
        yEnd = lineLength * sin(angle) + HEIGHT / 2;
        //画针
        setlinestyle(PS_SOLID, 3);  //实线 线宽为3
        setlinecolor(RGB(0, 0, 0)); //设置线颜色为黑色
        line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);

        //绘制圆盘
        setlinecolor(HSVtoRGB(0, 0.9, 0.8));
        circle(WIDTH / 2, HEIGHT / 2, 60);

        Sleep(10);
        EndBatchDraw();
    }

    _getch();

    closegraph();  //关闭窗口
    system("pause");
    return 0;
}

在这里插入图片描述

3.实现多个针的绘制以及旋转

  • 需要一个针的初始角度数组去保存每一根针的初始角度
  • 需要变量保存针的个数
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define WIDTH 800  //窗口的宽
#define HEIGHT 600  //窗口的高
#define PI 3.1415926
#define MAXSIZE 20 //针的最大个数

int main()
{
    initgraph(WIDTH, HEIGHT);
    float lineLength = 160;          //针的长度
    float xEnd = (WIDTH / 2) + lineLength;  //针的终点X坐标
    float yEnd = HEIGHT / 2;                //针的终点Y坐标
    float angle[MAXSIZE] = { 0 };        //针的旋转角度
    float rotateSpeed = PI / 360;      //旋转的速度
    //设置每一根针的偏转角度
    for (int i = 0; i < MAXSIZE; i++)
    {
        angle[i] = i * (2 * PI / MAXSIZE);
    }
    setbkcolor(RGB(255, 255, 255));    //设置背景色为白色
    cleardevice();                     //清屏
    while (1)
    {
        //加双缓冲绘图防止闪屏
        BeginBatchDraw();
        cleardevice();

        //绘制全部的针
        for (int i = 0; i < MAXSIZE; i++)
        {
            angle[i] += rotateSpeed;       //增加针的初始角度实现旋转效果
            if (angle[i] > PI * 2)
                angle[i] -= 2 * PI;
            xEnd = lineLength * cos(-angle[i]) + WIDTH / 2;
            yEnd = lineLength * sin(angle[i]) + HEIGHT / 2;
            //画针
            setlinestyle(PS_SOLID, 3);  //实线 线宽为3
            setlinecolor(RGB(0, 0, 0)); //设置线颜色为黑色
            line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
        }
        //绘制圆盘
        setlinecolor(HSVtoRGB(0, 0.9, 0.8));
        setfillcolor(HSVtoRGB(0, 0.9, 0.8));
        fillcircle(WIDTH / 2, HEIGHT / 2, 60);

        Sleep(10);
        EndBatchDraw();
    }
    _getch();
    closegraph();  //关闭窗口
    system("pause");
    return 0;
}

在这里插入图片描述

4.实现用户插入的那根针,以及用户按键操作

  • 通过函数实现各个功能
  • 需要使用全局变量以及static全局变量
#include<graphics.h>
#include<conio.h>
#include<math.h>
#define WIDTH 800  //窗口的宽
#define HEIGHT 600  //窗口的高
#define LINELENGTH 160   //针的长度
#define PI 3.1415926

static int lineNum = 0;           //初始化针的个数为0根
float angle[180] = { 0 };        //每个针的旋转角度数组
float xEnd = 0;                  //针的终点X坐标
float yEnd = 0;                  //针的中断Y坐标
float rotateSpeed = PI / 360;      //旋转的速度

//添加针以及初始化当前针的角度
void beamNeedle()
{
    angle[lineNum++] = PI;   //新针初始角度为PI
    //初始化针的末端坐标
    xEnd = LINELENGTH * cos(-angle[lineNum - 1]) + WIDTH / 2;
    yEnd = LINELENGTH * sin(angle[lineNum - 1]) + HEIGHT / 2;
    line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);   //绘制针
}
//针的旋转
void needleRotate()
{
    for (int i = 0; i < lineNum; i++)
    {
        angle[i] += rotateSpeed;        //增加角度
        if (angle[i] > PI * 2)
            angle[i] -= 2 * PI;
        xEnd = LINELENGTH * cos(-angle[i]) + WIDTH / 2;
        yEnd = LINELENGTH * sin(angle[i]) + HEIGHT / 2;
        line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
    }
}
//用户按键处理
void userKey()
{
    if (_kbhit())    //检测是否存在按键
    {
        char userKey = _getch();  //保存用户输入的按键
        if (userKey == ' ')       //按键为空格就发射针
        {
            beamNeedle();      //调用添加针以及初始化当前针的角度
        }
    }
}
//绘制圆盘
void drawCircle()
{
    setlinecolor(HSVtoRGB(0, 0.9, 0.8));
    setfillcolor(HSVtoRGB(0, 0.9, 0.8));
    fillcircle(WIDTH / 2, HEIGHT / 2, 60);
}
//绘制发射的针(左侧的那根针)
void stoneNeedle()
{
    //绘制一根发射的针
    setlinecolor(RGB(0, 0, 0));
    setlinestyle(PS_SOLID, 3);  //实线 线宽为3
    line(0, HEIGHT / 2, LINELENGTH, HEIGHT / 2);
}

int main()
{
    initgraph(WIDTH, HEIGHT);
    setbkcolor(RGB(255, 255, 255)); //设置背景色为白色
    cleardevice();    //清屏
    while (1)
    {
        //加双缓冲绘图防止闪屏
        BeginBatchDraw();
        cleardevice();

        stoneNeedle();    //绘制发射的针
        needleRotate();   //绘制所有的针
        userKey();        //获取用户输入
        drawCircle();      //绘制圆盘

        Sleep(10);
        EndBatchDraw();
    }

    closegraph();  //关闭窗口
    system("pause");
    return 0;
}

在这里插入图片描述

5.实现游戏结束处理,以及分数的绘制

  • 游戏结束的判断
  • 只需要遍历圆盘上的针,当它们的角度差<PI/60时,做出重玩游戏还是退出的处理
  • 头文件添加

因为使用了求绝对值的函数,因此需要加 math.h

#include<math.h>
void dieGame()
{
    for (int i = 0; i < lineNum - 1; i++)  //当前针与之前所有针比较
    {
        if (lineNum == 0)
        {
            printf("没有针啊!\n");
            break;
        }
        if (fabs(angle[lineNum - 1] - angle[i]) < PI / 60)
        {
            int isok = MessageBox(GetHWnd(), "Low B you Die! 是否退出?",
             "游戏结束", MB_YESNO | MB_ICONWARNING); //显示警告
            if (MouseHit())    //监听鼠标消息
            {
                MOUSEMSG msg = GetMouseMsg();
                if (isok == IDYES)
                {
                    exit(666);   //退出
                }
                else      //重新玩
                {
                    lineNum = 0;  //将针的个数置为0
                    cleardevice();
                }
            }
        }
    }
}
  • 分数的绘制
  • 加处理安全检查的宏定义
  • 由于需要使用sprintf()函数因此需要做上一步安全性检查的处理
#define _CRT_SECURE_NO_WARNINGS
  • 添加一个全局变量用于保存分数
int score = 0;   //分数
  • 实现分数的变化
  • 实现分数变化只需要在游戏判断输赢中做处理即可
void dieGame()
{
    for (int i = 0; i < lineNum - 1; i++)  //当前针与之前所有针比较
    {
        if (lineNum == 0)
        {
            printf("没有针啊!\n");
            break;
        }
        if (fabs(angle[lineNum - 1] - angle[i]) < PI / 60)
        {
            int isok = MessageBox(GetHWnd(), "Low B you Die! 是否退出?", "游戏结束", MB_YESNO | MB_ICONWARNING); //显示警告
            if (MouseHit())    //监听鼠标消息
            {
                MOUSEMSG msg = GetMouseMsg();
                if (isok == IDYES)
                {
                    exit(666);   //退出
                }
                else
                {
                    lineNum = 0;  //将针的个数置为0
                    cleardevice();
                }
            }
        }
    }
    score = lineNum * 10;
}
  • 实现分数的绘制
//绘制分数
void printScore()
{
    char buffer[20] = "";
    sprintf(buffer, "分数: %d", score);
    settextcolor(RGB(255, 0, 255));
    settextstyle(50, 0, "宋体");
    outtextxy(20, 20, buffer);
}

在这里插入图片描述

6.增加游戏的趣味性

  • 随机针的颜色
    只需要不断随机改变绘制针的颜色即可
    头文件引入
#include<time.h>
//针的旋转
void needleRotate()
{
    //*********************************************************
    srand((unsigned int)time(NULL));   //随机数随时间变化
    //*********************************************************
    for (int i = 0; i < lineNum; i++)
    {
        angle[i] += rotateSpeed;        //增加角度
        if (angle[i] > PI * 2)
            angle[i] -= 2 * PI;
        xEnd = LINELENGTH * cos(-angle[i]) + WIDTH / 2;
        yEnd = LINELENGTH * sin(angle[i]) + HEIGHT / 2;
        //*********************************************************
        setlinecolor(RGB(rand()%256, rand()%256, rand()%256));  //随机改变颜色
        //*********************************************************
        line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
    }
}
  • 圆盘上有一定针的时候,加快旋转速度
//针的旋转
void needleRotate()
{
    srand((unsigned int)time(NULL));   //随机数随时间变化
    //*********************************************************
        if (lineNum >= 10 && lineNum < 20)   //随针变多,速度增加
    {
        rotateSpeed = 2 * PI / 360;    //旋转速度变为原来的两倍
    }
    else if (lineNum >= 20)
    {
        rotateSpeed = 3 * PI / 360;   //旋转速度变为原来的三倍
    }
    //*********************************************************
    for (int i = 0; i < lineNum; i++)
    {
        angle[i] += rotateSpeed;        //增加角度
        if (angle[i] > PI * 2)
            angle[i] -= 2 * PI;
        xEnd = LINELENGTH * cos(-angle[i]) + WIDTH / 2;
        yEnd = LINELENGTH * sin(angle[i]) + HEIGHT / 2;
        setlinecolor(RGB(rand()%256, rand()%256, rand()%256));
        line(WIDTH / 2, HEIGHT / 2, xEnd, yEnd);
    }
}

在这里插入图片描述

相关文章
|
27天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
3天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
372 16
|
19天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
6天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
21天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
23天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2594 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
5天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
182 2
|
3天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
105 65
|
7天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
332 2
|
23天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1580 17
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码