精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● VFP>>〖源码共赏〗>>一个五子棋的框架(prg版)

主题:一个五子棋的框架(prg版)
发信人: hunter__fox(雁回西楼)
整理人: hunter__fox(2002-03-16 23:07:15), 站内信件
这是一个五子其和小程序,代码中留下了写算法的接口,此代码目已经可完成基本功能,但存盘等功能尚未写代码,可按自己喜好写。

* 五子棋程序
* Hunter 2001-11-08
* Hunter 2001-06-11
* Hunter 2001-06-08
*

* 请自己定博弈算法,并在
* _Form的Init     中相应处调用----Line 49
* _QiPan的Go      中相应处调用----Line 157


#Define Size_QiZi_Loc  30       && 棋子大小
#Define Total_Line_Loc 15       && 棋盘线数
#Define Renju_Loc      "五子棋"  && 表单标题
#Define MsgTest_Loc    "此处已经有棋子了。"
#Define MsgTitle_Loc   "不能落子"
#Define Black_Loc      "黑棋"
#Define White_Loc      "白棋"
#Define Victory_Loc    "胜利"
#Define ReSatrt_Loc    "重新开始吗?"

Public poRenju
poRenju = CreateObject("_Form")
poRenju.Show(1)
Read Events
  Close All
  Release All
  Clear All
*  Quit


*类别列表:
* _Form-------------表单>>>>DoComputer
* _QiPan------------棋盘>>>>Go(),ReBew(),SaveLog(),LoadLog(),GoLog,QiZiCount[225]
* _Container--------容器基类>>>>无边框,透明,高宽为棋子大小
*  _B------------黑棋子
*  _W------------白棋子
*  _Hover--------光标标志>>>>随鼠标移动,>>>>Top_Assign(),Left_Assign(),X,Y
*  _Line-------------线条基类>>>>鼠标事件由容器处理
*  _LineX--------盘中竖线>>>>宽度为零
*  _LineY--------盘中横线>>>>高度为零
*   _LineHover----光标线>>>>蓝色

*==========表单定义

Define Class _Form As Form
  AutoCenter = .T.
  BorderStyle = 2
  Caption = Renju_Loc
  Desktop = .T.
  MaxButton = .F.
  ShowWindow = 2
  WindowType = 1
  DoComputer = "" && 电脑是否下棋----为空不下棋,"W"表示下白棋,"B"表示下黑棋
  Add Object oQiPan As _QiPan With Top = 2,Left = 2 && 棋盘
  Procedure Init
    DoDefault()
    * 表单比棋盘略大一些
    This.Height = This.oQiPan.Height + 4
    This.Width = This.oQiPan.Width + 4
    If This.DoComputer = "B"
      && 请在此调用自己的博弈算法
    EndIf
  EndProc
  Procedure Destroy
    && 在此退出
    Clear Events
  EndProc
  Procedure KeyPress
  LParameters nKeyCode,nShift
    If IsNull(ThisForm.DoComputer)
      Do Case && 用键盘控制鼠标的移动,只要调用热点的相应方法即可.
      Case nKeyCode = 5 && 向上
        This.oQiPan.Hover.MoveUp
      Case nKeyCode = 24 && 向下
        This.oQiPan.Hover.MoveDown
      Case nKeyCode = 19 && 向左
        This.oQiPan.Hover.MoveLeft
      Case nKeyCode = 4 && 向右
        This.oQiPan.Hover.MoveRight
      Case nKeyCode = 13 Or nKeyCode = 32 && 空格及回车是落子.
        This.oQiPan.Hover.Click
      Case nKeyCode = 27 && ESC 退出
        ThisForm.Destroy
      OtherWise
        DoDefault()
      EndCase
    EndIf
  EndProc
EndDefine
*==========棋盘定义
Define Class _QiPan As Container
  Start = .T.
  BackColor = RGB(255,128,0)
  BorderWidth = 2
  BorderColor = RGB(0,0,255)
  Height = Size_QiZi_Loc * Total_Line_Loc + 4
  Width = Size_QiZi_Loc * Total_Line_Loc + 4
  GoLog = "" && 落子记录,每一步用一字节记录,前四位记X值,
             && 后四后记Y值,最长有225字节.通过它的长度可知该谁走棋
  && 以下是棋盘中的线条

  Add Object Protected Line01 As _LineX With Left = Size_QiZi_Loc *  0.5 + 2
  Add Object Protected Line02 As _LineX With Left = Size_QiZi_Loc *  1.5 + 2
  Add Object Protected Line03 As _LineX With Left = Size_QiZi_Loc *  2.5 + 2
  Add Object Protected Line04 As _LineX With Left = Size_QiZi_Loc *  3.5 + 2
  Add Object Protected Line05 As _LineX With Left = Size_QiZi_Loc *  4.5 + 2
  Add Object Protected Line06 As _LineX With Left = Size_QiZi_Loc *  5.5 + 2
  Add Object Protected Line07 As _LineX With Left = Size_QiZi_Loc *  6.5 + 2
  Add Object Protected Line08 As _LineX With Left = Size_QiZi_Loc *  7.5 + 2
  Add Object Protected Line09 As _LineX With Left = Size_QiZi_Loc *  8.5 + 2
  Add Object Protected Line10 As _LineX With Left = Size_QiZi_Loc *  9.5 + 2
  Add Object Protected Line11 As _LineX With Left = Size_QiZi_Loc * 10.5 + 2
  Add Object Protected Line12 As _LineX With Left = Size_QiZi_Loc * 11.5 + 2
  Add Object Protected Line13 As _LineX With Left = Size_QiZi_Loc * 12.5 + 2
  Add Object Protected Line14 As _LineX With Left = Size_QiZi_Loc * 13.5 + 2
  Add Object Protected Line15 As _LineX With Left = Size_QiZi_Loc * 14.5 + 2
  Add Object Protected Line16 As _LineY With Top  = Size_QiZi_Loc *  0.5 + 2
  Add Object Protected Line17 As _LineY With Top  = Size_QiZi_Loc *  1.5 + 2
  Add Object Protected Line18 As _LineY With Top  = Size_QiZi_Loc *  2.5 + 2
  Add Object Protected Line19 As _LineY With Top  = Size_QiZi_Loc *  3.5 + 2
  Add Object Protected Line20 As _LineY With Top  = Size_QiZi_Loc *  4.5 + 2
  Add Object Protected Line21 As _LineY With Top  = Size_QiZi_Loc *  5.5 + 2
  Add Object Protected Line22 As _LineY With Top  = Size_QiZi_Loc *  6.5 + 2
  Add Object Protected Line23 As _LineY With Top  = Size_QiZi_Loc *  7.5 + 2
  Add Object Protected Line24 As _LineY With Top  = Size_QiZi_Loc *  8.5 + 2
  Add Object Protected Line25 As _LineY With Top  = Size_QiZi_Loc *  9.5 + 2
  Add Object Protected Line26 As _LineY With Top  = Size_QiZi_Loc * 10.5 + 2
  Add Object Protected Line27 As _LineY With Top  = Size_QiZi_Loc * 11.5 + 2
  Add Object Protected Line28 As _LineY With Top  = Size_QiZi_Loc * 12.5 + 2
  Add Object Protected Line29 As _LineY With Top  = Size_QiZi_Loc * 13.5 + 2
  Add Object Protected Line30 As _LineY With Top  = Size_QiZi_Loc * 14.5 + 2
  && 以下是棋盘中的五个点
  Add Object Protected Line31 As _Line  With BorderWidth = 8,Height = 0,Width = 0,;
      Top = Size_QiZi_Loc *  3.5 + 2,left = Size_QiZi_Loc *  3.5 + 2
  Add Object Protected Line32 As _Line  With BorderWidth = 8,Height = 0,Width = 0,;
      Top = Size_QiZi_Loc *  3.5 + 2,left = Size_QiZi_Loc * 11.5 + 2
  Add Object Protected Line33 As _Line  With BorderWidth = 8,Height = 0,Width = 0,;
      Top = Size_QiZi_Loc *  7.5 + 2,left = Size_QiZi_Loc *  7.5 + 2
  Add Object Protected Line34 As _Line  With BorderWidth = 8,Height = 0,Width = 0,;
      Top = Size_QiZi_Loc * 11.5 + 2,left = Size_QiZi_Loc *  3.5 + 2
  Add Object Protected Line35 As _Line  With BorderWidth = 8,Height = 0,Width = 0,;
      Top = Size_QiZi_Loc * 11.5 + 2,left = Size_QiZi_Loc * 11.5 + 2
  && 以下是棋盘中用于标识光标的热点对象
  Add Object Hover As _Hover
  Procedure Init
    This.AddProperty("QiZiCount[255]",.Null.) && 此属性用于保存棋盘中所下的棋子,因为动态添加的棋
                                              && 子在清盘时要清掉,所以用此属性保存对它们的引用.

    DoDefault()
  EndProc
  Procedure MouseMove
  LParameters nButton,nShift,nXCoord,nYCoord
    && 鼠标移动时同步移动热点
    This.Hover.Left = Int((nXCoord-2) / Size_QiZi_Loc) * Size_QiZi_Loc + 2
    This.Hover.Top =  Int((nYCoord-2) / Size_QiZi_Loc) * Size_QiZi_Loc + 2
  EndProc
  Procedure MouseUp
  LParameters nButton,nShift,nXCoord,nYCoord
  EndProc
  Procedure Go &&落子
  && 落子方法的参数说明:
  && nTop 落子与棋盘上方的距离
  && nLeft 落子与棋盘左边的距离
  && nX 从左向右第几列(1---15)
  && nY 从上向下第几行(1---15)

  LParameters nTop,nLeft,nX,nY
    If This.Start = .F. && 这一局已经结束
      If MessageBox(ReSatrt_Loc,4,Renju_Loc) = 6
        This.ReNew()
      EndIf
      Return
    EndIf
    If At(Chr(nX * 16 + nY),This.GoLog) > 0 && 有棋子的地方不能落子
      MessageBox(MsgTest_Loc,0,Renju_Loc)
      Return 
    EndIf
    Local lnQiZiID
    lnQiZiID = Len(This.GoLog)+1 && GoLog 中保存的是行棋的记录
    && 先画一个棋子

    This.AddObject("o_"+Alltrim(Str(lnQiZiID)),;
                   Iif(Mod(Len(This.GoLog),2) = 0,"_B","_W"))
    This.QiZiCount[lnQiZiID] = ;
            Evaluate("This.o_" + Alltrim(Str(lnQiZiID)))
    This.QiZiCount[lnQiZiID].Top = nTop
    This.QiZiCount[lnQiZiID].Left = nLeft
    This.QiZiCount[lnQiZiID].Visible = .T.
    && 更新行棋记录
    This.GoLog = This.GoLog + Chr(nX * 16 + nY)
    If IsVictory(This.GoLog)
      MessageBox(Iif(Mod(Len(This.GoLog),2) = 1,Black_Loc,White_Loc) + Victory_Loc,0,Renju_Loc)
      This.Start = .F.
    Else
      && /////////////////////////////////////////////////////////////
      && 若该电脑走,则调用博弈算法
      && 请在此调用自已的博弈算法,并再调用此程序段下棋.
      && /////////////////////////////////////////////////////////////

    EndIf
  EndProc
  Procedure ReNew && 清盘
    Local lnQiZiID
    lnQiZiID = 1
    Do While Not(IsNull(This.QiZiCount[lnQiZiID]))
      This.RemoveObject(This.QiZiCount[lnQiZiID].Name)
      This.QiZiCount[lnQiZiID] = .Null.
      lnQiZiID = lnQiZiID + 1
    EndDo
    This.GoLog = ""
    This.Start = .T.
  EndProc
  Procedure SaveLog && 棋局存盘
  EndProc
  Procedure LoadLog && 读存盘文件
  EndProc
EndDefine
*==========竖线定义
Define Class _LineX As _Line
  Height = Size_QiZi_Loc * (Total_Line_Loc - 1)+1
  Width = 0
  Top = Size_QiZi_Loc * 0.5+2
EndDefine
*==========横线定义
Define Class _LineY As _Line
  Width = Size_QiZi_Loc * (Total_Line_Loc - 1)+1
  Height = 0
  Left = Size_QiZi_Loc * 0.5+2
EndDefine
*==========黑棋子定义
Define Class _B As _ConTainer
  Add Object Protected Shape1 As Shape With ;
      Curvature=99,FillStyle=0,Top = 1,Left = 1,;
      Height = Size_QiZi_Loc - 2,Width = Size_QiZi_Loc - 2
EndDefine
*==========白棋子定义
Define Class _W As _ConTainer
  Add Object Protected Shape1 As Shape With ;
      Curvature=99,FillStyle=0,Top = 1,Left = 1,;
      Height = Size_QiZi_Loc - 2,Width = Size_QiZi_Loc - 2,;
      BorderColor=RGB(192,192,192),FillColor=RGB(255,255,255)
EndDefine
*==========热点定义
Define Class _Hover As _Container
  X = 0
  Y = 0
  Add Object Protected Line1 As _LineHover With Width = 0,Height = Size_QiZi_Loc / 4,;
      Left = 0,Top = 0
  Add Object Protected Line2 As _LineHover With Height = 0,Width = Size_QiZi_Loc / 4,;
      Top = 0,Left = 0
  Add Object Protected Line3 As _LineHover With Width = 0,Height = Size_QiZi_Loc / 4,;
      Left = 0,Top = Size_QiZi_Loc / 4 * 3 + 1
  Add Object Protected Line4 As _LineHover With Height = 0,Width = Size_QiZi_Loc / 4,;
      Top = 0,Left = Size_QiZi_Loc / 4 * 3 + 1
  Add Object Protected Line5 As _LineHover With Width = 0,Height = Size_QiZi_Loc / 4,;
      Left = Size_QiZi_Loc - 1,Top = 0
  Add Object Protected Line6 As _LineHover With Height = 0,Width = Size_QiZi_Loc / 4,;
      Top = Size_QiZi_Loc - 1,Left = 0
  Add Object Protected Line7 As _LineHover With Width = 0,Height = Size_QiZi_Loc / 4,;
      Left = Size_QiZi_Loc - 1,Top = Size_QiZi_Loc / 4 * 3 + 1
  Add Object Protected Line8 As _LineHover With Height = 0,Width = Size_QiZi_Loc / 4,;
      Top = Size_QiZi_Loc - 1,Left = Size_QiZi_Loc / 4 * 3 + 1
  Procedure Click
    This.Parent.Go(This.Top,This.Left,This.X,This.Y) && 落子----由棋盘完成
  EndProc
  Procedure Left_Assign
  LParameters vNewVal
    This.Left = vNewVal
    This.X = Int((This.Left - 2) / Size_QiZi_Loc) + 1
  EndProc
  Procedure Top_Assign
  LParameters vNewVal
    This.Top = vNewVal
    This.Y = Int((This.Top - 2) / Size_QiZi_Loc) + 1
  EndProc
  && 定义下面的四个方法是为了支持键盘操作
  Procedure MoveUp && 上移
    If This.Y > 1
      This.Top = This.Top - Size_QiZi_Loc
    EndIf
  EndProc
  Procedure MoveDown && 下移
    If This.Y < Total_Line_Loc
This.Top = This.Top + Size_QiZi_Loc
EndIf
EndProc
Procedure MoveLeft && 左移
    If This.X > 1
      This.Left = This.Left - Size_QiZi_Loc
    EndIf
  EndProc
  Procedure MoveRight && 右移
    If This.X < Total_Line_Loc
This.Left = This.Left + Size_QiZi_Loc
EndIf
EndProc
EndDefine
*==========热点标识线条
Define Class _LineHover As _Line
  BorderColor = RGB(0,0,255)
EndDefine
*==========容器基类
Define Class _Container As Container
  BackStyle = 0
  BorderWidth = 0
  Height = Size_QiZi_Loc
  Width = Size_QiZi_Loc
EndDefine
*==========线条基类
Define Class _Line As Line
  Procedure MouseMove && 不处理事件,全部传到容器中进行处理,但要重算坐标
  LParameters nButton,nShift,nXCoord,nYCoord
    This.Parent.MouseMove(nButton,nShift,nXCoord,nYCoord)
  EndProc
  Procedure MouseDown
  LParameters nButton,nShift,nXCoord,nYCoord
    This.Parent.MouseDown(nButton,nShift,nXCoord,nYCoord)
  EndProc
  Procedure MouseUp
  LParameters nButton,nShift,nXCoord,nYCoord
    This.Parent.MouseUp(nButton,nShift,nXCoord,nYCoord)
  EndProc
  Procedure Click
    This.Parent.Click
  EndProc
  Procedure DblClick
    This.Parent.DblClick
  EndProc
EndDefine
*====================================================================================
Function IsVictory(GoLog) && 判断最后落子者是否构成五连
  Local laGo[Total_Line_Loc,Total_Line_Loc] && 这是一张棋盘
  Local n,lcEveryOne,lnX,lnY
  && 生成棋盘
  For n = Len(GoLog) To 1 Step -2 && 这张棋盘只需记录一种棋子即可
    lcEveryOne = Subst(GoLog,n,1)
    lnX = Int(Asc(lcEveryOne) / 16)
    lnY = Mod(Asc(lcEveryOne),16)
    laGo[lnX,lnY] = .T.
  EndFor
  Release n,lcEveryOne

  lnX = Int(Asc(Right(GoLog,1)) / 16) && 最后落点 ,值为 1 ~ Total_Line_Loc
  lnY = Mod(Asc(Right(GoLog,1)),16)

  Local X,Y,Z && 是否在四个方向之一构成五连----构成五连则胜出
  For X = Max(lnX - 4,1) To Min(lnX,Total_Line_Loc - 4) && Y 轴不变
    If laGo[X,lnY] And ;
       laGo[X + 1,lnY] And ;
       laGo[X + 2,lnY] And ;
       laGo[X + 3,lnY] And ;
       laGo[X + 4,lnY]
      Return .T.
    EndIf
  EndFor
  For Y = Max(lnY - 4,1) To Min(lnY,Total_Line_Loc - 4) && X 轴不变
    If laGo[lnX,Y] And ;
       laGo[lnX,Y + 1] And ;
       laGo[lnX,Y + 2] And ;
       laGo[lnX,Y + 3] And ;
       laGo[lnX,Y + 4]
      Return .T.
    EndIf
  EndFor
  For Z = 4 + Max(lnX,lnY) - Total_Line_Loc To Min(lnX - 1,lnY - 1,4) && XY 轴同步改变
    If laGo[lnX - Z,lnY - Z] And ;
       laGo[lnX - Z + 1,lnY - Z + 1] And ;
       laGo[lnX - Z + 2,lnY - Z + 2] And ;
       laGo[lnX - Z + 3,lnY - Z + 3] And ;
       laGo[lnX - Z + 4,lnY - Z + 4]
      Return .T.
    EndIf
  EndFor
  For Z = Max(0,lnX + 4 - Total_Line_Loc,4 - lnY) ;
          To Min(4,lnX - 1,Total_Line_Loc - lnY) && X 轴增加 Y 轴减少
    If laGo[lnX - Z,lnY + Z] And ;
       laGo[lnX - Z + 1,lnY + Z - 1] And ;
       laGo[lnX - Z + 2,lnY + Z - 2] And ;
       laGo[lnX - Z + 3,lnY + Z - 3] And ;
       laGo[lnX - Z + 4,lnY + Z - 4]
      Return .T.
    EndIf
  EndFor
  Return .F.
EndFunc



----
在代码天地里
我要做一个
猎狐者    

[关闭][返回]