怎样将图形画在网格交叉点上?(100分)

  • 主题发起人 主题发起人 zzzh
  • 开始时间 开始时间
Z

zzzh

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠好!

我是一名围棋爱好者,最近想用Delphi写一个围棋程序,代码如下:

unit Unit1;

interface
.....
var
Point: array[1..19] of array[1..19] of TPoint;
.....

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
i,j: Integer;
begin
for i:= 1 to 19 do
begin
for j:= 1 to 19 do
begin
Point[i,j].x:= 10+(i-1)*20;
Point[i,j].y:= 10+(j-1)*20;
end;
end;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
i,j: Integer;
begin
for i:= 1 to 19 do
begin
for j:= 1 to 19 do
begin
??? if X>(Point[i,j].x-10) and X<(Point[i,j].x+10)
and Y>(Point[i,j].y-10) and Y<(Point[i,j].y+10) then ???
begin
......

但运行时,系统说???间语句为Incompatible types,我百思不得其解,它们不都是Integer类型吗?
请各位大侠指教。小弟在此先谢过了。


礼!

zh
wxzhuhua@wx88.net
 
加上()

if (X>(Point[i,j].x-10)) and (X<(Point[i,j].x+10))
and (Y>(Point[i,j].y-10)) and (Y<(Point[i,j].y+10)) then
 
在Image1.OnMouseDown中使用
i := X div 20;
j := Y div 20;
那么棋子就在水平第i列,垂直第j行
这样改是不是效率更高呢?
 
没有必要定义一个TPoint的两维数组。只需要定义一个19*19的Boolean数组
记录哪个点上有棋子就行了。若要连下子的次序也记录下来,可用19*19的
整型数组,0表示没棋子,1表示第一步,2表示第二步......
要重画棋盘用简单的两重循环就可以了。
要判断棋子落在哪一格,用简单的整形除法就行了。要注意边界和舍入。
假设棋盘是在(15,15)开始画,每格10点,那么:
i := (X - 15 + 5) div 10;
j := (Y - 15 + 5) div 10;
然后限制 i 和 j 的值在 0 -- 18 之间。
 
另外,怎样判断吃子稍稍复杂,稍后会将算法写给你。
 
Pascal的and比<>级别高
 
To Bacchus:
看清楚,别人的网格是以20点为间隔的喔。
 
接受JohnsonGuo的指正,是我没有看清楚。
各位朋友,请给我一点时间,大约在周一将会有完整的源代码。
BTW,在这里能不能粘贴附件?若我将源代码写在正文中会太长。
 
对不起迟了两天,因没机会上网。
出于好玩我写了个下围棋的程序,不知各位有没有兴趣。
若zzzh愿意,我可以将全部源代码EMail给你作为参考,
希望你能写出更完善有用的围棋程序。
以下是其中关于吃子的算法:

function TFormBoard.CheckEat(X, Y: TCrd): Boolean;
var Checked: array[TCrd, TCrd] of Boolean;
Val: integer;

function IsDead(X, Y: TCrd): Boolean;
var v: integer;
begin
// 边界当作没有气处理
if (X < Low(TCrd)) or (X > High(TCrd)) or
(Y < Low(TCrd)) or (Y > High(TCrd)) then
begin
result := True;
Exit;
end;

v := Go[X, Y] * Val;
// 乘积为零即是空格,作有气处理
if v = 0 then
begin
result := False;
Exit;
end;
// 乘积大于零即与刚下的子同色,对于被判断的棋子是没有气的
if v > 0 then
begin
result := True;
Exit;
end;
// 防止检查的路径走回头路
if Checked[X, Y] then
begin
result := True;
Exit;
end;

// 这时是与刚下的子不同色的棋子,不能马上知道其是否有气
// 先将它放入检查记录内,然后,若它周围的四个方向都没有气,它就没有气了
Checked[X, Y] := True;
//ShowMessage('Checked: ' + IntToStr(X) + ', ' + IntToStr(Y));
if IsDead(X-1, Y) and
IsDead(X+1, Y) and
IsDead(X, Y-1) and
IsDead(X, Y+1) then
result := True
else
result := False;
end;

procedure CheckDead(X, Y: TCrd);
var i, j: integer;
begin
// 先将检查记录清空
for i:=Low(TCrd) to High(TCrd) do
for j:=Low(TCrd) to High(TCrd) do
Checked[i, j] := False;

if IsDead(X, Y) then
begin
// 若被吃,将检查记录内的子全提掉
for i:=Low(TCrd) to High(TCrd) do
for j:=Low(TCrd) to High(TCrd) do
begin
if Checked[i, j] then
Go[i, j] := 0;
end;
end;
end;

var i, j: integer;
begin
Val := Go[X, Y]; // 记下刚下的子作参照
CheckDead(X-1, Y); //--------------------------------
CheckDead(X+1, Y); // 分别检查与刚下的子相邻的四个子
CheckDead(X, Y-1); // 有没有被吃掉
CheckDead(X, Y+1); //--------------------------------

// 检查自杀的情况
for i:=Low(TCrd) to High(TCrd) do
for j:=Low(TCrd) to High(TCrd) do
Checked[i, j] := False;
Val := -Go[X, Y];
result := not IsDead(X, Y);
end;



 
多人接受答案了。
 
后退
顶部