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

参考

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

见缝插圆

随机生成的圆互不相交且尽量填满画布,按空格键可以切换不同的绘制模式

每次增加一个随机圆

设定圆的个数circleNum=100,定义3个数组用于存储所有圆的圆心坐标、半径,然后每隔100毫秒,添加一个随机圆并绘制

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

int main()
{
	int width = 600;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	cleardevice();
	srand(time(0));

	int xArray[100];
	int yArray[100];
	int rArray[100];
	int rmin = 8;
	int rmax = 50;
	int circleNum = 0;
	float x, y, r;

	while (circleNum < 100)
	{
		x = rand() % width;
		y = rand() % height;
		r = rand() % (rmax - rmin + 1) + rmin;

		xArray[circleNum] = x;
		yArray[circleNum] = y;
		rArray[circleNum] = r;
		circleNum++;

		setlinecolor(RGB(0, 0, 0));
		setfillcolor(RGB(255, 255, 0));
		fillcircle(x, y, r);

		Sleep(100);
	}


	_getch();
	closegraph();
	return 0;
}

在这里插入图片描述

新圆不和已有圆相交

每次随机生成一个新圆后,首先与所有已经生成的圆比较,如果和任何一个圆相交,则重新生成一个新圆;如果新圆和所有已生成的圆都不相交,则循环结束,将此圆添加到数组中

设置标志变量isNewCircleOK=0,当新圆满足不和已有圆相交时,isNewCircle==1

isNewCircleOK = 0;

while (isNewCircleOK == 0)
{
	x = rand() % width;
	y = rand() % height;
	r = rand() % (rmax - rmin + 1) + rmin;

	for (i = 0; i < circleNum; i++)
	{
		float dist2 = (xArray[i] - x) * (xArray[i] - x) + (yArray[i] - y) * (yArray[i] - y);
		float r2 = (rArray[i] + r) * (rArray[i] + r);
		if (dist2 < r2)
		{
			break;
		}
	}
	if (i == circleNum)
	{
		isNewCircleOK = 1;
	}
}

在这里插入图片描述

新圆半径最大化

如果生成的圆和之前已生成的圆都不相交,则不断增大新圆的半径,直到找到第一个与该圆相切的圆,或达到rmax为止

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

// 求解两个点之间的距离
float Dist2Points(float x1, float y1, float x2, float y2)
{
	float result;
	result = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
	return result;
}

// 判断两个圆是否相交
int isTwoCirclesIntersect(float x1, float y1, float r1, float x2, float y2, float r2)
{
	if (Dist2Points(x1, y1, x2, y2) < r1 + r2)
	{
		return 1;
	}
	return 0;
}

int main()
{
	int width = 600;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	cleardevice();
	srand(time(0));

	int xArray[1000];
	int yArray[1000];
	int rArray[1000];
	int rmin = 8;
	int rmax = 50;
	int circleNum = 0;
	float x, y, r;
	int isNewCircleOK;
	int i, j;

	while (circleNum < 1000)
	{
		isNewCircleOK = 0;

		while (isNewCircleOK == 0)
		{
			x = rand() % width;
			y = rand() % height;
			r = rmin;

			for (i = 0; i < circleNum; i++)
			{
				if (isTwoCirclesIntersect(xArray[i], yArray[i], rArray[i], x, y, r))
				{
					break;
				}
			}
			if (i == circleNum)
			{
				isNewCircleOK = 1;          // 新生成的圆和已有圆都不相交
			}
		}
		
		isNewCircleOK = 0;                  // 继续设为不OK,下面让这个新圆的半径最大
		while (isNewCircleOK == 0 && r < rmax)
		{
			r++;
			for (j = 0; j < circleNum; j++)
			{
				if (isTwoCirclesIntersect(xArray[j], yArray[j], rArray[j], x, y, r))
				{
					isNewCircleOK = 1;
					break;
				}
			}
		}
		xArray[circleNum] = x;
		yArray[circleNum] = y;
		rArray[circleNum] = r;
		circleNum++;

		setlinecolor(RGB(0, 0, 0));
		setfillcolor(RGB(255, 255, 0));
		fillcircle(x, y, r);

		Sleep(10);
	}


	_getch();
	closegraph();
	return 0;
}

封装多种绘制效果

// 填充黄色圆绘制
void DrawCircles1(float x, float y, float r)
{
	setlinecolor(RGB(0, 0, 0));
	setfillcolor(RGB(255, 255, 0));
	fillcircle(x, y, r);
}

// 填充随机颜色圆绘制
void DrawCircles2(float x, float y, float r)
{
	float h = rand() % 360;
	COLORREF color = HSVtoRGB(h, 0.6, 0.8);
	setlinecolor(RGB(255, 255, 255));
	setfillcolor(color);
	fillcircle(x, y, r);
}

// 填充随机颜色同心圆绘制
void DrawCircles3(float x, float y, float r)
{
	while (r > 0)
	{
		float h = rand() % 360;
		COLORREF color = HSVtoRGB(h, 0.6, 0.8);
		setlinecolor(RGB(255, 255, 255));
		setfillcolor(color);
		fillcircle(x, y, r);
		r -= 5;
	}
}

// 随机颜色同心圆线条绘制
void DrawCircles4(float x, float y, float r)
{
	while (r > 0)
	{
		float h = rand() % 360;
		COLORREF color = HSVtoRGB(h, 0.9, 0.8);
		setlinecolor(color);
		circle(x, y, r);
		r -= 5;
	}
}

按键互动

当按下空格键后,将circleNum设为0,相当于清除所有已有的圆;将drawMode加1,从而切换为下一种绘图模式

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

// 求解两个点之间的距离
float Dist2Points(float x1, float y1, float x2, float y2)
{
	float result;
	result = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
	return result;
}

// 判断两个圆是否相交
int isTwoCirclesIntersect(float x1, float y1, float r1, float x2, float y2, float r2)
{
	if (Dist2Points(x1, y1, x2, y2) < r1 + r2)
	{
		return 1;
	}
	return 0;
}

// 填充黄色圆绘制
void DrawCircles1(float x, float y, float r)
{
	setlinecolor(RGB(0, 0, 0));
	setfillcolor(RGB(255, 255, 0));
	fillcircle(x, y, r);
}

// 填充随机颜色圆绘制
void DrawCircles2(float x, float y, float r)
{
	float h = rand() % 360;
	COLORREF color = HSVtoRGB(h, 0.6, 0.8);
	setlinecolor(RGB(255, 255, 255));
	setfillcolor(color);
	fillcircle(x, y, r);
}

// 填充随机颜色同心圆绘制
void DrawCircles3(float x, float y, float r)
{
	while (r > 0)
	{
		float h = rand() % 360;
		COLORREF color = HSVtoRGB(h, 0.6, 0.8);
		setlinecolor(RGB(255, 255, 255));
		setfillcolor(color);
		fillcircle(x, y, r);
		r -= 5;
	}
}

// 随机颜色同心圆线条绘制
void DrawCircles4(float x, float y, float r)
{
	while (r > 0)
	{
		float h = rand() % 360;
		COLORREF color = HSVtoRGB(h, 0.9, 0.8);
		setlinecolor(color);
		circle(x, y, r);
		r -= 5;
	}
}

int main()
{
	int width = 600;
	int height = 600;
	initgraph(width, height);
	setbkcolor(RGB(255, 255, 255));
	cleardevice();
	srand(time(0));

	int xArray[1000];
	int yArray[1000];
	int rArray[1000];
	int rmin = 8;
	int rmax = 50;
	int circleNum = 0;
	float x, y, r;
	int isNewCircleOK;
	int i, j;
	int drawMode = 3;

	while (circleNum < 1000)
	{
		isNewCircleOK = 0;

		while (isNewCircleOK == 0)
		{
			if (_kbhit())
			{
				char input = _getch();
				if (input == ' ')
				{
					circleNum = 0;

					cleardevice();
					drawMode += 1;
					if (drawMode > 4)
					{
						drawMode = 1;
					}
				}
			}
			x = rand() % width;
			y = rand() % height;
			r = rmin;

			for (i = 0; i < circleNum; i++)
			{
				if (isTwoCirclesIntersect(xArray[i], yArray[i], rArray[i], x, y, r))
				{
					break;
				}
			}
			if (i == circleNum)
			{
				isNewCircleOK = 1;          // 新生成的圆和已有圆都不相交
			}
		}
		
		isNewCircleOK = 0;                  // 继续设为不OK,下面让这个新圆的半径最大
		while (isNewCircleOK == 0 && r < rmax)
		{
			r++;
			for (j = 0; j < circleNum; j++)
			{
				if (isTwoCirclesIntersect(xArray[j], yArray[j], rArray[j], x, y, r))
				{
					isNewCircleOK = 1;
					break;
				}
			}
		}
		xArray[circleNum] = x;
		yArray[circleNum] = y;
		rArray[circleNum] = r;
		circleNum++;

		if (drawMode == 1)
		{
			DrawCircles1(x, y, r);
		}
		if (drawMode == 2)
		{
			DrawCircles2(x, y, r);
		}
		if (drawMode == 3)
		{
			DrawCircles3(x, y, r);
		}
		if (drawMode == 4)
		{
			DrawCircles4(x, y, r);
		}

		Sleep(10);
	}


	_getch();
	closegraph();
	return 0;
}

在这里插入图片描述

在这里插入图片描述

  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值