当前位置:   article > 正文

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

见缝插针 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在这里插入图片描述

针的旋转

针的起点坐标为画面中心(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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

批量绘制多根针

用数组记录每根针的角度值。另外,当绘制的元素较多时,会出现明显的画面闪烁,这时可以使用批量绘图函数。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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

针的发射与新增

首先在画面左边绘制一根针,表示待发射的位置;当用户按下空格键,针的个数加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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

游戏失败判断

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

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

得分与显示效果改进

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

score += 1;
  • 1

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

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

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

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

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

setlinecolor(RGB(0, 0, 255));
if (i == lineNum - 1)
{
	setlinecolor(RGB(255, 0, 0));
}
  • 1
  • 2
  • 3
  • 4
  • 5

完整代码

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/47889
推荐阅读
相关标签
  

闽ICP备14008679号