分享
 
 
 

经典面试问题:12小球问题算法(源码)

王朝other·作者佚名  2007-09-14
窄屏简体版  字體: |||超大  

(文档请参考:http://blog.csdn.net/CXXSoft/archive/2006/09/28/1299731.aspx)

3、 运行效果

4、 算法源码

...{

作品名称: 小球问题通用解决方案

开发作者: 成晓旭

开发时间: 2003年01月22日

完成时间: 2003年01月23日

修改时间1: 2003年11月14日

增加用户问题条件设置绘制方法

修改时间2: 2003年11月18日

增加比较过程的记录功能

}

unit Common;

interface

uses

Windows,SysUtils,Classes,Graphics,BallType;

//清除画面方法

procedure ClearCanvas(aCanvas: TCanvas; aRect: TRect);

//小球问题条件设置方法

procedure Draw_Ball_Config(

AllBall:array of TC_Ball;

ACanvas:TCanvas;

aClearRect: TRect;

bShowTrace:Boolean);

//小球问题解决方法

procedure Serach_Error_Ball(

AllBall:array of TC_Ball;

ACanvas:TCanvas;

aClearRect: TRect;

bShowTrace:Boolean);

var

strLog1:AnsiString;

strLog2:AnsiString;

strLog3:AnsiString;

implementation

//单元内部常量定义

const

Fir_Pivot_X = 200;

Fir_Pivot_Y = 80;

Hint_X = 10;

One_DrawDelta = 140;

One_PreDelta = 70;

One_FroDelta = 30;

strADyB = '比较:A端(重) > B端(轻)' + CHR(13) + CHR(10);

strAXDB = '比较:A端 = B端' + CHR(13) + CHR(10);

strAXyB = '比较:A端(轻) < B端(重)' + CHR(13) + CHR(10);

A_Team = 'A 组:';

B_Team = 'B 组:';

preTail0 = '号球' + CHR(13) + CHR(10);

preTail1 = '号球';

proHead = '结论:异常球在 [';

lastResult = '结论:异常球是';

nextHint = CHR(13) + CHR(10) + '启示:';

ErrorHint = '命题不严密,请检查设置条件!';

function SearchBall_At4(AllBall:array of TC_Ball;

A,G:array of Byte;var vErr_Ball_Order:Byte;

var vIsHeavy:Boolean;ACanvas:TCanvas;bShowTrace:Boolean):Boolean;

var

A2,B2:Word;

A3,B3:Word;

Loop:Word;

bNumber:Byte;

bPartA,bPartB:array of TC_Ball;

bCmpPara:TC_CmpPara;

str:AnsiString;

begin

vErr_Ball_Order := 0;

vIsHeavy := False;

A2 := AllBall[A[1]].Weight + AllBall[A[2]].Weight + AllBall[G[1]].Weight;

B2 := AllBall[A[3]].Weight + AllBall[G[2]].Weight + AllBall[G[3]].Weight;

str := A_Team + IntToStr(AllBall[A[1]].Order) + ','

+ IntToStr(AllBall[A[2]].Order) + ','

+ IntToStr(AllBall[G[1]].Order);

str := str + preTail0;

strLog2 := strLog2 + str;

str := B_Team + IntToStr(AllBall[A[3]].Order) + ','

+ IntToStr(AllBall[G[2]].Order) + ','

+ IntToStr(AllBall[G[3]].Order);

str := str + preTail0;

strLog2 := strLog2 + str;

bNumber := 3;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[A[1]];

bPartA[1] := AllBall[A[2]];

bPartA[2] := AllBall[G[1]];

bPartB[0] := AllBall[A[3]];

bPartB[1] := AllBall[G[2]];

bPartB[2] := AllBall[G[3]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A2 = B2 then

begin

A3 := AllBall[A[4]].Weight;

B3 := AllBall[G[1]].Weight;

strLog2 := strLog2 + strAXDB;

str := proHead;

str := str + IntToStr(AllBall[A[4]].Order);

str := str + ']' + preTail1 + ' 【排3余1】';

strLog2 := strLog2 + str;

str := '用任一正常球与之比较,即可知异常球是偏轻偏重!';

strLog2 := strLog2 + nextHint + str;

with bCmpPara do

begin

Pre_LNumber := 4;

Fro_LNumber := 1;

SetLength(Pre_Latency,Pre_LNumber);

SetLength(Fro_Latency,Fro_LNumber);

for Loop := 0 to Pre_LNumber - 1 do

Pre_Latency[Loop] := AllBall[Loop + 9];

Fro_Latency[0] := AllBall[A[4]];

end;

Balance_One_Latency(Point(Hint_X,Fir_Pivot_Y + One_DrawDelta - One_PreDelta),

Point(Hint_X,Fir_Pivot_Y + One_DrawDelta + One_FroDelta),

bCmpPara,ACanvas,bShowTrace);

bNumber := 1;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[A[4]];

bPartB[0] := AllBall[G[1]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta * 2),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A3 = B3 then

begin

vErr_Ball_Order := 0;

strLog3 := '异常球与正常球一样重!' + ErrorHint;

end

else

begin

vErr_Ball_Order := A[4];

vIsHeavy := A3 > B3;

end;

end

else

begin

A3 := AllBall[A[1]].Weight;

B3 := AllBall[A[2]].Weight;

if A2 > B2 then

strLog2 := strLog2 + strADYB

else

strLog2 := strLog2 + strAXYB;

str := proHead;

str := str + IntToStr(AllBall[A[1]].Order) + ','

+ IntToStr(AllBall[A[2]].Order) + ','

+ IntToStr(AllBall[A[3]].Order);

str := str + ']' + preTail1 + ' 【排1余3】';

strLog2 := strLog2 + str;

str := '下一轮必须在本轮比较的同一端的两球中进行.即取:'

+IntToStr(AllBall[A[1]].Order) + ','

+ IntToStr(AllBall[A[2]].Order)

+'号球,在推算结果时,还必须用到此轮A、B端谁轻谁重!';

strLog2 := strLog2 + nextHint + str;

bNumber := 1;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[A[1]];

bPartB[0] := AllBall[A[2]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta * 2),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A3 = B3 then

begin

vErr_Ball_Order := A[3];

vIsHeavy := A2 < B2;

end

else

begin

if A2 > B2 then

begin

if A3 > B3 then

vErr_Ball_Order := A[1]

else

vErr_Ball_Order := A[2];

//IsHeavy := True;

end

else

begin

if A3 > B3 then

vErr_Ball_Order := A[2]

else

vErr_Ball_Order := A[1];

//IsHeavy := NOT True;

end;

vIsHeavy := A2 > B2;

end;

end;

Result := vErr_Ball_Order <> 0;

end;

function SearchBall_At8(AllBall:array of TC_Ball;IsAdyB:Boolean;

A,B,G:array of Byte;var vErr_Ball_Order:Byte;

var vIsHeavy:Boolean;ACanvas:TCanvas;bShowTrace:Boolean):Boolean;

var

A2,B2:Word;

A3,B3:Word;

bNumber:Byte;

bPartA,bPartB:array of TC_Ball;

senPivot,thrPivot:TPoint;

str:AnsiString;

begin

vErr_Ball_Order := 0;

vIsHeavy := False;

A2 := AllBall[A[1]].Weight + AllBall[A[2]].Weight + AllBall[B[1]].Weight;

B2 := AllBall[A[3]].Weight + AllBall[B[2]].Weight + AllBall[G[1]].Weight;

str := A_Team + IntToStr(AllBall[A[1]].Order) + ','

+ IntToStr(AllBall[A[2]].Order) + ','

+ IntToStr(AllBall[B[1]].Order);

str := str + preTail0;

strLog2 := strLog2 + str;

str := B_Team + IntToStr(AllBall[A[3]].Order) + ','

+ IntToStr(AllBall[B[2]].Order) + ','

+ IntToStr(AllBall[G[1]].Order);

str := str + preTail0;

strLog2 := strLog2 + str;

bNumber := 3;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[A[1]];

bPartA[1] := AllBall[A[2]];

bPartA[2] := AllBall[B[1]];

bPartB[0] := AllBall[A[3]];

bPartB[1] := AllBall[B[2]];

bPartB[2] := AllBall[G[1]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A2 = B2 then

begin

A3 := AllBall[B[3]].Weight;

B3 := AllBall[B[4]].Weight;

strLog2 := strLog2 + strAXDB;

str := proHead;

str := str + IntToStr(AllBall[A[4]].Order) + ','

+ IntToStr(AllBall[B[3]].Order) + ','

+ IntToStr(AllBall[B[4]].Order);

str := str + ']' + preTail1 + ' 【排5余3】';

strLog2 := strLog2 + str;

str := '下一轮必须在本轮比较的同一端的两球中进行.即取:'

+IntToStr(AllBall[B[3]].Order) + ','

+ IntToStr(AllBall[B[4]].Order)

+'号球,在推算结果时,还必须用到此轮A、B端谁轻谁重!';

strLog2 := strLog2 + nextHint + str;

bNumber := 1;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[B[3]];

bPartB[0] := AllBall[B[4]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta * 2),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A3 = B3 then

begin

vErr_Ball_Order := A[4];

vIsHeavy := IsAdyB;

end

else

begin

if IsAdyB then

begin

if A3 > B3 then

vErr_Ball_Order := B[4]

else

vErr_Ball_Order := B[3];

//IsHeavy := NOT IsAdyB;

end

else

begin

if A3 > B3 then

vErr_Ball_Order := B[3]

else

vErr_Ball_Order := B[4];

//IsHeavy := NOT IsAdyB;

end;

vIsHeavy := NOT IsAdyB;

end;

end

else

begin

if A2 > B2 then

strLog2 := strLog2 + strADYB

else

strLog2 := strLog2 + strAXYB;

str := proHead;

str := str + IntToStr(AllBall[A[1]].Order) + ','

+ IntToStr(AllBall[A[2]].Order) + ','

+ IntToStr(AllBall[A[3]].Order) + ','

+ IntToStr(AllBall[B[1]].Order) + ','

+ IntToStr(AllBall[B[2]].Order);

str := str + ']' + preTail1 + ' 【排3余5】';

strLog2 := strLog2 + str;

str := '此时,必须综合分析近两次的比较结果.当近两次比较的天平倾向相同时,'

+ '必须比较共同产生倾向因素的两个球;倾向相反时,'

+ '任取一个正常球与A组第3个球('

+ IntToStr(AllBall[A[2]].Order)

+ ')或B组第1个球('

+ IntToStr(AllBall[B[1]].Order)

+ ')比较.';

strLog2 := strLog2 + nextHint + str;

if ((IsAdyB = True) and (A2 > B2)) or ((IsAdyB = False) and (A2 < B2)) then

begin

A3 := AllBall[A[1]].Weight;

B3 := AllBall[A[2]].Weight;

bNumber := 1;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[A[1]];

bPartB[0] := AllBall[A[2]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta * 2),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A3 = B3 then

begin

vErr_Ball_Order := B[2];

vIsHeavy := NOT IsAdyB;

end

else if A2 > B2 then

begin

if A3 > B3 then

vErr_Ball_Order := A[1]

else

vErr_Ball_Order := A[2];

vIsHeavy := IsAdyB;

end

else if A2 < B2 then

begin

if A3 > B3 then

vErr_Ball_Order := A[2]

else

vErr_Ball_Order := A[1];

vIsHeavy := IsAdyB;

end;

end

else if ((IsAdyB = True) and (A2 < B2)) or ((IsAdyB = False) and (A2 > B2)) then

begin

A3 := AllBall[A[3]].Weight;

B3 := AllBall[G[1]].Weight;

bNumber := 1;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

bPartA[0] := AllBall[A[1]];

bPartB[0] := AllBall[G[1]];

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y + One_DrawDelta * 2),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A3 = B3 then

begin

vErr_Ball_Order := B[1];

vIsHeavy := NOT IsAdyB;

end

else if A3 > B3 then

begin

if IsAdyB then

begin

vErr_Ball_Order := A[3];

vIsHeavy := IsAdyB;

end

else

begin

vErr_Ball_Order := 0;

strLog3 := '"偏轻"的异常球 > 正常球!' + ErrorHint;

end;

end

else

begin

if IsAdyB then

begin

vErr_Ball_Order := 0;

strLog3 := '"偏重"的异常球 < 正常球!' + ErrorHint;

end

else

begin

vErr_Ball_Order := A[3];

vIsHeavy := IsAdyB;

end

end;

end;

end;

Result := vErr_Ball_Order <> 0;

end;

procedure Serach_Error_Ball(

AllBall:array of TC_Ball;

ACanvas:TCanvas;aClearRect: TRect;

bShowTrace:Boolean);

var

A,B:Word;

Loop:Word;

BufC:array[0..4] of Byte;

BufT:array[0..8] of Byte;

BufA,BufB:array[0..4] of Byte;

BufG:array[0..4] of Byte;

bOrder:Byte;

bHeavy:Boolean;

FoundBall :TC_SearchBall;

str:AnsiString;

bNumber:Byte;

bPartA,bPartB:array of TC_Ball;

bCmpPara:TC_CmpPara;

begin

A := 0;

strLog1 := '';

strLog2 := '';

strLog3 := '';

ClearCanvas(aCanvas,aClearRect);

str := A_Team;

for Loop := 1 to 4 do

begin

A := A + AllBall[Loop].Weight;

str := str + IntToStr(AllBall[Loop].Order) + ',';

//bPartA[Loop] := AllBall[Loop];

end;

str := str + preTail0;

strLog1 := strLog1 + str;

B := 0;

str := B_Team;

for Loop := 5 to 8 do

begin

B := B + AllBall[Loop].Weight;

str := str + IntToStr(AllBall[Loop].Order) + ',';

//bPartB[Loop] := AllBall[Loop];

end;

str := str + preTail0;

strLog1 := strLog1 + str;

bNumber := 4;

SetLength(bPartA,bNumber);

SetLength(bPartB,bNumber);

for Loop := 0 to bNumber - 1 do

begin

bPartA[Loop] := AllBall[Loop+1];

bPartB[Loop] := AllBall[Loop+bNumber + 1];

end;

Balance_One_Compare(Point(Fir_Pivot_X,Fir_Pivot_Y),

bNumber,bPartA,bPartB,ACanvas,bShowTrace);

if A = B then

begin

strLog1 := strLog1 + strAXDB;

str := proHead;

for Loop := 1 to 4 do

begin

BufC[Loop] := AllBall[8 + Loop].Order;

str := str + IntToStr(AllBall[8 + Loop].Order) + ',';

end;

str := str + '] ' + preTail1 + ' 【排8余4】';

strLog1 := strLog1 + str;

for Loop := 1 to 8 do

BufT[Loop] := AllBall[Loop].Order;

with bCmpPara do

begin

Pre_LNumber := 12;

Fro_LNumber := 4;

SetLength(Pre_Latency,Pre_LNumber);

SetLength(Fro_Latency,Fro_LNumber);

for Loop := 0 to Pre_LNumber - 1 do

Pre_Latency[Loop] := AllBall[Loop + 1];

for Loop := 0 to Fro_LNumber - 1 do

Fro_Latency[Loop] := AllBall[Loop + 9];

end;

Balance_One_Latency(Point(10,Fir_Pivot_Y - One_PreDelta),Point(10,Fir_Pivot_Y + One_FroDelta),

bCmpPara,ACanvas,bShowTrace);

if SearchBall_At4(AllBall,BufC,BufT,bOrder,bHeavy,ACanvas,bShowTrace) then

begin

FoundBall.Ball := AllBall[bOrder];

FoundBall.IsHeavy := bHeavy;

if FoundBall.IsHeavy then

FoundBall.ErrorMsg := '【偏重】'

else

FoundBall.ErrorMsg := '【偏轻】';

str := '【'+ IntToStr(FoundBall.Ball.Order) + '】 = '

+ IntToStr(FoundBall.Ball.Weight) + ' ' + FoundBall.ErrorMsg;

strLog3 := lastResult + str;

end;

end

else

begin

if A > B then

strLog1 := strLog1 + strADYB

else

strLog1 := strLog1 + strAXYB;

str := proHead;

for Loop := 1 to 8 do

str := str + IntToStr(AllBall[Loop].Order) + ',';

str := str + '] ' + preTail1 + '【排4余8】';

strLog1 := strLog1 + str;

for Loop := 1 to 4 do

begin

BufA[Loop] := AllBall[Loop].Order;

BufB[Loop] := AllBall[4 + Loop].Order;

BufG[Loop] := AllBall[8 + Loop].Order;

end;

with bCmpPara do

begin

Pre_LNumber := 12;

Fro_LNumber := 4;

SetLength(Pre_Latency,Pre_LNumber);

SetLength(Fro_Latency,Fro_LNumber);

for Loop := 0 to Pre_LNumber - 1 do

Pre_Latency[Loop] := AllBall[Loop + 1];

for Loop := 0 to Fro_LNumber - 1 do

Fro_Latency[Loop] := AllBall[Loop + 9];

end;

Balance_One_Latency(Point(Hint_X,Fir_Pivot_Y - One_PreDelta),Point(10,Fir_Pivot_Y + One_FroDelta),

bCmpPara,ACanvas,bShowTrace);

if SearchBall_At8(AllBall,A > B,BufA,BufB,BufG,bOrder,bHeavy,ACanvas,bShowTrace) then

begin

FoundBall.Ball := AllBall[bOrder];

FoundBall.IsHeavy := bHeavy;

if FoundBall.IsHeavy then

FoundBall.ErrorMsg := '【偏重】'

else

FoundBall.ErrorMsg := '【偏轻】';

str := '【'+ IntToStr(FoundBall.Ball.Order) + '】 = '

+ IntToStr(FoundBall.Ball.Weight) + ' ' + FoundBall.ErrorMsg;

strLog3 := lastResult + str;

end;

end;

//MessageBox(0,PChar(Str),'小球问题',MB_OK or MB_IConInformation);

end;

procedure Draw_Ball_Config(

AllBall:array of TC_Ball;

ACanvas:TCanvas;

aClearRect: TRect;

bShowTrace:Boolean);

begin

ClearCanvas(aCanvas,aClearRect);

Process_Initial_Ball(

Point(0,Fir_Pivot_Y - One_PreDelta-10),

AllBall,ACanvas,bShowTrace);

end;

procedure ClearCanvas(aCanvas: TCanvas; aRect: TRect);

begin

with aCanvas do

begin

Brush.Style := bsSolid;

Brush.Color := clWhite;

FillRect(aRect);

end;

end;

end.

5、 显示绘制源码

...{

作品名称: 小球问题通用解决方案

开发作者: 成晓旭

开发时间: 2003年01月22日

完成时间: 2003年01月22日

修改时间1: 2003年11月15日

增加小于问题初始状态绘制方法

}

unit BallType;

interface

uses

Dialogs,Windows,Classes,SysUtils,Graphics;

type

//小球问题:小球抽象数据类型

TC_Ball = Packed Record

Order:Byte;

Weight:Byte;

BgColor:TColor;

TextColor:TColor;

end;

//小球问题:被寻找的目标小球抽象数据类型

TC_SearchBall = Packed Record

Ball:TC_Ball;

IsHeavy:Boolean;

ErrorMsg:AnsiString;

end;

//小球问题:一次比较的参数的抽象数据类型

TC_CmpPara = Packed Record

Pre_LNumber:Byte;

Pre_Latency:array of TC_Ball;

Fro_LNumber:Byte;

Fro_Latency:array of TC_Ball;

end;

//小球问题:小球抽象类

TC_Ball_Class = class

private

bDrawOrder: Boolean;

bAbstractBall:TC_Ball;

bStartPoint:TPoint;

bSize:Integer;

bTextColor:TColor;

bBgColor:TColor;

bColorChanged: Boolean;

bCanvas: TCanvas;

public

procedure SetBgAndTextColor(bgColor: TColor; ttColor: TColor);

procedure DrawSelf();

constructor Create(bTrance: Boolean);

end;

//小球问题:天平抽象类

TC_Balance = class

// published

bMainPivot:TPoint;

bPartAPivot:TPoint;

bPartBPivot:TPoint;

bColor:TColor;

bPivotColor:TColor;

bCanvas: TCanvas;

bWeightA:Integer;

bWeightB:Integer;

private

bWidth:Integer;

bHeight:Integer;

bDelta:Integer;

public

procedure DrawSelf();

end;

//小球问题:天平比较一次抽象类[行为抽象]

TC_Compare = class

cbPivot:TPoint;

cbPreStart,cbFroStart:TPoint;

cbCmpPara:TC_CmpPara;

cbCount:Byte;

cbPre_Latency:array of TC_Ball;

cBallPartA:array of TC_Ball;

cBallPartB:array of TC_Ball;

cbFro_Latency:array of TC_Ball;

cBalance:TC_Balance;

cCanvas: TCanvas;

private

cbPPartA,cbPPartB:TPoint;

pPre_Latency:array of TC_Ball_Class;

pPartA:array of TC_Ball_Class;

pPartB:array of TC_Ball_Class;

pFro_Latency:array of TC_Ball_Class;

isShowTrace:Boolean;

procedure Draw_Balance();

procedure Draw_Part_A();

procedure Draw_Part_B();

procedure Draw_Latency();

public

procedure Draw_AllBall();

procedure Weigh_Out();

constructor Create(bTrace: Boolean);

end;

//小球问题抽象类<2003-11-14至今未被使用,是为方法的通用性而设计>

TC_Ball_Problem = class

bpBall:array of TC_Ball;

bpCompareCount:Byte;

bpBallCount:Byte;

bpCanvas: TCanvas;

bpCompare:array of TC_Compare;

pBalace:TC_Balance;

public

//procedure Weigh_Out(bCenterX,bCenterY:Integer);

end;

//天平的一次比较结果处理算法

procedure Balance_One_Latency(

BallStart1,BallStart2:TPoint;

OneCmpPara:TC_CmpPara;

ACanvas:TCanvas;

bTrace:Boolean);

//天平的一次比较执行算法

procedure Balance_One_Compare(

BalancePivot:TPoint;

BallNum:Byte;

PartA,PartB:array of TC_Ball;

ACanvas:TCanvas;

bTrace:Boolean);

//问题条件设置处理算法(小于的初始状态演示算法)

procedure Process_Initial_Ball(

StartPoint:TPoint;

AllBall:array of TC_Ball;

ACanvas:TCanvas;

bTrace:Boolean

);

implementation

...{ TC_Ball_Class }

constructor TC_Ball_Class.Create(bTrance: Boolean);

begin

bDrawOrder := NOT bTrance;

end;

procedure TC_Ball_Class.DrawSelf();

var

strDrawText:String;

w,h,r:Integer;

begin

//暂时增加

if bDrawOrder then

strDrawText := IntToStr(bAbstractBall.Order)

else

strDrawText := IntToStr(bAbstractBall.Weight);

if bColorChanged then

begin

bCanvas.Brush.Color := bBgColor;

bCanvas.Pen.Color := bBgColor;

bCanvas.Font.Color := bTextColor;

end

else

begin

bCanvas.Brush.Color := bAbstractBall.BgColor;

bCanvas.Pen.Color := bAbstractBall.BgColor;

bCanvas.Font.Color := bAbstractBall.TextColor;

end;

bCanvas.Font.Size := bSize;

bCanvas.Font.Style := [fsBold];

w := bCanvas.TextWidth(strDrawText);

h := bCanvas.TextHeight(strDrawText);

if w > h then

r := w

else

r := h;

//注意:此处的计算比例,是根据矩形的内接圆、外切圆推算出来的,

//再加以实现绘制时的位置系数调试、调整而来

bCanvas.Ellipse(bStartPoint.X,bStartPoint.Y,bStartPoint.X + r * 1414 div 1000,bStartPoint.Y + r * 1414 div 1000);

if (Length(strDrawText) = 1) then

bCanvas.TextOut(bStartPoint.X + r * 414 div 1000,bStartPoint.Y + r * 207 div 1000,strDrawText)

else if (Length(strDrawText) = 2) then

bCanvas.TextOut(bStartPoint.X + r * 214 div 1000,bStartPoint.Y + r * 228 div 1000,strDrawText);

end;

procedure TC_Ball_Class.SetBgAndTextColor(bgColor: TColor; ttColor: TColor);

begin

Self.bBgColor := bgColor;

Self.bTextColor := ttColor;

bColorChanged := true;

end;

...{ TC_Balance }

procedure TC_Balance.DrawSelf;

procedure DrawTray(ACanvas:TCanvas;aX,aY,Awidth,AHeight:Integer;aDeltaY:Integer);

begin

with ACanvas do

begin

MoveTo(aX,aY);

LineTo(aX - AWidth,aY + aDeltaY);

LineTo(aX - AWidth - AHeight,aY - AHeight + aDeltaY);

MoveTo(aX,aY);

LineTo(aX + AWidth,aY - aDeltaY);

LineTo(aX + AWidth + AHeight,aY - aHeight - aDeltaY);

end;

end;

var

X0,Y0,X1,Y1,X2,Y2,D,H:Integer;

begin

bDelta := 6;

if bWeightA > bWeightB then//[A > B]

bDelta := bDelta

else if bWeightA = bWeightB then//[A = B]

bDelta := 0

else//[A < B]

bDelta := - bDelta;

X0 := bMainPivot.X;

Y0 := bMainPivot.Y;

D := bWidth;

H := bHeight;

bCanvas.Pen.Color := bPivotColor;

bCanvas.Brush.Color := bPivotColor;

bCanvas.Polygon([Point(X0,Y0),Point(X0 - H,Y0 + H),Point(X0 + H,Y0 + H),Point(X0,Y0)]);

bCanvas.Pen.Color := bColor;

DrawTray(bCanvas,X0,Y0,D,H,bDelta);

X1 := X0 - D - H;

Y1 := Y0 - H + bDelta;

DrawTray(bCanvas,X1,Y1,D div 2,H,0);

X2 := X0 + D + H;

Y2 := Y0 - H - bDelta;

DrawTray(bCanvas,X2,Y2,D div 2,H,0);

bPartAPivot.X := X1;

bPartAPivot.Y := Y1;

bPartBPivot.X := X2;

bPartBPivot.Y := Y2;

end;

...{ TC_Compare }

constructor TC_Compare.Create(bTrace: Boolean);

begin

isShowTrace := bTrace;

end;

procedure TC_Compare.Draw_AllBall;

const

strHint = '比较前:';

var

Loop:Integer;

begin

SetLength(pPre_Latency,cbCmpPara.Pre_LNumber);

SetLength(cbCmpPara.Pre_Latency,cbCmpPara.Pre_LNumber);

for Loop := 0 to cbCmpPara.Pre_LNumber - 1 do

begin

pPre_Latency[Loop] := TC_Ball_Class.Create(isShowTrace);

pPre_Latency[Loop].bAbstractBall := cbCmpPara.Pre_Latency[Loop];

pPre_Latency[Loop].bSize := 10;

pPre_Latency[Loop].bStartPoint := Point(80+cbPreStart.X + Loop * 25,cbPreStart.Y);

pPre_Latency[Loop].SetBgAndTextColor(clBlue,clYellow);

pPre_Latency[Loop].bCanvas := cCanvas;

pPre_Latency[Loop].bCanvas.Font.Size := 11;

pPre_Latency[Loop].bCanvas.Font.Style := [fsBold];

pPre_Latency[Loop].bCanvas.Font.Color := clBlack;

pPre_Latency[Loop].bCanvas.Brush.Color := clWhite;

pPre_Latency[Loop].bCanvas.TextOut(cbPreStart.X,cbPreStart.Y,strHint);

pPre_Latency[Loop].DrawSelf();

pPre_Latency[Loop].Free();

end;

end;

procedure TC_Compare.Draw_Balance;

var

Loop:Integer;

begin

cBalance := TC_Balance.Create();

cBalance.bWeightA := 0;

cBalance.bWeightB := 0;

for Loop := 0 to cbCount - 1 do

begin

cBalance.bWeightA := cBalance.bWeightA + cBallPartA[Loop].Weight;

cBalance.bWeightB := cBalance.bWeightB + cBallPartB[Loop].Weight;

end;

cBalance.bMainPivot := cbPivot;

cBalance.bPivotColor := clFuchsia;

cBalance.bColor := clBlue;

cBalance.bWidth := 100;

cBalance.bHeight := 18;

cBalance.bCanvas := cCanvas;

cBalance.DrawSelf();

cbPPartA := cBalance.bPartAPivot;

cbPPartB := cBalance.bPartBPivot;

cBalance.Free();

end;

procedure TC_Compare.Draw_Latency;

const

strHint = '比较后:';

var

Loop:Integer;

begin

SetLength(pFro_Latency,cbCmpPara.Fro_LNumber);

//SetLength(cbCmpPara.Fro_Latency,cbCmpPara.Fro_LNumber);

//注意:下面Pre_Latency不能用Fro_Latency来代替,不知道为什么2003-11-20

SetLength(cbCmpPara.Pre_Latency,cbCmpPara.Fro_LNumber);

for Loop := 0 to cbCmpPara.Fro_LNumber - 1 do

begin

pFro_Latency[Loop] := TC_Ball_Class.Create(isShowTrace);

pFro_Latency[Loop].bAbstractBall := cbCmpPara.Fro_Latency[Loop];

pFro_Latency[Loop].bSize := 10;

pFro_Latency[Loop].bStartPoint := Point(80+cbFroStart.X + Loop * 25,cbFroStart.Y);

pFro_Latency[Loop].SetBgAndTextColor(clGreen,clYellow);

pFro_Latency[Loop].bCanvas := cCanvas;

pFro_Latency[Loop].bCanvas.Font.Size := 11;

pFro_Latency[Loop].bCanvas.Font.Style := [fsBold];

pFro_Latency[Loop].bCanvas.Font.Color := clBlack;

pFro_Latency[Loop].bCanvas.Brush.Color := clWhite;

pFro_Latency[Loop].bCanvas.TextOut(cbFroStart.X,cbFroStart.Y,strHint);

pFro_Latency[Loop].DrawSelf();

pFro_Latency[Loop].Free();

end;

end;

procedure TC_Compare.Draw_Part_A;

var

Loop,r:Integer;

begin

SetLength(pPartA,cbCount);

for Loop := 0 to cbCount - 1 do

begin

pPartA[Loop] := TC_Ball_Class.Create(isShowTrace);

pPartA[Loop].bAbstractBall.Order := cBallPartA[Loop].Order;

pPartA[Loop].bAbstractBall.Weight := cBallPartA[Loop].Weight;

pPartA[Loop].bSize := 10;

pPartA[Loop].SetBgAndTextColor(clYellow,clRed);

pPartA[Loop].bCanvas := cCanvas;

//注意:此句一定要有,设置字体的大小属性

pPartA[Loop].bCanvas.Font.Size := pPartA[Loop].bSize;

if pPartA[Loop].bCanvas.TextWidth(IntToStr(pPartA[Loop].bAbstractBall.Order)) >

pPartA[Loop].bCanvas.TextHeight(IntToStr(pPartA[Loop].bAbstractBall.Order)) then

r := pPartA[Loop].bCanvas.TextWidth(IntToStr(pPartA[Loop].bAbstractBall.Order))

else

r := pPartA[Loop].bCanvas.TextHeight(IntToStr(pPartA[Loop].bAbstractBall.Order));

r := r * 1414 div 1000;

//下面的计算公式有点难

pPartA[Loop].bStartPoint.X := cbPPartA.X - (cbCount div 2) * r - r * 5 * (cbCount mod 2) div 10 + Loop * r;

pPartA[Loop].bStartPoint.Y := cbPPartA.Y - r;

pPartA[Loop].DrawSelf();

pPartA[Loop].Free();

end;

end;

procedure TC_Compare.Draw_Part_B;

var

Loop,r:Integer;

begin

SetLength(pPartb,cbCount);

for Loop := 0 to cbCount - 1 do

begin

pPartB[Loop] := TC_Ball_Class.Create(isShowTrace);

pPartB[Loop].bAbstractBall.Order := cBallPartB[Loop].Order;

pPartB[Loop].bAbstractBall.Weight := cBallPartB[Loop].Weight;

pPartB[Loop].bSize := 10;

pPartB[Loop].SetBgAndTextColor(clYellow,clRed);

pPartB[Loop].bCanvas := cCanvas;

pPartB[Loop].bCanvas.Font.Size := pPartB[Loop].bSize;

if pPartB[Loop].bCanvas.TextWidth(IntToStr(pPartB[Loop].bAbstractBall.Order)) >

pPartB[Loop].bCanvas.TextHeight(IntToStr(pPartB[Loop].bAbstractBall.Order)) then

r := pPartB[Loop].bCanvas.TextWidth(IntToStr(pPartB[Loop].bAbstractBall.Order))

else

r := pPartB[Loop].bCanvas.TextHeight(IntToStr(pPartB[Loop].bAbstractBall.Order));

r := r * 1414 div 1000;

pPartB[Loop].bStartPoint.X := cbPPartB.X - (cbCount div 2) * r - r * 5 * (cbCount mod 2) div 10 + Loop * r;

pPartB[Loop].bStartPoint.Y := cbPPartB.Y - r;

pPartB[Loop].DrawSelf();

pPartB[Loop].Free();

end;

end;

procedure TC_Compare.Weigh_Out();

begin

Draw_Balance();

Draw_Part_A();

Draw_Part_B();

end;

procedure Balance_One_Compare(

BalancePivot:TPoint;

BallNum:Byte;

PartA,PartB:array of TC_Ball;

ACanvas:TCanvas;

bTrace:Boolean);

var

OneCmp:TC_Compare;

Loop:Integer;

begin

OneCmp := TC_Compare.Create(bTrace);

OneCmp.cbPivot := BalancePivot;

OneCmp.cbCount := BallNum;

OneCmp.cCanvas := ACanvas;

SetLength(OneCmp.cBallPartA,OneCmp.cbCount);

SetLength(OneCmp.cBallPartB,OneCmp.cbCount);

for Loop := 0 to OneCmp.cbCount - 1 do

begin

OneCmp.cBallPartA[Loop] := PartA[Loop];

OneCmp.cBallPartB[Loop] := PartB[Loop];

end;

OneCmp.Weigh_Out();

OneCmp.Free();

end;

procedure Balance_One_Latency(

BallStart1,BallStart2:TPoint;

OneCmpPara:TC_CmpPara;

ACanvas:TCanvas;

bTrace:Boolean);

var

OneCmp:TC_Compare;

begin

OneCmp := TC_Compare.Create(bTrace);

OneCmp.cCanvas := ACanvas;

OneCmp.cbCmpPara := OneCmpPara;

OneCmp.cbPreStart := BallStart1;

OneCmp.cbFroStart := BallStart2;

OneCmp.Draw_AllBall();

OneCmp.Draw_Latency();

OneCmp.Free();

end;

//问题条件设置处理算法(小于的初始状态演示算法)

procedure Process_Initial_Ball(

StartPoint:TPoint;

AllBall:array of TC_Ball;

ACanvas:TCanvas;

bTrace:Boolean);

const

//strHint = '初始状态:';

strHint = '';

var

Loop:Integer;

aBall: TC_Ball_Class;

begin

for Loop := Low(AllBall) to High(AllBall) - 1 do

begin

aBall := TC_Ball_Class.Create(bTrace);

aBall.bAbstractBall := AllBall[Loop + 1];

aBall.bSize := 10;

aBall.bStartPoint := Point(2 + StartPoint.X + Loop * 25,StartPoint.Y);

aBall.bCanvas := ACanvas;

aBall.bCanvas.Font.Size := 11;

aBall.bCanvas.Font.Style := [fsBold];

aBall.bCanvas.Font.Color := clBlack;

aBall.bCanvas.Brush.Color := clWhite;

aBall.bCanvas.TextOut(StartPoint.X,StartPoint.Y,strHint);

aBall.DrawSelf();

aBall.Free();

end;

end;

end.

6、 界面源码

...{

作品名称: 小球问题通用解决方案

开发作者: 成晓旭

开发时间: 2003年01月21日

完成时间: 2003年01月22日

修改时间1: 2003年02月10日 新增Delphi绘图功能

修改时间2: 2003年11月14日 新增对问题模拟条件的用户设置功能

修改时间2: 2003年11月20日 新增ClearCanvas()方法,解决不能清除画面问题

}

unit BMain;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls,BallType,Common, Buttons, ExtCtrls;

type

TExceptStyle = (esLight,esHeavy); //偏轻 偏重

const

strHint = '中国';

BallNumber = 12; //小球数量

BallValue = 10; //正常小球的质量

HeavyValue = 15; //偏重小球的质量

LightValue = 5; //偏轻小球的质量

type

TfrmMain = class(TForm)

btnDemo: TButton;

imgMain: TImage;

gbConfig: TGroupBox;

RadioButton1: TRadioButton;

RadioButton2: TRadioButton;

RadioButton3: TRadioButton;

RadioButton4: TRadioButton;

RadioButton5: TRadioButton;

RadioButton6: TRadioButton;

RadioButton7: TRadioButton;

RadioButton8: TRadioButton;

RadioButton9: TRadioButton;

RadioButton10: TRadioButton;

RadioButton11: TRadioButton;

RadioButton12: TRadioButton;

ImgConfig: TImage;

cbEStyle: TCheckBox;

Label1: TLabel;

Memo0: TMemo;

Label2: TLabel;

Label3: TLabel;

Memo1: TMemo;

Label4: TLabel;

Memo2: TMemo;

Label5: TLabel;

Memo3: TMemo;

btnSetNumber: TButton;

btnAuto: TButton;

btnAbout: TButton;

Label6: TLabel;

cbTrance: TCheckBox;

procedure FormShow(Sender: TObject);

procedure RadioButton1Click(Sender: TObject);

procedure btnDemoClick(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure btnSetNumberClick(Sender: TObject);

procedure btnAutoClick(Sender: TObject);

procedure btnAboutClick(Sender: TObject);

private

...{ Private declarations }

isTrance: Boolean; //是否跟踪(cbTrance的状态记录)

SmallBall:array[0..BallNumber] of TC_Ball; //小球的抽象数据

ExceptBall: TC_Ball; //异常小球

ExceptStyle:TExceptStyle; //异常小球的特性

ExceptBallValue:Integer; //异常小球的质量

ExceptColor:TColor; //异常小球的表示颜色

//处理小球问题条件设置RadioGroup

function ProcessRadioButton(isSort:Boolean):Integer;

//选择异常小球方法

procedure ChooseExceptBall();

//绘制所有小球方法

// withExceptBall = true<有异常小球的绘制>

// withExceptBall = false<无异常小球的绘制>

procedure DrawSmallBall(withExceptBall: Boolean; isTrance: Boolean);

procedure ClearCanvas

(aCanvas: TCanvas);

public

...{ Public declarations }

end;

var

frmMain: TfrmMain;

implementation

...{$R *.dfm}

//单元内部常量定义

const

Soft_Name = '小球问题解答过程演示程序0.2版';

strWaitHint = '本功能正在加紧完善中......' + CHR(13) + CHR(10) +

'请拭目以待!';

strSetNumber = '设置[3-12]的小球数目,程序将自动演示问题的解答过程!'

+ CHR(13) + CHR(10) + strWaitHint;

strAutoAnswer = '设置任意数目的小球,程序将根据本题的问题模式,'

+'推算最少的比较次数,并自动演示推算过程!'

+ CHR(13) + CHR(10) + strWaitHint;

About_Soft_Info = Soft_Name + CHR(13) + CHR(10) +

'开发作者:成晓旭'+ CHR(13) + CHR(10) +

'完成时间:2003年01月23日' + CHR(13) + CHR(10) +

'最后修改:2003年11月20日' + CHR(13) + CHR(10) +

'联系方式:CXXSoft@163.com' + CHR(13) + CHR(10) +

'设计说明:本程序采用纯面向对象的分析、设计、实现。' +

'也是本人的第一个运用' +

' 设计模式的作品。' + CHR(13) + CHR(10) +

'发布说明:程序完成时,我将公布其源码<欢迎来信索取>。';

function TfrmMain.ProcessRadioButton(isSort:Boolean):Integer;

const

space = 25;

var

aCtrl:TControl;

aChoose:TRadioButton;

//点击的小球索引号,循环计数器,第一个RadioButton的Top属性,GroupBox中RadioCount的计数器(关键)

indexBall,I,aTop,RadioCount:Integer;

begin

indexBall := -1;

aTop := 0;

RadioCount := 0; //注意:此处初值 = -1 是错误的

for I := 0 to gbConfig.ControlCount - 1 do

begin

aCtrl := gbConfig.Controls[I];

if aCtrl.ClassType = TRadioButton then

begin

try

Inc(RadioCount);

aChoose := TRadioButton(aCtrl);

if isSort then

begin

if indexBall = -1 then

aTop := aChoose.Top

else

aChoose.Top := aTop;

aChoose.Left := (RadioCount - 1) * space + 8;

end

else

begin

if aChoose.Checked then

begin

indexBall := RadioCount;

//ShowMessage('Index Ball = ' + IntToStr(indexBall));

break; //算法效率之关键

end;

end;

except

end;

end;

end;

Result := indexBall;

end;

procedure TfrmMain.FormShow(Sender: TObject);

begin

ProcessRadioButton(true);

DrawSmallBall(false,cbTrance.Checked);

end;

procedure TfrmMain.ChooseExceptBall();

var

index:Integer;

begin

index := ProcessRadioButton(false);

if (index >= 0) and (index <= BallNumber) then

ExceptBall := SmallBall[index];

if cbEStyle.Checked then

begin

ExceptStyle := esHeavy;

ExceptBallValue := HeavyValue;

ExceptColor := clRed;

end

else

begin

ExceptStyle := esLight;

ExceptBallValue := LightValue;

ExceptColor := clFuchsia;

end;

ExceptBall.Weight := ExceptBallValue;

ExceptBall.BgColor := ExceptColor;

ExceptBall.TextColor := clBlack;

SmallBall[index] := ExceptBall;

end;

procedure TfrmMain.DrawSmallBall(withExceptBall: Boolean; isTrance: Boolean);

var

Loop:Integer;

begin

for Loop := 1 to BallNumber do

begin

SmallBall[Loop].Order := Loop;

SmallBall[Loop].Weight := BallValue;

SmallBall[Loop].BgColor := clBlue;

SmallBall[Loop].TextColor := clRed;

end;

if withExceptBall then

begin

ChooseExceptBall();

end;

Draw_Ball_Config(SmallBall,ImgConfig.Canvas,ClientRect,isTrance);

end;

procedure TfrmMain.RadioButton1Click(Sender: TObject);

begin

try

isTrance := cbTrance.Checked;

except

isTrance := NOT isTrance;

end;;

DrawSmallBall(true,isTrance);

btnDemo.SetFocus();

end;

procedure TfrmMain.btnDemoClick(Sender: TObject);

begin

Serach_Error_Ball(SmallBall,imgMain.Canvas,ClientRect,isTrance);

Memo1.Lines.Text := strLog1;

Memo2.Lines.Text := strLog2;

Memo3.Lines.Text := strLog3;

end;

procedure TfrmMain.FormCreate(Sender: TObject);

begin

// Width := Screen.Width;

// Height := Screen.Height;

Width := 800;

Height := 600;

Caption := Soft_Name;

end;

procedure TfrmMain.ClearCanvas(aCanvas: TCanvas);

begin

aCanvas.Brush.Style := bsSolid;

aCanvas.Brush.Color := clWhite;

aCanvas.FillRect(ClientRect);

end;

procedure TfrmMain.btnSetNumberClick(Sender: TObject);

begin

Application.MessageBox(strSetNumber,Soft_Name,MB_ICONINFORMATION);

end;

procedure TfrmMain.btnAutoClick(Sender: TObject);

begin

Application.MessageBox(strAutoAnswer,Soft_Name,MB_ICONINFORMATION);

end;

procedure TfrmMain.btnAboutClick(Sender: TObject);

begin

Application.MessageBox(About_Soft_Info,Soft_Name,MB_ICONINFORMATION);

end;

end.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有