⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c14_3f.cpp

📁 C++Builder编程实例详解,用具体的例子阐明C++的一些基本操作,所有程序均在BC++上编译过.可靠,建议下载
💻 CPP
字号:
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "C14_3f.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    Drawable = false;
    Gaming = false;
    Caption = "网络井字棋游戏";
    Listen->LocalPort = 1024;
    Connect->RemotePort = 1024;
    NewGameDraw();
    StartListen();
}
//---------------------------------------------------------------------------
void TForm1::StartListen()
{
    if(Listen->State != sckClosed)
    { // 关闭控件
        Listen->Close();
    }
    Listen->Listen(); // 开始监听网络。

    StatusBar1->Panels->Items[1]->Text = "监听网络..."; // 设置状态条
             // Panels->Items[1]->Text 指向第二个状态栏的内容
             // Panels->Items[0] 指向第一个状态栏
             // 如果StatusBar1的SimplePanel属性设为"true"(简单状态条),
             // 可以用SimpleText属性直接访问状态条的内容。
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LinkClick(TObject *Sender)
{
    if(Connect->State != sckClosed)
        Connect->Close();

    Server = "127.0.0.1"; // 设置输入地址的缺省值
    if(InputQuery("连接主机", "输入地址 (IP地址或主机名):", Server))
    // 提示用户输入服务器地址,判断输入
        if(Server.Length() > 0)
        {
            Listen->Close(); // 在申请连接前,停止监听
            Connect->Connect(Server, 1024); // 以1024(与服务器监听端口相同)端口连接服务器
            StatusBar1->Panels->Items[1]->Text = "正在连接...";
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ConnectError(TObject *Sender, short Number,
	AnsiString &Description, int Scode, const AnsiString Source,
	const AnsiString HelpFile, int HelpContext, WordBool &CancelDisplay)
{
    ShowMessage("连接失败");
    StatusBar1->Panels->Items[1]->Text = "";	
}
//---------------------------------------------------------------------------
void TForm1::NewGameDraw()
{
    int i;

    Image1->Canvas->FillRect(Form1->Canvas->ClipRect); // 清屏
    for(i=1;i<5;i++)
    { // 画棋盘格
        Image1->Canvas->MoveTo(ONESTEP, i*ONESTEP);
        Image1->Canvas->LineTo(4*ONESTEP, i*ONESTEP);
        Image1->Canvas->MoveTo(i*ONESTEP, ONESTEP);
        Image1->Canvas->LineTo(i*ONESTEP, 4*ONESTEP);
    }
    memset(Block, 0, sizeof(short)*25); // 清内存
    StatusBar1->Panels->Items[0]->Text = "";
}
//--------------------------------------------------------------------------
void __fastcall TForm1::NoWinClick(TObject *Sender)
{
    if(!Gaming)
        return;

    StatusBar1->Panels->Items[0]->Text = "";
    StatusBar1->Panels->Items[2]->Text = "认输";
    Variant v("2");
    Connect->SendData(v);
    Timer1->Enabled = false; // 停止记时
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ConnectConnect(TObject *Sender)
{
    NewGameDraw(); // 初始化数据
    Drawable = true; // Drawable 代表是否需要本程序用户画图
                     // 当 Drawable = true 时,为本用户走棋(画图)。
    Gaming = true; // 开始游戏
    Timer1->Enabled = true; // 开始记时
    StatusBar1->Panels->Items[1]->Text = "连接到:" + Connect->RemoteHostIP;
    StatusBar1->Panels->Items[2]->Text = "你先走!";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ConnectClose(TObject *Sender)
{ // 连接(由对方)终止
  // 当连接的另一方关闭连接,本控件触发该事件
  // 如果在程序中关闭连接控件
  // 则不产生该事件
    Connect->Close(); // 关闭本控件
    NewGameDraw(); // 重画游戏
    Timer1->Enabled = false;
    StatusBar1->Panels->Items[1]->Text = "结束连接";
    StatusBar1->Panels->Items[2]->Text = "";
    StatusBar1->Panels->Items[0]->Text = "";
    StartListen(); // 继续监听网络
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListenError(TObject *Sender, short Number,
	AnsiString &Description, int Scode, const AnsiString Source,
	const AnsiString HelpFile, int HelpContext, WordBool &CancelDisplay)
{ // 监听控件产生错误
    StatusBar1->Panels->Items[1]->Text = "无法监听";
    StatusBar1->Panels->Items[0]->Text = "";
    StatusBar1->Panels->Items[2]->Text = "";
    Listen->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CloseClick(TObject *Sender)
{ // 用户选择关闭连接菜单
    Connect->Close();
    StatusBar1->Panels->Items[1]->Text = "结束连接";
    StatusBar1->Panels->Items[0]->Text = "";
    StatusBar1->Panels->Items[2]->Text = "";
    StartListen();
}
//---------------------------------------------------------------------------
void TForm1::DrawRed(int X, int Y)
{ // 画红棋子
    int x, y;

    if(!Drawable || Block[X][Y] || !Gaming)
    // 当前格有棋子或禁止画
       return;

    Block[X][Y] = RedPlayer; // 设置当前格为红方棋子
    Drawable = false;
    StatusBar1->Panels->Items[2]->Text = "对方走...";

    char buf[1024];
    sprintf(buf, "1,%d,%d", X, Y);
    Variant v(buf);
    Connect->SendData(v); // 发送
    if(IsWon(RedPlayer))
    { // 已经胜利
        StatusBar1->Panels->Items[2]->Text = "你赢了!";
        Gaming = false;
    }
    Timer1->Enabled = false; // 记时

    x = X * ONESTEP + ONESTEP / 2; // 计算棋子中心位置
    y = Y * ONESTEP + ONESTEP / 2;

    int dx = ONESTEP / 3; // 计算棋子范围
    long RawColor = Image1->Canvas->Pen->Color; // 保存画笔原设置
    long RawWidth = Image1->Canvas->Pen->Width;
    Image1->Canvas->Pen->Color = clRed; // 设置画笔属性
    Image1->Canvas->Pen->Width = ONESTEP / 5;
    Image1->Canvas->Ellipse(x-dx, y-dx, x+dx, y+dx); // 画圆
    Image1->Canvas->Pen->Color = RawColor; // 恢复画笔设置
    Image1->Canvas->Pen->Width = RawWidth;
}
//--------------------------------------------------------------------------
void TForm1::DrawBlue(int X, int Y)
{
    int x, y;
    if(Drawable || Block[X][Y] || !Gaming)
    // 不该对方走或当前格有棋子
       return;

    Block[X][Y] = BluePlayer; // 设置当前格为蓝方棋子
    Drawable = true;

    x = X * ONESTEP + ONESTEP / 2; // 计算棋子中心位置
    y = Y * ONESTEP + ONESTEP / 2;

    int dx = ONESTEP / 3; // 计算棋子大小
    long RawColor = Image1->Canvas->Pen->Color; // 保存画笔原设置
    long RawWidth = Image1->Canvas->Pen->Width;
    Image1->Canvas->Pen->Color = clBlue; // 设置画笔属性
    Image1->Canvas->Pen->Width = ONESTEP / 5;
    Image1->Canvas->MoveTo(x-dx, y-dx); // 画十字
    Image1->Canvas->LineTo(x+dx, y+dx);
    Image1->Canvas->MoveTo(x-dx, y+dx);
    Image1->Canvas->LineTo(x+dx, y-dx);
    Image1->Canvas->Pen->Color = RawColor; // 恢复画笔设置
    Image1->Canvas->Pen->Width = RawWidth;
}
//--------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button,
	TShiftState Shift, int X, int Y)
{
    X /= ONESTEP;
    Y /= ONESTEP;
    if(X>0 && X<4 && Y>0 && Y<4)
    { // 鼠标点在棋盘格内
        DrawRed(X, Y);
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ConnectDataArrival(TObject *Sender, int bytesTotal)
{
    Variant v;
    Connect->GetData(v, VT_BSTR, bytesTotal); // 接收数据
    AnsiString str = v;
    char* buf = str.c_str(); // 类型转换
    int i = atoi(buf);
    switch(i)
    { // 判断接收数据(报文)类型
      case 1:
      { // 对方走棋
        StatusBar1->Panels->Items[2]->Text = "你走!";
        char *p = strchr(buf, ',') + 1; // 获得第一个逗号后面字符串的地址
                                        // strchr是一个C语言函数,用于返回
                                        // 字符串中包含指定字符的首地址。
                                        // strchr(...)+1即可获得字符串中该字符
                                        // 的下一个字符的地址。
        int x = atoi(p); // 类型转换宏,将字符串转换为整数。
                         // atoi宏从字符串的第一个字符开始转换,
                         // 当该宏遇到非数字字符时(如:','),停止转换。
        p = strchr(p, ',') + 1;
        int y = atoi(p);
        DrawBlue(4-x, 4-y); // 旋转棋子位置,画蓝方棋子
        if(IsWon(BluePlayer))
        { // 对方已经胜利
            StatusBar1->Panels->Items[2]->Text = "对方胜!";
            Gaming = false;
        }
        else
            Timer1->Enabled = true;
        break;
      }
      case 2:
      // 收到认输报文
        StatusBar1->Panels->Items[2]->Text = "对方认输!";
        Gaming = false;
        Timer1->Enabled = false; // 结束记时
        break;
      case 3:
      // 收到重新开始报文
        Gaming = true; // 开始游戏
        Drawable = false; // 禁止本程序用户走棋
        Timer1->Enabled = false; // 停止记时
        NewGameDraw(); // 初始化数据
        StatusBar1->Panels->Items[2]->Text = "对方走...";
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Listen1Click(TObject *Sender)
{
    StartListen();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListenConnectionRequest(TObject *Sender, int requestID)
{ // 在有连接申请时,触发该事件。
    Listen->Close(); // 停止监听网络
    Gaming = true;
    Drawable = false;
    Connect->Accept(requestID); // 连接
    StatusBar1->Panels->Items[1]->Text = "连接到:" + Connect->RemoteHostIP;
    StatusBar1->Panels->Items[2]->Text = "对方先走!";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListenClose(TObject *Sender)
{ // 监听控件关闭
    Listen->Close();
    StatusBar1->Panels->Items[0]->Text = "";
    StatusBar1->Panels->Items[1]->Text = "";
    StatusBar1->Panels->Items[2]->Text = "";
}
//---------------------------------------------------------------------------
bool  TForm1::IsWon(int player)
{
    int i, j;

    for(i=1;i<4;i++)
      for(j=1;j<4;j++)
      { // 遍历各点
        if(WonAt(player, i, j))
        { // 已经获胜
            Gaming = false;
            return(true);
        }
      }
    return(false);
}
//--------------------------------------------------------------------------
bool TForm1::WonAt(int Player, int X, int Y)
{
    int i, j;

    for(i=-1;i<1;i++) // 遍历指定棋子的四周
      for(j=-1;j<2;j++)
        if(i || j)
          if( Block[X-i][Y-j] == Player &&
              Block[X][Y] == Player &&
              Block[X+i][Y+j] == Player)
            return(true); // 判断棋子是否连成一线
    return(false);
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{ // 该函数用于记时
  // 当定时器产生Timer事件时,自动增加记时读数
    AnsiString str = StatusBar1->Panels->Items[0]->Text;
    char* p = str.c_str(); // 类型转换
                           // 不能使用 str.ToInt() 函数转换,
                           // 当该字符串为空时,str.ToInt() 出错。
    int i = atoi(p) + 1; // 读数加1
    char buf[10];
    sprintf(buf, " %d", i);
    StatusBar1->Panels->Items[0]->Text = buf; // 修改读数
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ReNewClick(TObject *Sender)
{ // 重新开始游戏
    NewGameDraw();
    Gaming = false;
    Variant v("3"); // 定义类型为3的报文
    Connect->SendData(v); // 发送数据
    Gaming = true;
    Drawable = true;
    StatusBar1->Panels->Items[2]->Text = "你走!";
    Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::sClearClick(TObject *Sender)
{ // 清理程序,重新开始
    Connect->Close();
    NewGameDraw();
    StartListen();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ExitClick(TObject *Sender)
{ // 退出
    Connect->Close(); // 关闭连接
    Listen->Close(); // 关闭监听
    exit(0);	
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -