画200个圆(圆的半径<50且不相交的情况下达到最大)

#include <iostream>
#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    int width, height;
    width = 800; height = 600;
    initgraph(width, height);
    setbkcolor(WHITE);
    cleardevice();
    int xArray[200], yArray[200], rArray[200], circleNum, rmin, rmax;
    circleNum = 1; rmin = 8; rmax = 60;
    float dist2; int isOk = 1; float r2; int issmall;
    int x, y, r;
    x = rand() % width;
    y = rand() % height;
    r = rand() % (rmax - rmin + 1) + rmin;//随机生成一个圆的数值,这个r的范围是8-50
    xArray[0] = x;//
    yArray[0] = y;
    rArray[0] = r;
    setlinecolor(BLACK);
    circle(xArray[circleNum], yArray[circleNum], rArray[circleNum]);
    setfillcolor(YELLOW);
    fillcircle(xArray[circleNum], yArray[circleNum], rArray[circleNum]);//先随便设置一个圆放入数组中并画出来

    while (circleNum < 200)//循环直至数组中放满200个圆
    {
        int x, y, r;
        x = rand() % width;//是x不是xArray[i],先是尝试生成三个数值,满足不相交条件里再放进数组里
        y = rand() % height;
        r = rand() % (rmax - rmin + 1) + rmin;//随机生成一个圆的数值
        for (int i = 0; i < circleNum; i++)//判断数组中的圆与新增的圆是否相交
        {
            dist2 = pow(xArray[i] - x, 2) + pow(yArray[i] - y, 2);
            r2 = pow(rArray[i] + r, 2);
            if (dist2 < r2)
            {
                isOk = 0;//默认isOk=1;若相交的话就变为0;
                break;//数组中有圆与尝试圆相交的话就直接跳出for循环,进入下面的if语句
            }

        }
        if (isOk == 1)/*上面for循环完了也没有出发isOk=0,就说明没有圆相交,不相交就再判断是否达到最大半径,
        但是注意是isOk==1,不是isOk=1,否则判断无效*/
            issmall = 1;//不相交和相切就说明没有达到最大半径
        while (issmall == 1&&r<60)//要让画的圆的半径在不大于50且不与其他圆相交的基础上尽量大,issmall==1就说明圆还没有达到最大半径
        {
            r += 1;//半径逐渐增大直到相切
            for (int i = 0; i < circleNum; i++)//判断数组中的圆与半径+1的圆是否相交
            {
                dist2 = pow(xArray[i] - x, 2) + pow(yArray[i] - y, 2);
                r2 = pow(rArray[i] + r, 2);
                if (dist2 < r2)//相交则说明半径太大了,这时,半径-1就不会相交了
                {
                    issmall = 0;
                    r = r - 1;
                    break;
                }
                if (dist2 == r2)//相切则说明正好合适,半径不需要再-1
                {
                    issmall = 0;
                    break;//break只能跳出for循环,要再终结while循环就要控制issmall
                }

            }
        }

        if (isOk == 1&&issmall==0)//不相交且达到最大半径就可以把数值放入数组中并且画圆了
        {
            xArray[circleNum] = x;//是xArray[circleNum]而不是xArray[i],合格的数值是要放进数组中最新的空位里
            yArray[circleNum] = y;
            rArray[circleNum] = r;
            setlinecolor(BLACK);
            circle(xArray[circleNum], yArray[circleNum], rArray[circleNum]);
            setfillcolor(YELLOW);
            fillcircle(xArray[circleNum], yArray[circleNum], rArray[circleNum]);
            circleNum++;
            Sleep(30);//画一个圆就停一下,要不然会直接画完
        }
        else//相交的话就continue进入继续while循环
        {
            isOk = 1;
        }
    }
    _getch();
    closegraph();

    return 0;
}
/*
启示:
1.本来想通过数学计算直接算得圆的最大半径,但是用程序表达会比较复杂,所以直接用“笨方法”让圆不断+1来增大,
  对于人来说是笨方法但是对于计算机来说未必
2.if(isOk==1)if(isOk=1)是完全不一样的
3.有时候程序运行了没有达到预期中的效果,可能是语法出错如2,可能是设计思路不对,但也有可能是数值不对,比如
  如果一开始没有随便画个圆放入数组中后让circleNum为1的话,就无法进入for循环,因为不满足i<circleNum,这类错
  误可以通过设置断点逐语句来运行发现
4.很多时候要使用到嵌套循环,比如while里嵌for,break只能终止一层循环,而通过对数值比如isOk/issmall等的控制就可以控制外层循环
5.有些反复使用的代码可以用函数封装,增加代码的可读性,比如为判断两个圆是否相交而设个函数

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值