//正规的算法题需有输入输出范例,我用Canvas绘制输出直观一些
//看看有什么问题。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
cColCount = 44;
cRowCount = 36;
cPointWidth = 16;
cPointHeight = 16;
var
vRects: array[0..cColCount-1, 0..cRowCount-1] of Boolean; // 随机巨型
vChecks: array[0..cColCount-1, 0..cRowCount-1] of Boolean; // 是否扫描过
vBlockCount: Integer; // 分割的块数
vBlockList: array of TRect; // 每个块的矩形坐标
procedure Init;
begin
//Randomize;//先每次一样
FillChar(vChecks, SizeOf(vChecks), 0);
FillChar(vRects, SizeOf(vRects), 0);
vBlockCount := 0;
end;
procedure Input;
var
I, J: Integer;
begin
for I := Low(vRects) to High(vRects) do
for J := Low(vRects) to High(vRects) do
if Random(2) = 0 then vRects[I, J] := True;
end;
procedure Calc;
var
I, J: Integer;
X, Y: Integer;
L: Integer;
function FullLine( // 连接下一行
mRowIndex: Integer; // 行号
mColStrat: Integer; // X起点
mLength: Integer; // 长度
mTest: Boolean // 是否只是测试
): Boolean; // 返回是否可以连接
var
I: Integer;
begin
Result := False;
if mRowIndex > High(vRects[mColStrat]) then Exit;
if mTest then
begin
for I := mColStrat to mColStrat + mLength - 1 do
if not vRects[I, mRowIndex] or vChecks[I, mRowIndex] then Exit;
Result := True;
end
else
begin
for I := mColStrat to mColStrat + mLength - 1 do
vChecks[I, mRowIndex] := True;
vBlockList[vBlockCount - 1].BottomRight := Point(
Succ(mColStrat + mLength - 1) * cPointWidth,
Succ(mRowIndex) * cPointHeight);
end;
end;
begin
for I := Low(vRects) to High(vRects) do
for J := Low(vRects) to High(vRects) do
if vRects[I, J] and not vChecks[I, J] then // 是一个白块,并没有被扫描过
begin
Inc(vBlockCount);
SetLength(vBlockList, vBlockCount);
vBlockList[vBlockCount - 1] :=
Rect(I * 16, J * 16, Succ(I) * cPointWidth, Succ(J) * cPointHeight);
// 向右扫描
X := I;
L := 0;
while X <= High(vRects) do
if vRects[X, J] and not vChecks[X, J] then
begin
vBlockList[vBlockCount - 1].Right := Succ(X) * cPointWidth;
vChecks[X, J] := True; // 标记已经扫描过了
Inc(L);
Inc(X);
end else Break;
if L < 1 then Continue;
// 向下扫描
Y := J + 1;
while FullLine(Y, I, L, True) do
begin
FullLine(Y, I, L, False);
Inc(Y);
end;
end;
end;
procedure Output;
begin
ShowMessage(IntToStr(vBlockCount)); // 输出
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Init;
Input;
Calc;
Output;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
I, J: Integer;
begin
Canvas.Brush.Color := clBlack;
Canvas.FillRect(Canvas.ClipRect);
Canvas.Brush.Color := clWhite;
for I := Low(vRects) to High(vRects) do
for J := Low(vRects) to High(vRects) do
begin
if vRects[I, J] then
Canvas.FillRect(
Rect(I * cPointWidth, J * cPointHeight,
Succ(I) * cPointWidth, Succ(J) * cPointHeight)
);
end;
Canvas.Brush.Style := bsClear;
Canvas.Pen.Color := clRed;
for I := 0 to vBlockCount - 1 do
Canvas.Rectangle(vBlockList);
end;
end.