围棋,大家都知道是一个在平面上玩的游戏。有朋友别出心裁,提出在一条线上下围棋的想法,并取名叫做StringGo。
觉得很有意思,编个程序玩玩。
首先,要画线围棋的棋盘。顾名思义,线棋盘就是一根直线上均匀画上交叉点,就是取真正围棋盘上的一根线.
线画个看看,程序就是这样的拉 :
procedure TForm1.FormPaint(Sender: TObject);
var
i: Integer;
begin
with canvas do
begin
Pen.Width := 1;
moveto(10,50);
LineTo(210,50);
For i := 0 to 10 do
begin
if (i = 0) or (i = 10) then
Pen.Width := 3 //画两端的粗线
else
Pen.Width := 1; //画中间的细线
moveto(10 + i * 20,40);
Lineto(10 + i * 20,60);
end;
end;
end;
运行结果是这样的:
一个简单的StringGo的棋盘就画好了.
不过,这个棋盘有很多毛病,
1.棋盘位置是固定的,不能移动和伸缩;
2.棋盘大小也是固定的,只有11个交叉点.
3.这段程序不能随便移动重用,只能画在这个窗口的画布上,其他地方要画的画还要重写这段程序.
下面先解决问题2,让棋盘的大小(交叉点数)可以灵活设置,顺便补一个围棋盘上常见的"星位".
程序改成这样就可以了:
procedure TForm1.FormPaint(Sender: TObject);
begin
DrawBoard(8); //画9点棋盘
//DrawBoard(15); //画15点棋盘
end;
Procedure TForm1.DrawBoard(N : Integer);
var
i,M: Integer;
begin
M := N Div 2;
N := (M) * 2; //N必须是偶数,也就是必须得到奇数个交叉点;
with canvas do
begin
Pen.Width := 1;
moveto(10,50);
LineTo(10 + N * 20, 50);
For i := 0 to N do
begin
if (i = 0) or (i = N) then
Pen.Width := 3 //画两端的粗线
else
Pen.Width := 1; //画中间的细线
moveto(10 + i * 20,40);
Lineto(10 + i * 20,60);
if i = M then //在中点画一个星(天元,呵呵!)
begin
Brush.Color := ClBlack;
Brush.Style := bsSolid;
Ellipse(8 + i * 20,48,12 + i * 20,52);
end;
end;
end;
end;
给Form1增加了一个方法,带一个点数的参数就可以了.程序运行的效果是:
9点棋盘:
15点棋盘:
剩下的棋盘问题一次性解决算了,这次改动动作稍微大一点,为了很好地重用,创建了一个新类,TStringGoBoard,也就是线棋盘类了.
完整的程序如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TStringGoBoard = Class(TObject) //线棋盘类
Private
FMaxP : Integer; //棋盘最大点树
FRect : TRect; //棋盘区域位置
Function GetDD : Integer; //相邻交叉点间隔距离
Function GetBX0 : Integer; //棋盘起画点X
Function GetBY0 : Integer; //棋盘起画点Y
Protected
Procedure SetMaxP(AMaxP : Integer);
Property DD : Integer Read GetDD; //相邻交叉点间隔距离
Property BX0 : Integer Read GetBX0; //棋盘起画点X
Property BY0 : Integer Read GetBY0; //棋盘起画点Y
Public
Procedure Drawto(ACanvas : TCanvas); //画到一个画布上
Property MaxP : Integer Read FMaxP Write SetMaxP;
Property Rect : TRect Read FRect Write FRect;
End;
TForm1 = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
private
FBoard : TStringGoBoard;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FBoard := TStringGoBoard.Create; //窗口创建是创建棋盘
FBoard.Rect := ClientRect; //占整个窗口位置
FBoard.MaxP := 8; //设为9点棋盘
//FBoard.MaxP := 15; //设为15点棋盘
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
FBoard.Drawto(Canvas); //窗口重画时画出棋盘
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FBoard.Free; //窗口销毁时销毁棋盘
end;
procedure TForm1.FormResize(Sender: TObject);
begin
FBoard.Rect := ClientRect; //窗口变化大小是变化棋盘大小
Repaint; //启动重画窗口
end;
{TStringGoBoard}
Function TStringGoBoard.GetDD : Integer; //相邻交叉点间隔距离
begin
Result := ((Rect.Right - Rect.Left) - 20) div MaxP; //宽度两边各留10个像素
end;
Function TStringGoBoard.GetBX0 : Integer; //棋盘起画点X
begin
Result := Rect.Left + 10;
end;
Function TStringGoBoard.GetBY0 : Integer; //棋盘起画点Y
begin
Result := Rect.Top + (Rect.Bottom - Rect.Top) div 2;
end;
Procedure TStringGoBoard.SetMaxP(AMaxP : Integer);
begin
FMaxP := (AMaxP Div 2) * 2; //N必须是偶数,也就是必须得到奇数个交叉点;
end;
Procedure TStringGoBoard.Drawto(ACanvas : TCanvas); //画到一个画布上
var
i,M: Integer;
X0,Y0,BDD,CDD : Integer;
begin
M := MaxP div 2;
with ACanvas do
begin
Pen.Width := 1;
X0 := BX0; //动态计算画棋盘位置
Y0 := BY0;
BDD := DD;
CDD := BDD div 2;
moveto(X0,Y0);
LineTo(X0 + MaxP * BDD, Y0);
For i := 0 to MaxP do
begin
if (i = 0) or (i = MaxP) then
Pen.Width := 3 //画两端的粗线
else
Pen.Width := 1; //画中间的细线
moveto(X0 + i * BDD,Y0 - CDD);
Lineto(X0 + i * BDD,Y0 + CDD);
if i = M then //在中点画一个星(天元,呵呵!)
begin
Brush.Color := ClBlack;
Brush.Style := bsSolid;
Ellipse(X0 - 2 + i * BDD, Y0 -2, X0 +2 + i * BDD, Y0 +2);
end;
end;
end;
end;
end.
呵呵,这次的效果如下:
棋盘足够好用了,接下来就要编下棋的程序了.