五子棋游戏程序(一.内核部分)

这个程序是学Win32编程到GDI部分的产物,因为是纯粹用GDI写的,所以效率很一般,所幸这种棋类程序也不需要太多的图形性能. 程序分2部分,一个内核部分,一个图形界面部分. 对于五子棋来说,内核当然就要能正确的判断当前棋盘上的情况,要能知道一步棋走下去,是不是会产生输赢结果,图形接口则是提供完整的棋盘界面给用户交互.当然也担当着输入输出的任务.

下面这个是内核部分,我把他用dll库来实现,这样以后扩充别的会很方便.

//=================================================================================
//Name:  Base.h
//Funcation: Base Type Define,CPU support,MyUnicode Support.
//Author: kakashi.R
//Last Update: 6.1.2005
//================================================================================= 


#ifndef _BASE_H
#define _BASE_H

#define  TRUE  1
#define  FALSE  0
#define  SUCCESS  1
#define  FAILURE  0
#define  ENABLE  1
#define  DISABLE  0
#define  HIGH  1
#define  LOW  0
#define  USED  1
#define  UNUSE  0
#define  NULL  0

#pragma message("")
#pragma message("This is A Header File Created by kakashir. :)")
#pragma message("")

#if (defined _IOSTREAM)   //Incude iostream.h for I/O.
#pragma message("")
#pragma message("Macro _IOSTREAM actived Now.")
#pragma message("Now iostream.h included for I/O.")
#pragma message("")
#include <iostream.h>
#endif  //#if (defined _IOSTREAM)


#if ( !(defined APIENTRY) && (defined _STDAPI) ) //__stdcall style support.
#pragma message("")
#pragma message("Macro _STDAPI actived Now.")
#pragma message("Funcations call style KeyWord APIENTRY Defined as __stdcall.")
#pragma message("")
#define  APIENTRY   __stdcall   
#define  CENTRY    __cdecl    
#define  API    APIENTRY   
#define  PASCAL    API    
#define  CALLBACK   PASCAL    
#endif  //#if ( !(defined APIENTRY) && (defined _STDAPI) )

#ifdef _I386   //Intel 80386 and later CPU support and typedefs.
#pragma message("")
#pragma message("Macro _I386 actived NOW.")
#pragma message("Data define Keywords defined for Intel 80386 and later Processer Family.")
#pragma message("")

#if !(defined _UNICODE)
typedef  char    CHAR;
typedef  CHAR    TCHAR;
#endif  //#if !(defined _UNICODE )

typedef  __int8    BYTE;
typedef  __int16    WORD;
typedef  __int32    DWORD;
typedef  __int64    QWORD;
typedef  float    FLOAT;
typedef  double    DOUBLE;

typedef  unsigned __int8  UBYTE;
typedef  unsigned __int16  UWORD;
typedef  unsigned __int32  UDWORD;
typedef  unsigned __int64  UQWORD;

typedef  void*    LPVOID;
typedef  WORD*    LPWORD;
typedef  BYTE*    LPBYTE;
typedef  DWORD*    LPDWORD;
typedef  QWORD*    LPQWORD;
typedef  FLOAT*    LPFLOAT;
typedef  DOUBLE*    LPDOUBLE;

typedef  UBYTE*    LPUBYTE;
typedef  UWORD*    LPUWORD;
typedef  UDWORD*    LPUDWORD;
typedef  UQWORD*    LPUQWORD;
    
typedef  bool    BOOL;
typedef  void    VOID;

typedef union ___uint128     //128bit unsigned data support.
{
 unsigned __int64  __128[2];
 unsigned __int32  __32[4];
 unsigned __int16  __16[8];
 unsigned __int8   __8[16];
}uint128;

typedef union ___sint128    //128bit signed data support.
{
 signed __int64  __128[2];
 signed __int32  __32[4];
 signed __int16  __16[8];
 signed __int8  __8[16];
}sint128;

typedef  UBYTE    U8;
typedef  short unsigned  U16;
typedef  long unsigned  U32;
typedef  UQWORD    U64;
typedef  uint128    U128;

typedef  BYTE    S8;
typedef  short signed   S16;
typedef  long signed   S32;
typedef  QWORD    S64;
typedef  sint128    S128;
#endif  //#ifdef  _I386


#if (defined _UNICODE && defined _I386)  // MyUNICODE support!! :)
#pragma message("")
#pragma message("Macro _UNICODE actived NOW.")
#pragma message("The Keyword CHAR(upcase) defined 16bit for support UNICODE now.")
#pragma message("Pleas use cout() to display UNICODE char or String.")
#pragma message("use __char to define Old ANSCII-Style Character :)")
#pragma message("")

typedef char __char;

typedef union ___wchar   //Define MyUNICODE struct.

 U16 Unicode16;
 U8 Unicode8[2];
}__wchar;

typedef   __wchar CHAR;

#include <UnicodeTable.h>  //include MyUNICODE Table :)
#define __IOSTREAM
#include <iostream.h>

#if (defined _IOSTREAM)

void APIENTRY _cout(CHAR Word)  //MyUnicode I/O Funcation for character Display
{
 if(Word.Unicode8[1] == 0)
  {
   cout<<(__char)Word.Unicode8[0]<<flush;
  }
 else
  {
   if(Word.Unicode8[1] >=0 && Word.Unicode8[1] <= HIGH_WORD_MAX &&
      Word.Unicode8[0] >=0 && Word.Unicode8[0] <= LOW_WORD_MAX)
    {
     _Buffer[0] = *(UnicodeTable[(Word.Unicode8[1]-1)] +   (2*Word.Unicode8[0])   );
     _Buffer[1] = *(UnicodeTable[(Word.Unicode8[1]-1)] +   (2*Word.Unicode8[0])+1 );
     _Buffer[2] = '/0';
     cout<<_Buffer<<flush;
    }
  }
 
}
void APIENTRY _cout(CHAR* Word)  //MyUnicode I/O Funcation for String display
{
 U32 Length = sizeof(Word)/2;
 U32 Tmp_a=0;
 for(Tmp_a=0;Tmp_a<Length;Tmp_a++)
  {
   if((Word+Tmp_a)->Unicode8[1] == 0)
    {
     cout<<(__char)( (Word+Tmp_a)->Unicode8[0])<<flush;
    }
   else if ( ((Word+Tmp_a)->Unicode8[1]) >=0 && ((Word+Tmp_a)->Unicode8[1]) <= HIGH_WORD_MAX &&
             ((Word+Tmp_a)->Unicode8[0]) >=0 && ((Word+Tmp_a)->Unicode8[0]) <= LOW_WORD_MAX )
     {
      _Buffer[0] = *(UnicodeTable[ ( (Word+Tmp_a)->Unicode8[1] )-1 ] + 2*( (Word+Tmp_a)->Unicode8[0] )  );
      _Buffer[1] = *(UnicodeTable[ ( (Word+Tmp_a)->Unicode8[1] )-1 ] + 2*( (Word+Tmp_a)->Unicode8[0] )+1);
      _Buffer[2] = '/0';
      cout<<_Buffer<<flush;     
     }
  }
}
#define  lpUnicode(var,value)  ((var)->Unicode16) = value
#define  Unicode(var,value)  ((var).Unicode16)  = value
#define  cout(UnicodeString)  _cout(UnicodeString) 

#endif  //#if (defined _IOSTREAM) 

#endif //#if (define __UNICODE)

#endif   //#ifndef _BASE_H

=ChesManDefine.h===============================================================================

#ifndef _CHESMAN_H
#define _CHESMAN_H

#define  _I386
#define  _STDCALL
#define  _IOSTREAM
#include "./Header/Base.h"


#define  MAX_X  20
#define  MAX_Y  20
#define  NO_CHESSMAN  0
#define  WHITE_CHESSMAN  1
#define  BLACK_CHESSMAN  2
#define  BLACK_WIN  3
#define  WHITE_WIN  4
#define  NEXTONE   5

typedef struct _str_ChessManPos
{
 DWORD X;
 DWORD Y;
}str_ChessManPos; 

VOID Replace();
DWORD CheckIsWin(__int8 *lpChess); 

#endif //#ifndef _CHESMAN_H

================================================================================

#include "./Header/ChesManDefine.h"

str_ChessManPos  str_WinPos[5]; //保存嬴方的棋路

DWORD gPosX,gPosY;   //暂时存储当前棋路
BOOL IsLastCheckedBlack=FALSE;   //上个棋子是否是黑棋
BOOL IsLastCheckedWhite=FALSE;  // 上个棋子是否是白棋
BOOL IsCheckedBlack=FALSE;  //当前棋子是否是黑棋
BOOL IsCheckedWhite=FALSE;    //当前棋子是否是白棋

BYTE Counter=0;

DWORD DetectIsWin();
VOID RecordPos(DWORD _PosX,DWORD _PosY);
VOID RecordWinPos();

DWORD CheckIsWin(__int8 *lpChess)
{

 WORD cPosX=1,cPosY=1,cPos=1,cPosEnd=0;
//Scan Part:
 for(cPosY=1;cPosY<=MAX_Y;cPosY++)   //Scan All rows. Swap two for,it'll scan all cols
  {
   for(cPosX=1;cPosX<=MAX_X;cPosX++)
    {
     if (lpChess[20*(cPosY-1)+(cPosX-1)] ==NO_CHESSMAN )
      {
       Counter=0;
       IsLastCheckedBlack=FALSE;
       IsLastCheckedWhite=FALSE;
       continue;
      }
     if (lpChess[20*(cPosY-1)+(cPosX-1)] == BLACK_CHESSMAN )
      { 

       IsCheckedBlack = TRUE;
       IsCheckedWhite = FALSE;
       RecordPos(cPosX,cPosY);
       if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
       continue;
      }
     if (lpChess[20*(cPosY-1)+(cPosX-1)]== WHITE_CHESSMAN )
      {
       IsCheckedWhite = TRUE;
       IsCheckedBlack = FALSE;
       RecordPos(cPosX,cPosY);
       if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
       continue;
      }
    }
   Replace();
  }

 
 
 for(cPosX=1;cPosX<=MAX_Y;cPosX++)   //Scan all cols
  {
   for(cPosY=1;cPosY<=MAX_X;cPosY++)
    {
     if (lpChess[20*(cPosY-1)+(cPosX-1)] ==NO_CHESSMAN )
      {
       Counter=0;
       IsLastCheckedBlack=FALSE;
       IsLastCheckedWhite=FALSE;
       continue;
      }
     if (lpChess[20*(cPosY-1)+(cPosX-1)] == BLACK_CHESSMAN )
      { 
       IsCheckedBlack = TRUE;
       IsCheckedWhite = FALSE;
       RecordPos(cPosX,cPosY);
       if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
       continue;
      }
     if (lpChess[20*(cPosY-1)+(cPosX-1)]== WHITE_CHESSMAN )
      {
       IsCheckedWhite = TRUE;
       IsCheckedBlack = FALSE;
       RecordPos(cPosX,cPosY);
       if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
       continue;
      }
    }
   Replace();
  }

 for(cPos=1;cPos<=MAX_X;cPos++)   //Scan Left Diagonal Line
  {
   if (lpChess[20*(cPos-1)+(cPos-1)] == NO_CHESSMAN )
    {
     Counter=0;
     IsLastCheckedBlack=FALSE;
     IsLastCheckedWhite=FALSE;
     continue;
    }
   if (lpChess[20*(cPos-1)+(cPos-1)] == BLACK_CHESSMAN )
    { 
     IsCheckedBlack = TRUE;
     IsCheckedWhite = FALSE;
     RecordPos(cPos,cPos);
     if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
     continue;
    }
   if (lpChess[20*(cPos-1)+(cPos-1)]== WHITE_CHESSMAN )
    {
     IsCheckedWhite = TRUE;
     IsCheckedBlack = FALSE;
     RecordPos(cPos,cPos);
     if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
     continue;
    }
  }
 Replace();
 
 for(cPos=1;cPos<=MAX_X;cPos++)   //Scan Right Diagonal Line (Roatate the Matrix)
  {
   if (lpChess[20*(cPos-1)+(MAX_X-(cPos-1)-1)] == NO_CHESSMAN )
    {
     Counter=0;
     IsLastCheckedBlack=FALSE;
     IsLastCheckedWhite=FALSE;
     continue;
    }
   if (lpChess[20*(cPos-1)+(MAX_X-(cPos-1)-1)] == BLACK_CHESSMAN )
    { 
     IsCheckedBlack = TRUE;
     IsCheckedWhite = FALSE;
     RecordPos((MAX_X-(cPos-1)),cPos);
     if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
     continue;
    }
   if (lpChess[20*(cPos-1)+(MAX_X-(cPos-1)-1)]== WHITE_CHESSMAN )
    {
     IsCheckedWhite = TRUE;
     IsCheckedBlack = FALSE;
     RecordPos((MAX_X-(cPos-1)),cPos);
     if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
     continue;
    }
  }
 Replace();
 
 cPosX=0;
 for(cPos=1;cPos<=MAX_X-1;cPos++)  //Scan Left Diagnoal RightUp Parts
  {
   
   _asm push cPos; 
   cPosEnd = cPos;
   for(cPos=1;cPos<=MAX_X-cPosEnd;cPos++)
    {
     if (lpChess[20*(cPos-1)+(cPos+cPosX)] == NO_CHESSMAN )
      {
       Counter=0;
       IsLastCheckedBlack=FALSE;
       IsLastCheckedWhite=FALSE;
       continue;
      }
     if (lpChess[20*(cPos-1)+(cPos+cPosX)] == BLACK_CHESSMAN )
      { 
       IsCheckedBlack = TRUE;
       IsCheckedWhite = FALSE;
       RecordPos((cPos+cPosX+1),cPos);
       if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
       continue;
      }
     if (lpChess[20*(cPos-1)+(cPos+cPosX)] == WHITE_CHESSMAN )
      {
       IsCheckedWhite = TRUE;
       IsCheckedBlack = FALSE;
       RecordPos((cPos+cPosX+1),cPos);
       if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
       continue;
      }
    }
   Replace();
   cPosX++;
   _asm pop cPos;
   
 }
 Replace();
 
 cPosX=0;
 for(cPos=1;cPos<=MAX_X;cPos++)  //Scan Left Diagnoal LeftDown Parts
  {
   
   _asm push cPos; 
   for(cPos;cPos<=MAX_X;cPos++)
    {
     if (lpChess[20*(cPos)+(cPosX)] == NO_CHESSMAN )
      {
       Counter=0;
       IsLastCheckedBlack=FALSE;
       IsLastCheckedWhite=FALSE;
       cPosX++;
       continue;
      }
     if (lpChess[20*(cPos)+(cPosX)] == BLACK_CHESSMAN )
      { 
       IsCheckedBlack = TRUE;
       IsCheckedWhite = FALSE;
       RecordPos((cPosX+1),(cPos+1));
       if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
       cPosX++;
       continue;
      }
     if (lpChess[20*(cPos)+(cPosX)] == WHITE_CHESSMAN )
      {
       IsCheckedWhite = TRUE;
       IsCheckedBlack = FALSE;
       RecordPos((cPosX+1),(cPos+1));
       if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
       cPosX++;
       continue;
      }
    }
   Replace();
   cPosX=0;
   _asm pop cPos;
  }
 Replace();

 cPosX=0;
 for(cPos=1;cPos<=MAX_X-1;cPos++)  //Scan Right-Diagnoal RightDown Parts (Roatate the Matrix)
  {
   
   _asm push cPos; 
   cPosEnd = cPos;
   for(cPos=1;cPos<=MAX_X-cPosEnd;cPos++)
    {
     if (lpChess[20*(cPos+cPosX)+MAX_X-cPos] == NO_CHESSMAN )
      {
       Counter=0;
       IsLastCheckedBlack=FALSE;
       IsLastCheckedWhite=FALSE;
       continue;
      }
     if (lpChess[20*(cPos+cPosX)+MAX_X-cPos] == BLACK_CHESSMAN )
      { 
       IsCheckedBlack = TRUE;
       IsCheckedWhite = FALSE;
       RecordPos((MAX_X-cPos+1),(cPos+cPosX+1));
       if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
       continue;
      }
     if (lpChess[20*(cPos+cPosX)+MAX_X-cPos] == WHITE_CHESSMAN )
      {
       IsCheckedWhite = TRUE;
       IsCheckedBlack = FALSE;
       RecordPos((MAX_X-cPos+1),(cPos+cPosX+1));
       if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
       continue;
      }
    }
   Replace();
   cPosX++;
   _asm pop cPos;
   
 }
 Replace();


 cPosX=0;
 for(cPos=1;cPos<=MAX_X;cPos++)  //Scan Right-Diagnoal LeftUp Parts (Roatate the Matrix)
  {
   
   _asm push cPos; 
   for(cPos;cPos<=MAX_X;cPos++)
    {
     if (lpChess[20*(cPosX)+(MAX_X-cPos-1)] == NO_CHESSMAN )
      {
       Counter=0;
       IsLastCheckedBlack=FALSE;
       IsLastCheckedWhite=FALSE;
       cPosX++;
       continue;
      }
     if (lpChess[20*(cPosX)+(MAX_X-cPos-1)] == BLACK_CHESSMAN )
      { 
       IsCheckedBlack = TRUE;
       IsCheckedWhite = FALSE;
       RecordPos((MAX_X-cPos),(cPosX+1));
       if(DetectIsWin()==BLACK_WIN){return BLACK_WIN;}
       cPosX++;
       continue;
      }
     if (lpChess[20*(cPosX)+(MAX_X-cPos-1)] == WHITE_CHESSMAN )
      {
       IsCheckedWhite = TRUE;
       IsCheckedBlack = FALSE;
       RecordPos((MAX_X-cPos),(cPosX+1));
       if(DetectIsWin()==WHITE_WIN){return WHITE_WIN;}
       cPosX++;
       continue;
      }
    }
   Replace();
   cPosX=0;
   _asm pop cPos;
  }
 Replace();


 return FAILURE;

VOID Replace()  //重置函数 当一行检测完时,用来重置记录变量
{
 IsLastCheckedBlack=FALSE;
 IsLastCheckedWhite=FALSE;
 IsCheckedBlack=FALSE;
 IsCheckedWhite=FALSE;
 Counter=0; 
}


VOID RecordPos(DWORD _PosX,DWORD _PosY)  //记录当前棋路
{
 gPosX=_PosX;
 gPosY=_PosY;
}

VOID RecordWinPos()  //记录胜利方的棋路
{
 str_WinPos[Counter].X = gPosX;
 str_WinPos[Counter].Y = gPosY;
}


DWORD DetectIsWin()   //判断是否胜利
{
 
 if ( (IsLastCheckedBlack==TRUE) && (IsCheckedBlack==TRUE) )
  {
   RecordWinPos(); 
   Counter++;
  }
 if ( (IsLastCheckedWhite==TRUE) && (IsCheckedWhite==TRUE) )
  {
   RecordWinPos();
   Counter++;
  }

 if ( (IsLastCheckedBlack==FALSE) && (IsCheckedBlack==TRUE))
  {
   Counter=0;
   RecordWinPos();
   IsLastCheckedBlack=TRUE;
   IsLastCheckedWhite=FALSE;
   Counter=1;
  }
 if ( (IsLastCheckedWhite==FALSE) && (IsCheckedWhite==TRUE))
  {
   Counter=0;
   RecordWinPos();
   IsLastCheckedWhite=TRUE;
   IsLastCheckedBlack=FALSE;
   Counter=1;
  }

 if (Counter>=5)
  {
   if(IsCheckedBlack)
    {
     Counter=0;
     return BLACK_WIN;
    }
   if(IsCheckedWhite)
    {
     Counter=0;
     return WHITE_WIN;
    }
  }
 return NEXTONE;
}

这个是内核部分了,其实内核的思路很简单,我们知道,棋盘可以用2维数组来模拟,再这个内核中,我用了20*20大小的数组来模拟20行20列的棋盘.棋盘上的每个位置只会有3种状态:无棋子,黑色棋子,白色棋子.这样只要在每下一步后,检索整个数组就可以了。对于五子棋,当行,列,对角线的平行线集合上某个颜色的棋子连续达到5个时,就算赢.按这个算法.,可以写出内核.先扫描行,再是列,然后是对角线.注意对角线似乎是难一些的部分,其实只要写好一个方向的算法,然后把整个数组向右旋转90度就可以了。这点大家看看程序就明白了

测试了下,发现有BUG,当黑棋斜着下时,会报非法错误。仔细DEBUG后,是内联asm的问题。偶为了省事(其实就是懒),把循环体中的变量push保存了,按道理循环完毕后有对应的pop来恢复堆栈指针,但是在循环体中,在作条件检测,满足的话就会跳出这个函数,这样,堆栈指针就不会正常,而是有4字节的偏移量。导致在恢复esi时出错。这个错误在console下调试时不容易看出来,但是在做为dll时,就会明显出错。偶也灭改上面的代码,都说到这里了,有兴趣的朋友自己改改吧 :)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值