现在的位置: 首页 > 综合 > 正文

Delphi开发基于UDP的网络五子棋

2013年10月14日 ⁄ 综合 ⁄ 共 5346字 ⁄ 字号 评论关闭

Delphi开发基于UDP的网络五子棋

 

五子棋是一种家喻户晓的棋类游戏,它的多变吸引了无数的玩家。下面我来介绍我用Delphi6.0中文企业版制作的“网络五子棋”程序。

一、网络五子棋设计思想

先介绍一下程序原理。下棋需要有棋盘,程序中我们通过在窗体激活时在image1TCanvas对象上画出了五子棋棋盘。有了五子棋棋盘还需要有棋子。我使用了image1TCanvas对象上绘制圆形图案代表棋子。界面中要求用户选择作为主机还是联机,用server变量来保存。

我们设计的难点在于与对方需要通讯。这里我使用了基于UDP(User Data Protocol)NMUDP控件。UDP是用户数据文报协议的简称,两台计算机之间的传输类似于传递邮件;两台之间没有明确的连接,使用UDP协议建立对等通信。这里虽然两者两台计算机不分主次,但我们设计时假设一台做主机(黑方),等待其他人加入。其他人想加入的时候输入主机的IP为了区分通信中传送的是“从机IP信息”,“下的棋子位置信息”,“悔棋请求”等,在发送信息的首部加上代号。我如下定义了协议:

0+从机IP

1+下的棋子位置坐标(x,y

2 (联机成功)

3+serverserver代表胜方)

4’(表示要求悔棋)

5+101表示同意,0表示不同意悔棋)

在下棋过程中,为了保存下过的棋子的位子使用了map数组,map数组初值为零,表示此处物棋子。map数组可以有12值,分别代表2种棋子图案,黑子,白子。为了显著表示对方刚下的棋子,这里我们用蓝子代表刚下过的黑子,红子代表刚下过的白子,其横纵坐标位置保存在old_qx,old_qy中。每下一步棋子,首先处理对(old_qx,old_qy)处对方刚下的棋子变色,将本步棋在棋盘上显示,并将本步棋的x,y坐标传出。每当接收到对方的下的棋子位置信息时,根据server判断画红子还是蓝子,并根据位置修改(old_qx,old_qy)。

本程序具有一定智能性,可以判断是否已经连成五子。程序中每下一步棋子,调用Gameover函数判断是否已经连成五子,如果返回非零,则说明已经连成五子,显示输赢结果。无论否已经连成五子,均将本步信息传到对方。Gameover函数中对棋盘的横竖斜方向均判断一遍,来达到检测出输赢。

 图片1

二、窗体界面和具体的代码:


unit Unit1;

 

interface

 

uses

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

  Dialogs, ExtCtrls, StdCtrls, NMUDP, ComCtrls,

  winsock;

type

  TForm1 = class(TForm)

    Image1: TImage;

    Image2: TImage;

    Label1: TLabel;

    Label2: TLabel;

    GroupBox1: TGroupBox;

    RadioButton1: TRadioButton;

    RadioButton2: TRadioButton;

    GroupBox2: TGroupBox;

    Edit1: TEdit;

    NMUDP1: TNMUDP;

    StatusBar1: TStatusBar;

    Button1: TButton;

    Button2: TButton;

    Button3: TButton;

    function  gameover(a:integer):integer;

    procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;

      Shift: TShiftState; X, Y: Integer);

    procedure RadioButton1Click(Sender: TObject);

    procedure RadioButton2Click(Sender: TObject);

    procedure NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer;

      FromIP: String; Port: Integer);

    procedure FormCreate(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure Button3Click(Sender: TObject);

    procedure FormActivate(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

 

var

  Form1: TForm1;

  map:array[1..15,1..15] of integer;

  server:integer;

  old_qx,old_qy:integer;

implementation

 

{$R *.dfm}

//uses winsock

//取本机IP地址

function GetIP:String;

var

 WSData: TWSAData;

 Buffer: array[0..63] of Char;

 HostEnt: PHostEnt;

 PPInAddr: ^PInAddr;

 IPString: String;

begin

 IPString:='';

 try

   WSAStartUp($101, WSData);

   GetHostName(Buffer, SizeOf(Buffer));

   HostEnt:=GetHostByName(Buffer);

   if Assigned(HostEnt) then

   begin

     PPInAddr:=@(PInAddr(HostEnt.H_Addr_List^));

     while Assigned(PPInAddr^) do

     begin

       IPString:=StrPas(INet_NToA(PPInAddr^^));

       Inc(PPInAddr);

     end;

   end;

   Result := IPString;

 finally

   try

     WSACleanUp;

   except

   end;

 end;

end;

 

function  TForm1.gameover(a:integer ):integer;//判断输赢

var i,j,s:integer;

begin

s:=0;

For i:= 1 To 11 do

  For j:= 1 To 11 do

  If (map[i,j] = a) and (map[i+1,j+1] = a) And (map[i+2,j+2] = a) And (map[i + 3,j + 3] = a )And (map[i + 4,j + 4] = a )Then  s:= a; // Exit Function

For i:= 5 To 15  do

  For j:= 1 To 11 do

  If (map[i, j] = a) And (map[i - 1, j + 1] = a )And (map[i - 2, j + 2] = a )And (map[i - 3, j + 3] = a) And (map[i - 4, j + 4] = a )Then     s:= a;

 

For i:= 1 To 15 do

  For j:= 5 To 15 do

  If (map[i, j] = a) And( map[i, j - 1] = a )And( map[i, j - 2] = a) And (map[i, j - 3] = a) And( map[i, j - 4] = a )Then   s:= a;

 

For i:= 5 To 11 do

  For j:= 1 To 15 do

  If (map[i, j] = a) And( map[i + 1, j] = a )And (map[i + 2, j] = a) And( map[i + 3, j] = a) And( map[i + 4, j] = a )Then   s:= a;

if s<>0 then

  Result:=s

else

  Result:=0;

End;

 

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

var qx,qy:integer;

    buf:array[1..20] of char;

begin

    // label1.Caption :=inttostr(x-12)+'  '+inttostr(y-12);

     button3.Enabled :=true;

     x:=x-13;

     y:=y-13;

     qx:=trunc(x/21)+1;

     qy:=trunc(y/20)+1;

    // label2.Caption :=inttostr(qx)+'  '+inttostr(qy);

     map[qx,qy]:=server;

       //处理上一次的对方走的棋子颜色改变

      if server=1 then  //主机 黑方

       begin

        image1.Canvas.Brush.Color:=clWHITE;

        image1.Canvas.pen.Color:=clWHITE;

        image1.Canvas.Ellipse(old_qx*21-9,old_qy*20-9+1,old_qx*21+9,old_qy*20+9+1);

        old_qx:=qx;old_qy:=qy;

       end

       else

       begin

        image1.Canvas.Brush.Color:=clBlack;

        image1.Canvas.pen.Color:=clBlack;

        image1.Canvas.Ellipse(old_qx*21-9,old_qy*20-9+1,old_qx*21+9,old_qy*20+9+1);

        old_qx:=qx;old_qy:=qy;

       end;

     //处理本次的对方走的棋子

     if  server=1 then

     begin

     image1.Canvas.Brush.Color:=clBlack;

     image1.Canvas.pen.Color:=clBlack;

     image1.Canvas.Ellipse(qx*21-9,qy*20-9+1,qx*21+9,qy*20+9+1);

     end

     else

     begin

     image1.Canvas.Brush.Color:=clWHITE;

     image1.Canvas.pen.Color:=clWHITE;

     image1.Canvas.Ellipse(qx*21-9,qy*20-9+1,qx*21+9,qy*20+9+1);

     end;

 

     //继续传棋子信息

     begin

        buf[1]:='1';buf[2]:=CHR(qx); buf[3]:=CHR(qy);

        NMUDP1.SendBuffer(buf,20);

     end;

     image1.Enabled:=false;//下过一步后,禁止再走棋

 

     //判断输赢

     if gameover(server)=server then

     begin

        label1.caption:='你赢了';

        image1.Enabled:=false;

        buf[1]:='3';buf[2]:=CHR(server);

        NMUDP1.SendBuffer(buf,20);

        button1.Enabled:=true;

        button3.Enabled:=false; //悔棋按钮禁用

        image1.Enabled:=false;

        statusbar1.SimpleText:='你赢了,下棋结束,请重新开局';

     end;

 

end;

 

procedure TForm1.RadioButton1Click(Sender: TObject);

begin

    groupbox2.Visible:=false;

    NMUDP1.LocalPort:=5555;

    NMUDP1.RemotePort:=6666;

    server:=1;

    statusbar1.SimpleText:=getip+'正在等待联机';

end;

 

procedure TForm1.RadioButton2Click(Sender: TObject);

begin

     groupbox2.Visible:=true;

end;

 

procedure TForm1.NMUDP1DataReceived(Sender: TComponent;

抱歉!评论已关闭.