C++入门——实现见缝插针游戏

参考

  1. 《C和C++游戏趣味编程》 童晶

见缝插针

“见缝插针”游戏:按下空格键后发射一根针到圆盘上,所有针逆时针方向转动;如果新发射的针碰到已有的针,游戏结束

在这里插入图片描述

绘制圆盘与针

绘制一个圆表示圆盘、一条线段表示一根针,圆心坐标及线段起点坐标均为(width/2, height/2)

#include <graphics.h>
#include <conio.h>
#include <stdio.h>

int main()
{
	int width = 800;
	int height = 600;
	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();
	return 0;
}

在这里插入图片描述

针的旋转

针的起点坐标为画面中心(width/2, height/2),假设针的长度为lineLength,针的旋转角度为angle,则由三角函数可以求出针的末端坐标(xEnd, yEnd)。然后,让针的角度逐渐增加,就实现了针的旋转效果

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));

	float lineLength = 160;
	float xEnd, yEnd;
	float angle = 0;
	float rotateSpeed = PI / 360;

	setlinestyle(PS_SOLID, 3);								 // 线宽为3
	while (1)
	{
		cleardevice();
		angle += rotateSpeed;
		if (angle > 2 * PI)                                  // 防止角度数据无限增加
		{
			angle -= 2 * PI;
		}
		xEnd = lineLength * cos(-angle) + width / 2;         // 计算针的末端坐标
		yEnd = lineLength * sin(-angle) + height / 2;
		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);
	}
	closegraph();
	return 0;
}

批量绘制多根针

用数组记录每根针的角度值。另外,当绘制的元素较多时,会出现明显的画面闪烁,这时可以使用批量绘图函数。BeginBatchDraw()用于开始批量绘图,执行后任何绘图操作都将暂时不输出到屏幕上,直到FlushBatchDraw()或EndBatchDraw()才将之前的绘图输出

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	setlinestyle(PS_SOLID, 3);								     // 线宽为3

	float lineLength = 160;
	float xEnd, yEnd;
	float rotateSpeed = PI / 360;
	int lineNum = 20;
	float Angles[20];
	int i;
	for (i = 0; i < lineNum; i++)
	{
		Angles[i] = i * 2 * PI / lineNum;
	}

	BeginBatchDraw();                                           
	while (1)
	{
		cleardevice();
		setlinecolor(RGB(0, 0, 0));
		for (i = 0; i < lineNum; i++)
		{
			Angles[i] += rotateSpeed;
			if (Angles[i] > 2 * PI)                              // 防止角度数据无限增加
			{
				Angles[i] -= 2 * PI;
			}
			xEnd = lineLength * cos(-Angles[i]) + width / 2;     // 计算针的末端坐标
			yEnd = lineLength * sin(-Angles[i]) + height / 2;
			line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
			
		}

		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                     // 设置圆盘线条颜色为红色
		circle(width / 2, height / 2, 60);
		FlushBatchDraw();
		Sleep(10);
	}
	closegraph();
	return 0;
}

针的发射与新增

首先在画面左边绘制一根针,表示待发射的位置;当用户按下空格键,针的个数加1,并且新增加的针初始角度为PI。用户不断按下空格键,即可持续生成新的针

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	setlinestyle(PS_SOLID, 3);								     // 线宽为3

	float lineLength = 160;
	float xEnd, yEnd;
	float rotateSpeed = PI / 360;
	int lineNum = 0;
	float Angles[1000];
	int i;

	BeginBatchDraw();                                           
	while (1)
	{
		cleardevice();
		setlinecolor(RGB(0, 0, 0));
		line(0, height / 2, lineLength, height / 2);             // 左边发射区域的一根针

		for (i = 0; i < lineNum; i++)
		{
			Angles[i] += rotateSpeed;
			if (Angles[i] > 2 * PI)                              // 防止角度数据无限增加
			{
				Angles[i] -= 2 * PI;
			}
			xEnd = lineLength * cos(-Angles[i]) + width / 2;     // 计算针的末端坐标
			yEnd = lineLength * sin(-Angles[i]) + height / 2;
			line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
		}

		if (_kbhit())
		{
			char input = _getch();
			if (input == ' ')                                    // 如果为空格键
			{
				lineNum++;
				Angles[lineNum - 1] = PI;
				xEnd = lineLength * cos(-Angles[lineNum - 1]) + width / 2;
				yEnd = lineLength * sin(-Angles[lineNum - 1]) + height / 2;
				line(width / 2, height / 2, xEnd, yEnd);
			}
		}
		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                     // 设置圆盘线条颜色为红色
		circle(width / 2, height / 2, 60);
		FlushBatchDraw();
		Sleep(10);
	}
	closegraph();
	return 0;
}

游戏失败判断

当两根针的旋转角度差的绝对值小于PI/60时,判断发生了碰撞

for (i = 0; i < lineNum - 1; i++)                // 拿新的针和之前所有针比较
{
	if (fabs(Angles[lineNum - 1] - Angles[i]) < PI / 60)
	{
		rotateSpeed = 0;                         // 如果碰撞,停止旋转
		break;
	}
}

得分与显示效果改进

当用户按空格键并且游戏没有失败,则得分增加1:

score += 1;

最后将score转换为字符串输出:

TCHAR s[20]; // 定义字符串数组
_stprintf(s, _T("%d"), score);
settextstyle(50, 0, _T("Times"));
settextcolor(RGB(50, 50, 50));
outtextxy(65, 200, s);

填充绘制圆盘,随着针数的增加,圆盘填充颜色越来鲜艳:

setfillcolor(HSVtoRGB(0, lineNum / 60.0, 0.8));
setlinecolor(HSVtoRGB(0, 0.9, 0.8));
fillcircle(width / 2, height / 2);

将正在旋转的针的颜色设为蓝色,最新发射的针的颜色设为红色:

setlinecolor(RGB(0, 0, 255));
if (i == lineNum - 1)
{
	setlinecolor(RGB(255, 0, 0));
}

完整代码

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>

int main()
{
	float PI = 3.1415926;
	int width = 800;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	setlinestyle(PS_SOLID, 3);								     // 线宽为3

	float lineLength = 160;
	float xEnd, yEnd;
	float rotateSpeed = PI / 360;
	int lineNum = 0;
	float Angles[1000];
	int score = 0;
	int i;

	BeginBatchDraw();                                           
	while (1)
	{
		cleardevice();
		setlinecolor(RGB(0, 0, 0));
		line(0, height / 2, lineLength, height / 2);             // 左边发射区域的一根针

		for (i = 0; i < lineNum; i++)
		{
			Angles[i] += rotateSpeed;
			if (Angles[i] > 2 * PI)                              // 防止角度数据无限增加
			{
				Angles[i] -= 2 * PI;
			}
			xEnd = lineLength * cos(-Angles[i]) + width / 2;     // 计算针的末端坐标
			yEnd = lineLength * sin(-Angles[i]) + height / 2;
			setlinecolor(RGB(0, 0, 255));                        // 设定旋转针的颜色为蓝色
			if (i == lineNum - 1)
			{
				setlinecolor(RGB(255, 0, 0));                    // 新增的针为红色
			}
			line(width / 2, height / 2, xEnd, yEnd);             // 绘制一根针
		}

		if (_kbhit() && rotateSpeed != 0)
		{
			char input = _getch();
			if (input == ' ')                                    // 如果为空格键
			{
				lineNum++;
				Angles[lineNum - 1] = PI;
				xEnd = lineLength * cos(-Angles[lineNum - 1]) + width / 2;
				yEnd = lineLength * sin(-Angles[lineNum - 1]) + height / 2;
				line(width / 2, height / 2, xEnd, yEnd);
				for (i = 0; i < lineNum - 1; i++)                // 拿新的针和之前所有针比较
				{
					if (fabs(Angles[lineNum - 1] - Angles[i]) < PI / 60)
					{
						rotateSpeed = 0;                         // 如果碰撞,停止旋转
						break;
					}
				}
				score += 1;
			}
		}
		setfillcolor(HSVtoRGB(0, lineNum / 60.0, 0.8));          // 针越多,圆盘颜色越鲜艳
		setlinecolor(HSVtoRGB(0, 0.9, 0.8));                     // 圆盘线条颜色为红色
		fillcircle(width / 2, height / 2, 60);                   // 绘制中间的圆盘
		TCHAR s[20];                                             // 定义字符串数组
		swprintf_s(s, _T("%d"), score);
		settextstyle(50, 0, _T("Times"));                        // 设置文字大小、字体
		settextcolor(RGB(50, 50, 50));
		outtextxy(65, 200, s);

		FlushBatchDraw();
		Sleep(10);
	}
	closegraph();
	return 0;
}
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++中,priority_queue是一个容器适配器,用于实现优先级队列。默认情况下,priority_queue是一个大顶堆,也就是说,优先级最高的元素会被放在队列的前面。但是,我们也可以通过自定义排序规则来创建小顶堆。 在C++中,可以通过指定第三个模板参数Compare来自定义排序规则。比如,可以使用std::greater<T>来创建小顶堆,其中T是存储在priority_queue中的元素类型。例如,可以这样定义一个小顶堆的priority_queue: ```cpp std::priority_queue<int, std::vector<int>, std::greater<int>> pq; ``` 这样定义的priority_queue会根据元素的值从小到大进行排序,优先级最高的元素会被放在队列的前面。 另外,priority_queue还提供了一些成员函数来操作队列,比如empty()、size()、top()、push()、pop()等。你可以使用这些成员函数来判断队列是否为空、获取队列的大小、访问队列的第一个元素、向队列中插入元素以及移除队列中的元素。 总结起来,如果你想创建一个小顶堆的priority_queue,可以通过指定std::greater<T>作为第三个模板参数来实现。然后,你可以使用priority_queue提供的成员函数来操作队列。 #### 引用[.reference_title] - *1* [C++ STL——Queue容器、priority_queue](https://blog.csdn.net/LiuXF93/article/details/121119026)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [c++priority_queue详解](https://blog.csdn.net/qq_43679351/article/details/124825229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值