📄 c15_4f.cpp
字号:
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop
#include "C15_4f.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void TForm1::NewGameDraw()
{
int i, j, k;
MyRect r;
PaintBox1->Canvas->FillRect(Form1->Canvas->ClipRect); // 清屏
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
{ // 画棋盘格
r = Border[i][j][k];
PaintBox1->Canvas->MoveTo(r.x1, r.y1);
PaintBox1->Canvas->LineTo(r.x2, r.y2);
PaintBox1->Canvas->LineTo(r.x3, r.y3);
PaintBox1->Canvas->LineTo(r.x4, r.y4);
PaintBox1->Canvas->LineTo(r.x1, r.y1);
}
memset(Block, NoPlayer, sizeof(short)*125); // 清内存
for(i=0;i<5;i++)
for(j=0;j<5;j++)
{ // 初始化数组边界
Block[0][i][j] = OtherPlayer;
Block[4][i][j] = OtherPlayer;
Block[i][0][j] = OtherPlayer;
Block[i][4][j] = OtherPlayer;
Block[i][j][0] = OtherPlayer;
Block[i][j][4] = OtherPlayer;
}
StatusBar1->Panels->Items[0]->Text = "";
StatusBar1->Panels->Items[2]->Text = "";
}
//---------------------------------------------------------------------------
void TForm1::GameDraw()
{
int i,j, k;
MyRect r;
PaintBox1->Canvas->FillRect(Form1->Canvas->ClipRect); // 清屏
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
{ // 画棋盘格
r = Border[i][j][k];
PaintBox1->Canvas->MoveTo(r.x1, r.y1);
PaintBox1->Canvas->LineTo(r.x2, r.y2);
PaintBox1->Canvas->LineTo(r.x3, r.y3);
PaintBox1->Canvas->LineTo(r.x4, r.y4);
PaintBox1->Canvas->LineTo(r.x1, r.y1);
}
}
//---------------------------------------------------------------------------
void TForm1::DrawRed(int X, int Y, int Z)
{ // 画红棋子
int x, y;
Block[X][Y][Z] = RedPlayer; // 设置当前格为红方棋子
MyRect r = Border[X-1][Y-1][Z-1];
if(IsWon(RedPlayer))
{ // 已经胜利
StatusBar1->SimpleText = "你赢了!";
Gaming = false;
}
Timer1->Enabled = false; // 停止记时
int dy = OneStepY / 5;
int OneStep = OneStepX > OneStepY ? OneStepY : OneStepX;
long RawColor = PaintBox1->Canvas->Pen->Color; // 保存画笔原设置
long RawWidth = PaintBox1->Canvas->Pen->Width;
PaintBox1->Canvas->Pen->Color = clRed; // 设置画笔属性
PaintBox1->Canvas->Pen->Width = OneStep / 5;
PaintBox1->Canvas->Ellipse(r.x1, r.y1+dy, r.x3, r.y3-dy); // 画圆
PaintBox1->Canvas->Pen->Color = RawColor; // 恢复画笔设置
PaintBox1->Canvas->Pen->Width = RawWidth;
}
//---------------------------------------------------------------------------
void TForm1::DrawBlue(int X, int Y, int Z)
{
Block[X][Y][Z] = BluePlayer; // 设置当前格为蓝方棋子
MyRect r = Border[X-1][Y-1][Z-1];
int dx = OneStepX / 4; // 计算棋子大小
int dy = OneStepY / 4;
int OneStep = OneStepX > OneStepY ? OneStepY : OneStepX;
long RawColor = PaintBox1->Canvas->Pen->Color; // 保存画笔原设置
long RawWidth = PaintBox1->Canvas->Pen->Width;
PaintBox1->Canvas->Pen->Color = clBlue; // 设置画笔属性
PaintBox1->Canvas->Pen->Width = OneStep / 5;
PaintBox1->Canvas->MoveTo(r.x1 + dx, r.y1 + dy); // 画十字
PaintBox1->Canvas->LineTo(r.x3 - dx, r.y3 - dy);
PaintBox1->Canvas->MoveTo(r.x2 - dx, r.y2 + dy);
PaintBox1->Canvas->LineTo(r.x4 + dx, r.y4 - dy);
PaintBox1->Canvas->Pen->Color = RawColor; // 恢复画笔设置
PaintBox1->Canvas->Pen->Width = RawWidth;
}
//---------------------------------------------------------------------------
// 该函数用于判断是否结束游戏(胜利)。
bool TForm1::IsWon(int Player)
{
int i, j, k;
for(i=1;i<4;i++)
for(j=1;j<4;j++)
for(k=1;k<4;k++)
{ // 遍历各点
if(WonAt(Player, i, j, k))
{ // 已经获胜
Gaming = false;
Drawable = false;
return(true);
}
}
return(false);
}
//---------------------------------------------------------------------------
bool TForm1::WonAt(int Player, int X, int Y, int Z)
{
int i, j, k;
for(i=-1;i<2;i++) // 遍历指定棋子的四周
for(j=-1;j<2;j++)
for(k=-1;k<2;k++)
if(i || j || k)
if( Block[X-i][Y-j][Z-k] == Player &&
Block[X][Y][Z] == Player &&
Block[X+i][Y+j][Z+k] == Player)
return(true); // 判断棋子是否连成一线
return(false);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::NewGameClick(TObject *Sender)
{
NewGameDraw();
StatusBar1->Panels->Items[2]->Text = "开始新游戏,你先走";
Timer1->Enabled = true;
//BlueMove();
Drawable = true;
Gaming = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
GameDraw(); // 重画棋盘
PaintDraw(); // 重画棋子
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
OneStepY = PaintBox1->Height / 13;
OneStepX = (PaintBox1->Width - OneStepY * 3) / 5;
int i, j, k;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
{
Border[i][j][k].x1 = (k + 1)*OneStepX + (3 - j)*OneStepY;
Border[i][j][k].y1 = (j + i * 4 + 1) * OneStepY;
Border[i][j][k].x4 = (k + 1) * OneStepX + (2 - j)*OneStepY;
Border[i][j][k].y4 = (j + i * 4 + 2) * OneStepY;
Border[i][j][k].x3 = Border[i][j][k].x4 + OneStepX;
Border[i][j][k].y3 = Border[i][j][k].y4;
Border[i][j][k].x2 = Border[i][j][k].x1 + OneStepX;
Border[i][j][k].y2 = Border[i][j][k].y1;// + OneStepY;
}
}
//---------------------------------------------------------------------------
void TForm1::PaintDraw()
{
int i, j, k;
for(i=1;i<4;i++)
for(j=1;j<4;j++)
for(k=1;k<4;k++)
if(Block[i][j][k] == RedPlayer)
DrawRed(i,j,k);
else if(Block[i][j][k] == BluePlayer)
DrawBlue(i,j,k);
}
//---------------------------------------------------------------------------
bool TForm1::IsInBorder(int &x, int &y, int &z)
{
int i, j, k;
HRGN hRgn;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
{ // 遍历各棋格
// 创建多边形,
// CreatePolygonRgn 是Windows函数
hRgn = CreatePolygonRgn((POINT*)&Border[i][j][k], 4, WINDING);
int stat = PtInRegion(hRgn, x, y); // 利用Windows函数判断鼠标位置
// PtInRegion 用于判断指定点(X,Y)是否在多边形中
DeleteObject(hRgn); // 删除多边形
// 多边形使用后必须删除以释放占用的系统资源
if(stat)
{ // 点在多边形(平行四边形)内
x = i+1;
y = j+1;
z = k+1;
return(true);
}
}
return(false);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
int x = X, y = Y, z;
if(IsInBorder(x, y, z))
// 鼠标点在棋盘格内
if(IsNot(x, y, z))
{ // 当前位置无棋子
if(Drawable)
{ // 由用户走棋
Timer1->Enabled = false;
DrawRed(x, y, z);
Drawable = false;
if(!IsWon(RedPlayer))
{ // 红方未胜
StatusBar1->Panels->Items[2]->Text = "计算机走,稍等";
BlueMove();
if(IsWon(BluePlayer))
{ // 蓝方胜
StatusBar1->Panels->Items[2]->Text = "对不起,计算机胜!";
Gaming = false;
return;
}
}
else
{ // 红方胜
StatusBar1->Panels->Items[2]->Text = "祝贺,你赢了!";
Gaming = false;
return;
}
if(NoWon())
{ // 和棋
StatusBar1->Panels->Items[2]->Text = "和棋!";
Gaming = false;
return;
}
else
{
Drawable = true;
Timer1->Enabled = true;
StatusBar1->Panels->Items[2]->Text = "你走";
}
}
}
}
//---------------------------------------------------------------------------
// 该函数用于判断是否和棋
bool TForm1::NoWon()
{
int i, j, k;
for(i=1;i<4;i++)
for(j=1;j<4;j++)
for(k=1;k<4;k++)
// 遍历各点
if(Block[i][j][k] == NoPlayer)
// 如果当前点无棋子,则返回 FALSE 。
return(false);
return(true); // 所有点都有棋子,返回 TRUE 。
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Gaming = false;
Drawable = false;
NewGameClick(NULL);
}
//---------------------------------------------------------------------------
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; // 修改读数
}
//---------------------------------------------------------------------------
bool TForm1::IsBlue(int X, int Y, int Z)
{ // 判断当前位置是否有蓝棋
if(X>3 || X<1)
return(false); // X 超界
else if(Y>3 || Y<1) // Y 超界
return(false);
else if(Z>3 || Z<1) // Z 超界
return(false);
else if(Block[X][Y][Z] != BluePlayer)
return(false);
else
return(true); // 当前位置是蓝棋
}
//---------------------------------------------------------------------------
bool TForm1::IsRed(int X, int Y, int Z)
{ // 判断当前位置是否有红棋
if(X>3 || X<1)
return(false); // X 超界
else if(Y>3 || Y<1) // Y 超界
return(false);
else if(Z>3 || Z<1)
return(false);
else if(Block[X][Y][Z] != RedPlayer)
return(false);
else
return(true); // 当前位置是红棋
}
//---------------------------------------------------------------------------
bool TForm1::IsNot(int X, int Y, int Z)
{ // 判断当前位置是否无棋子
if(X>3 || X<1)
return(false); // X 超界
else if(Y>3 || Y<1)
return(false); // Y 超界
else if(Z>3 || Z<1)
return(false);
else if(Block[X][Y][Z] != NoPlayer)
return(false);
else
return(true); // 当前位置无棋子
}
//---------------------------------------------------------------------------
void TForm1::BlueMove()
{ // 计算机走棋(蓝棋)函数
int x, y, z;
int dx, dy, dz;
int BlockX, BlockY, BlockZ;
bool BlockCount = false;
int MoveCount = 0;
int MaxMoveCount=0;
int MaxX, MaxY, MaxZ;
int OneCount = 0;
int MaxOneCount = 0;
int OneX, OneY, OneZ;
bool X_Y = false;
int X, Y, Z;
for(x=1;x<4;x++)
for(y=1;y<4;y++)
for(z=1;z<4;z++)
if(Block[x][y][z] == NoPlayer)
{
MoveCount = 0;
OneCount = 0;
for(dx=-1;dx<2;dx++)
for(dy=-1;dy<2;dy++)
for(dz=-1;dz<2;dz++)
if(dx || dy || dz)
{
if(IsBlue(x+dx, y+dy, z+dz))
if(IsBlue(x+2*dx, y+2*dy, z+2*dz) || IsBlue(x-dx, y-dy, z-dz))
{ // 蓝方胜
DrawBlue(x, y, z);
return;
}
if(IsRed(x+dx, y+dy, z+dz))
if(IsRed(x+2*dx, y+2*dy, z+2*dz) || IsRed(x-dx, y-dy, z-dz))
{ // 如果红方走在(X,Y)处,将获胜
BlockX = x;
BlockY = y;
BlockZ = z;
BlockCount = true;
}
// 以下计算当前点最大可能获胜数
if(IsBlue(x+dx, y+dy, z+dz))
if(IsNot(x+2*dx, y+2*dy, z+2*dz) || IsNot(x-dx, y-dy, z-dz))
MoveCount++;
else if(IsNot(x+dx, y+dy, z+dz))
if(IsBlue(x+2*dx, y+2*dy, y+2*dz) || IsBlue(x-dx, y-dy, z-dz))
MoveCount++;
// 以下计算当前位置周围的空缺数
if(IsNot(x+dx, y+dy, z+dz))
OneCount++;
}
if(MoveCount>MaxMoveCount)
{ // 保存最大可能获胜数及走法
MaxMoveCount = MoveCount;
MaxX = x;
MaxY = y;
MaxZ = z;
}
if(OneCount > MaxOneCount)
{
MaxOneCount = OneCount;
OneX = x;
OneY = y;
OneZ = z;
}
if(IsNot(x, y, z))
{ // 当前位置为空
X_Y = true;
X = x;
Y = y;
Z = z;
}
}
if(BlockCount)
// 阻止红方胜
DrawBlue(BlockX, BlockY, BlockZ);
else if(MaxMoveCount)
// 蓝方最有可能获胜
DrawBlue(MaxX, MaxY, MaxZ);
else if(MaxOneCount)
// 最好走的位置(周围的棋子少)
DrawBlue(OneX, OneY, OneZ);
else if(X_Y)
// 空位置
DrawBlue(X, Y, Z);
// 如果以上条件都不满足,说明棋盘上已经放满了棋子,
// 如果仍无获胜方,为和棋。
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ExitClick(TObject *Sender)
{
Application->Terminate();
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -