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

📄 mainform1.cpp

📁 《C++Builder程序设计范例--中国象棋》配书盘自述文件
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop


#include "MainForm1.h"
#include "EditForm2.h"
#include "InfoForm3.h"
#include "ChessErr.h"
#include "InputPlyDepth.h"
#include "InputSecPerMove.h"
#include "InputMinPerGame.h"
#include "EndGameDlog.h"
#include "AboutDlog.h"
#include "ColorDlog.h"
#include "PieceValueDlog.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "CDefines.h"
#include "Global.h"


#undef MAXPATH
#define MAXPATH  160

/*
 *  全局变量
 */

BYTE ColorSquareColors[3] = { 0, 128, 0 };   /* 绿色 */

bool ShowBestPath = true;
HBRUSH hColorBrush;
HBITMAP PieceBmpArray[7][2];
HBITMAP MaskArray[7];
COLORTYPE ComputerColor;
short LINESIZE;
short CHARSIZE;
bool Editing;
int BORDERSIZE;
bool SoundOn;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

/*
在 #pragma资源声明里,加入包含定制光标的资源文件MyRc.res。
*/

#pragma resource "Chess.res"
#pragma resource "MyRc.res"

TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{

}
//---------------------------------------------------------------------------
/*
主Form必须负责创建子Form,前面两行分别创建了两个子Form,接下来的两行
将这些子Form放到一个数组中。然后,通过一个循环依次显示这些子Form。
使用这项技术时,不要让系统自动创建这些子Form。为此,需要打开
“Project Options”对话框,翻到“Form”页,然后将这些子Form
从列表框移到“Available Forms”列表框中。
*/
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
  InfoForm = new TInfoForm(this);
  EditForm = new TEditForm(this);
  ChildForms[1] = EditForm;
  ChildForms[2] = InfoForm;
  for (int i=1;i<3;i++)
    ChildForms[i]->Show();

   SoundOn = true;
   FileName = new char[MAXPATH];
   WhoseTurn = player;
   CurPlayer = red;
   ComputerColor = black;
   Editing = EditingChessBoard = GotStartSquare = false;
   blNewChessGame = true;
}
CheckLevelMenu(LEVELTYPE);
//---------------------------------------------------------------------------
/*
这是主窗体显示时事件处理函数
从资源文件载入光标及位图
由于光标及位图保存在资源文件(.res)内有两个好处。第一,它可以包含不同类型
的多种资源。第二,C++ Builder可以方便地把一个资源文件连接入最后的可执行
文件。
 "::"在变量前表明该变量是全局(外部)变量,
 在函数前表明该函数是全局(外部)函数。
*/
void __fastcall TMainForm::FormShow(TObject *Sender)
{
   HDC hDC;
   hDC = GetDC(MainForm->Handle);
   TEXTMETRIC tm;
   GetTextMetrics(hDC, &tm);
   CHARSIZE = short(tm.tmAveCharWidth);
   LINESIZE = short(tm.tmHeight + tm.tmExternalLeading);
   ReleaseDC(MainForm->Handle, hDC);
   BORDERSIZE = LINESIZE + MYFRAMESIZE;

 if ((GetSystemMetrics(SM_CXSCREEN)<800) || (GetSystemMetrics(SM_CYSCREEN)<600))
   MessageBox(NULL,"屏幕分辩率低于800X600!","警告",
      		 MB_ICONINFORMATION | MB_OK);

   Screen->Cursors[crWaitCursor]=LoadCursor(HInstance, "IDC_WCUR");
   //把自定义光标装入Screen对象
    ::PieceBmpArray[pawn-1][red]=LoadBitmap(HInstance, "RPawnBmp");
    ::PieceBmpArray[pawn-1][black] = LoadBitmap(HInstance, "BPawnBmp");
    ::PieceBmpArray[rook-1][red] = LoadBitmap(HInstance, "RRookBmp");
    ::PieceBmpArray[rook-1][black] = LoadBitmap(HInstance, "BRookBmp");
    ::PieceBmpArray[knight-1][black] = LoadBitmap(HInstance, "BKnightBmp");
    ::PieceBmpArray[bishop-1][black] = LoadBitmap(HInstance, "BBishopBmp");
    ::PieceBmpArray[assist-1][black] =  LoadBitmap(HInstance, "BAssistBmp");
    ::PieceBmpArray[gunner-1][black] =  LoadBitmap(HInstance, "BGunnerBmp");

    ::PieceBmpArray[knight-1][red] = LoadBitmap(HInstance, "RKnightBmp");
    ::PieceBmpArray[bishop-1][red] = LoadBitmap(HInstance, "RBishopBmp");
    ::PieceBmpArray[assist-1][red] = LoadBitmap(HInstance, "RAssistBmp");
    ::PieceBmpArray[gunner-1][red] = LoadBitmap(HInstance, "RGunnerBmp");
    ::PieceBmpArray[king-1][red] = LoadBitmap(HInstance, "RKingBmp");
    ::PieceBmpArray[king-1][black] = LoadBitmap(HInstance, "BKingBmp");
    ::MaskArray[pawn-1] = LoadBitmap(HInstance, "PMaskBmp");
    ::MaskArray[rook-1] = LoadBitmap(HInstance, "RMaskBmp");
    ::MaskArray[knight-1] =  LoadBitmap(HInstance, "KTMaskBmp");
    ::MaskArray[bishop-1] = LoadBitmap(HInstance, "BMaskBmp");
    ::MaskArray[assist-1] =  LoadBitmap(HInstance, "AMaskBmp");
    ::MaskArray[gunner-1] =   LoadBitmap(HInstance, "GMaskBmp");
    ::MaskArray[king-1] =  LoadBitmap(HInstance, "KMaskBmp");

    MainWndRect= MainForm->GetClientRect();
    MainForm->Menu=TChessMenu;    //设置主窗体主菜单
    Talk();
    MainForm->CheckLevelMenu(Level);
    hColorBrush = CreateSolidBrush(
      RGB(ColorSquareColors[0], ColorSquareColors[1], ColorSquareColors[2]));
    Dragging = true;
    Screen->Cursor = TCursor(crArrow); //分配箭头光标给应用程序
    ChildForms[2]->BringToFront();
}

//---------------------------------------------------------------------------
/*
 设置主窗体背景
通过文件方式载入位图。
对于位图没有保存在资源文件(.res)内,C++ Builder不能把从文件装入的位图
连接入最后的可执行文件。因此,必须确保在c:\BcbChess下有必需的位图文件。
 很明显,使用VCL函数比原始的API函数要方便得多。使用后,
 应将Canvas->Brush->Bitmap这个特性设为NULL,以释放位图。
 如果不删除位图,将导致程序内存不足。
*/
 void TMainForm::SetMainWindowBk()
   {
      Graphics::TBitmap *BLKBrushBmp = new Graphics::TBitmap();

      BLKBrushBmp->LoadFromFile("BKBrush.bmp");
      //BLKBrushBmp->LoadFromFile("c:\\BcbChess\\BKBrush.bmp");
      MainForm->Canvas->Brush->Bitmap=BLKBrushBmp;
      MainForm->Canvas->FillRect(MainForm->GetClientRect());
      MainForm->Canvas->Brush->Bitmap=NULL;
       delete BLKBrushBmp;
   }
//---------------------------------------------------------------------------
/*
主窗体重画事件处理函数
ReleaseDC函数释放设备描述句柄,不然,会导致系统资源不足
*/
void __fastcall TMainForm::FormPaint(TObject *Sender)
{
  SetMainWindowBk();
  HDC PaintDC = GetDC(MainForm->Handle);
  DrawFrame(PaintDC, MainWndRect);
  ReleaseDC(MainForm->Handle, PaintDC);
  PaintDC = GetDC(InfoForm->Handle);
  DrawFrame(PaintDC, InfoAreaRect);
  ReleaseDC(InfoForm->Handle, PaintDC);
  PrintChessBoard();
}
//---------------------------------------------------------------------------
/*
鼠标按下时事件处理函数
对弈状态时,按下左鼠标,可以抓住棋子进行移动,第二次按下时,释放棋子。
编辑状态时,按下左鼠标,可以使编辑窗体中的棋子透明显示,第二次在主窗体按下时,
可以添加棋子,再按击时,擦除棋子。
*/
void __fastcall TMainForm::FormMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
   POINT point;
   if (Button != mbLeft)
    return;
    MouseX=X;
    MouseY=Y;
   if (EditingChessBoard)
      {
      DoEdit();
      return;
      }

   if (WhoseTurn == computer && NoComputerMove == false)
      return;
  
  point=Point(MouseX,MouseY);
  MainForm->ScreenToClient( point);

   if (!GotStartSquare)
      {
      MoveStartSquare = GetValidSquare(point, CurPlayer, true);
      if (MoveStartSquare == -1)
         return;
      GotStartSquare = true;
      if (!Dragging)
         DrawInvertedBitmap(MoveStartSquare);
      else
         DragStart(MoveStartSquare, point);
      }
   else
      {
      MoveEndSquare = GetValidSquare(point, CurPlayer, false);
      GotStartSquare = false;
      if (MoveEndSquare == -1)
         {
         if (Dragging)
              DragEnd(false);
	 Warning("错误的移动!");
         DrawNormalBitmap(MoveStartSquare);
         return;
         }
      if (!MoveCheck(MoveStartSquare, MoveEndSquare))
         {
         if (Dragging)
            DragEnd(false);
         DrawNormalBitmap(MoveStartSquare);
         return;
         }
      GotValidMove = true;
      UndoMove->Enabled = true;
      if (GameOver)
         EndGame();
      else if (NoComputerMove == false)
         ComputersTurn();
      else if (MultiMove)
         {
         CurPlayer = (CurPlayer == red) ? black : red;
         }
      }
}
//---------------------------------------------------------------------------
/*
轮到计算机计算时的回调函数。
程序处于机器控制状态。主菜单发生改变。光标发生改变。
*/
void TMainForm::ComputersTurn()
{
   WhoseTurn = computer;
   Screen->Cursor =TCursor(crWaitCursor); //分配等待光标给应用程序
   MainForm->Menu=TChessThinkMenu; //设置主窗体主菜单
   ProgramMove();
   MainForm->Menu=TChessMenu;  //动态设置主窗体主菜单
   WhoseTurn = player;
   Screen->Cursor = TCursor(crArrow); //分配箭头光标给应用程序
   if (GameOver)
      EndGame();
}
//---------------------------------------------------------------------------
/*
主菜单项“新建”事件处理函数
主窗体进入初始对弈状态。同时清除信息窗体中的提示信息。
*/

void __fastcall TMainForm::NewChessGame1Click(TObject *Sender)
{
   Timer1->Enabled=false;
   InfoForm->Timer->Caption="时间:";
   UndoMove->Enabled = false;
   RedoUndo->Enabled = false;

   blNewChessGame = true;
   NewChessGame();
   PrintChessBoard();
   CurPlayer = Player;
   ComputerColor = Opponent;
}
//---------------------------------------------------------------------------
/*
自定义IDM_FILENEW消息回调函数
按击动态对话框“Yes”按钮发送一个消息,相当于按击主菜单项“新建”
*/
void TMainForm::FileNew(TMessage &Msg)
{
 MainForm->NewChessGame1Click(NewChessGame1);
}
//---------------------------------------------------------------------------
/*
主菜单项“恢复”事件处理函数
调用公用对话框打开控件函数,读入二进制棋盘文件。
*/
void __fastcall TMainForm::RestoreGame1Click(TObject *Sender)
{
     if(OpenDialog1->Execute())
      {
      blNewChessGame = false;
      RestoreGame(MainForm->OpenDialog1->FileName.c_str());
      CurPlayer = Player;
      ComputerColor = Opponent;
      RedoUndo->Enabled = false;   //重下菜单变灰
      UndoMove->Enabled = false;   //悔棋菜单变灰
      }
}
//---------------------------------------------------------------------------
/*
自定义函数
调用公用对话框保存控件函数,写入二进制棋盘文件。
*/
void  TMainForm::SaveGameAs()
{
    if(SaveDialog1->Execute())
 {
 blNewChessGame=false;
 SaveGame(MainForm->SaveDialog1->FileName.c_str());
 }
}

//---------------------------------------------------------------------------
/*
主菜单项“保存”事件处理函数
调用公用对话框保存控件函数,写入二进制棋盘文件。
*/
void __fastcall TMainForm::SaveGame1Click(TObject *Sender)
{
  if (blNewChessGame == true)
     SaveGameAs();
   else
     SaveGame(MainForm->SaveDialog1->FileName.c_str());

}
//---------------------------------------------------------------------------
/*
主菜单项“另存为...”事件处理函数
调用公用对话框保存控件函数,写入二进制棋盘文件。
*/
 void __fastcall TMainForm::SaveGameAsClick(TObject *Sender)
{
      SaveGameAs();
}
//---------------------------------------------------------------------------
/*
 自定义消息IDM_ERROR的回调函数
  动态构造、显示和删除ChessErrorDlg。
  虽然没有写TChessErrorDlg的析构函数,但当删除它们的Owner时VCL自动删除
  了控件。如果包含非可视化对象的指针,则需要增加ChessErrorDlg的析构函数。
*/
void TMainForm::EMError(TMessage &Msg)
{
  TChessErrorDlg *ChessErrorDlg= new TChessErrorDlg(Application,(AnsiString)buffer);
  ChessErrorDlg->ShowModal();
  delete  ChessErrorDlg;
}
/*
主菜单项“关于”事件处理函数
调用自定义静态对话框函数,无模态显示版权信息。
*/
void __fastcall TMainForm::AboutClick(TObject *Sender)
{
 AboutDlg->Show();
}
//---------------------------------------------------------------------------
/*
自定义编辑函数
读取光标位置,把选择的棋子在主窗体上的合法位置上显示出来。
*/
void TMainForm::DoEdit()
{
   POINT point;
   SQUARETYPE Square;
   int SelectedItem;
   Modified = true;
   point=Point(MouseX,MouseY);
   MainForm->ScreenToClient(point);
   Square = GetValidSquare(point, black, false);

   if (ChessBoard[Square].piece != empty)
      {
      ChessBoard[Square].piece = empty;
      UpdateChessBoard();
      return;
      }
    SelectedItem = EditForm->GetSelectedItem();

    ChessBoard[Square].piece = (PIECETYPE)(SelectedItem % 7 + 1);
    ChessBoard[Square].color = (SelectedItem < 7) ? red : black;
    UpdateChessBoard();
}

//---------------------------------------------------------------------------
/*
菜单项“摆子”的回调函数。
  EditForm->BringToFront()将编辑子窗体EditForm推到前端。
  CheckMenuItem第一个参数为菜单句柄,从菜单TChessEditMenu句柄属性Handle获取。
      第二个参数告诉菜单项是用命令ID指明的。
      第三个参数它告诉菜单项是应该执行哪一些操作。在这种情况下,
      MF_CHECKED告诉CheckMenuItem菜单项被打勾。
      MF_UNCHECKED告诉CheckMenuItem菜单项勾被取消。
*/
void __fastcall TMainForm::MovePieceClick(TObject *Sender)
{
    SaveChessBoard = new BOARDTYPE[0x99];
   if (SaveChessBoard == NULL)
      {
      Error("没有足够的内存");
      return;
      }
    memcpy(SaveChessBoard, ChessBoard, sizeof(BOARDTYPE) * 0x99);
   Editing = EditingChessBoard = true;
   MainForm->Menu=TChessEditMenu; //动态设置主窗体主菜单
   Modified = false;
   if (CurPlayer == red)
      {
       CheckMenuItem(TChessEditMenu->Handle, BlackTurn->Command, MF_UNCHECKED);
       CheckMenuItem(TChessEditMenu->Handle, RedTurn->Command, MF_CHECKED);
      }
   else
      {
      CheckMenuItem(TChessEditMenu->Handle, BlackTurn->Command, MF_CHECKED);
      CheckMenuItem(TChessEditMenu->Handle, RedTurn->Command, MF_UNCHECKED);
      }
   EditForm->BringToFront();
}
//---------------------------------------------------------------------------
/*
主菜单项“清除”事件处理函数
把主窗体中棋盘上棋子全部擦除。
*/

void __fastcall TMainForm::ClearClick(TObject *Sender)
{
  SQUARETYPE sq;

   Modified = true;
    for (sq = 0; sq <= 0x98; sq++)
      ChessBoard[sq].piece = empty;
    UpdateChessBoard();

}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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