📄 c14_3f.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 + -