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

参考

  1. 《C和C++游戏趣味编程》
见缝插圆 随机生成的圆互不相交且尽量填满画布,按空格键可以切换不同的绘制模式
每次增加一个随机圆 设定圆的个数circleNum=100,定义3个数组用于存储所有圆的圆心坐标、半径,然后每隔100毫秒,添加一个随机圆并绘制
#include #include #include #include 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; }

C++|C++入门——实现见缝插圆游戏
文章图片

新圆不和已有圆相交
每次随机生成一个新圆后,首先与所有已经生成的圆比较,如果和任何一个圆相交,则重新生成一个新圆;如果新圆和所有已生成的圆都不相交,则循环结束,将此圆添加到数组中
设置标志变量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; } }

C++|C++入门——实现见缝插圆游戏
文章图片

新圆半径最大化
如果生成的圆和之前已生成的圆都不相交,则不断增大新圆的半径,直到找到第一个与该圆相切的圆,或达到rmax为止
#include #include #include #include #include // 求解两个点之间的距离 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 #include #include #include #include // 求解两个点之间的距离 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; }

C++|C++入门——实现见缝插圆游戏
文章图片

【C++|C++入门——实现见缝插圆游戏】C++|C++入门——实现见缝插圆游戏
文章图片

    推荐阅读