用分治策略,当k>0时,将2^k*2^k棋盘分割成4个2^(k-1)*2^(k-1)子棋盘,如下图。
只要递归的使用这种分割,就可以将问题缩小到2*2的四缺三小问题啦。
我的编译环境是VS2019,用到了EasyX图形库,几百KB大小,可以去官网下一个,个人感觉挺好用。
输入:
4(k的值),50(每个方格的边长(像素单位))
输出:
自己运行时由于加了Sleep()函数,所以会是一个动态的过程。数字代表递归的次数。颜色为RGB随机数,不想太多颜色可以把注释随机颜色的那行删掉,把case中的setfillcolor()函数取消注释,这样会是四象限四色。
代码如下:
#include <graphics.h> // 引用图形库头文件
#include <conio.h>
#include<iostream>
#include<cmath>
#include<time.h>
using namespace std;
int length, side;
RECT r;
int ksta;
void chess(int x1, int y1, int x2, int y2, int xp, int yp, int k)
{
if (k == 0)
{
return;
}
Sleep(1000); //看到递归过程,数字越大图形变换越慢
wchar_t time[2] = L"";
swprintf_s(time, L"%d", ksta-k);
setfillcolor(RGB(rand() % 255, rand() % 255, rand() % 255));//随机颜色
int area;
int xmid = (x1 + x2) / 2, ymid = (y1 + y2) / 2;
if (xp < xmid)
{
if (yp < ymid)
{
area = 1;
}
else
{
area = 3;
}
}
else if (yp < ymid)
{
area = 2;
}
else
{
area = 4;
}
switch (area)
{
case 1: //第一象限
//setfillcolor(WHITE);
fillrectangle(xmid, ymid - side, xmid + side, ymid);//第二象限
r = { xmid, ymid - side, xmid + side, ymid };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid - side, ymid, xmid, ymid + side);//第三象限
r = { xmid - side, ymid, xmid, ymid + side };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid, ymid, xmid + side, ymid + side);//第四象限
r = { xmid, ymid, xmid + side, ymid + side };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
chess(x1, y1, xmid, ymid, xp, yp, k - 1); //第一象限
chess(xmid, y1, x2, ymid, xmid, ymid - side, k - 1); //第二象限
chess(x1, ymid, xmid, y2, xmid - side, ymid, k - 1); //第三象限
chess(xmid, ymid, x2, y2, xmid, ymid, k - 1); //第四象限
break;
case 2: //第二象限
//setfillcolor(BLUE);
fillrectangle(xmid - side, ymid - side, xmid, ymid);//第一象限
r = { xmid - side, ymid - side, xmid, ymid };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid - side, ymid, xmid, ymid + side);//第三象限
r = { xmid - side, ymid, xmid, ymid + side };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid, ymid, xmid + side, ymid + side);//第四象限
r = { xmid, ymid, xmid + side, ymid + side };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
chess(x1, y1, xmid, ymid, xmid-side, ymid-side, k - 1); //第一象限
chess(xmid, y1, x2, ymid, xp, yp, k - 1); //第二象限
chess(x1, ymid, xmid, y2, xmid - side, ymid, k - 1); //第三象限
chess(xmid, ymid, x2, y2, xmid, ymid, k - 1); //第四象限
break;
case 3: //第三象限
//setfillcolor(GREEN);
fillrectangle(xmid - side, ymid - side, xmid, ymid);//第一象限
r = { xmid - side, ymid - side, xmid, ymid };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid, ymid - side, xmid + side, ymid);//第二象限
r = { xmid, ymid - side, xmid + side, ymid };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid, ymid, xmid + side, ymid + side);//第四象限
r = { xmid, ymid, xmid + side, ymid + side };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
chess(x1, y1, xmid, ymid, xmid - side, ymid - side, k - 1); //第一象限
chess(xmid, y1, x2, ymid, xmid, ymid - side, k - 1); //第二象限
chess(x1, ymid, xmid, y2, xp, yp, k - 1); //第三象限
chess(xmid, ymid, x2, y2, xmid, ymid, k - 1); //第四象限
break;
case 4: //第四象限
//setfillcolor(YELLOW);
fillrectangle(xmid - side, ymid - side, xmid, ymid);//第一象限
r = { xmid - side, ymid - side, xmid, ymid };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid, ymid - side, xmid + side, ymid);//第二象限
r = { xmid, ymid - side, xmid + side, ymid };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
fillrectangle(xmid - side, ymid, xmid, ymid + side);//第三象限
r = { xmid - side, ymid, xmid, ymid + side };
drawtext(time, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
chess(x1, y1, xmid, ymid, xmid - side, ymid - side, k - 1); //第一象限
chess(xmid, y1, x2, ymid, xmid, ymid - side, k - 1); //第二象限
chess(x1, ymid, xmid, y2, xmid - side, ymid, k - 1); //第三象限
chess(xmid, ymid, x2, y2, xp, yp, k - 1); //第四象限
break;
default:
break;
}
}
int main()
{
int k;
cout << "输入k的值,以及方格的边长" << endl;
cin >> k >> side;
if(k <= 0 || side <= 0)
{
cout << "输入不合法!" << endl;
return 0;
}
ksta = k+1;
initgraph(1000, 1000);
length = pow(2, k);
setfillcolor(WHITE);
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
rectangle(side * j, side * i, side * (j + 1), side * (i + 1));
}
}
srand((unsigned)time(NULL));
int x = rand() % length * side;
int y = rand() % length * side;
setfillcolor(WHITE);
fillrectangle(x, y, x + side, y + side);
settextstyle(side / 2, 0, _T("宋体"));
setbkmode(TRANSPARENT);
r = { x, y,x+side ,y+side };
drawtext(_T("0"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
int area;
if (x < length * side / 2)
{
if (y < length * side / 2)
{
area = 1;
}
else
{
area = 3;
}
}
else if (y < length * side / 2)
{
area = 2;
}
else
{
area = 4;
}
chess(0, 0, length * side, length * side, x, y, k);
_getch(); // 按任意键继续
closegraph(); // 关闭绘图窗口
return 0;
}