程序设计课程设计五子棋实验报告(附代码)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文档编号:项目名称–版本
程序设计课程设计
五子棋游戏程序
报告书
制订人:张三
学号:************
2010年7月6日
文档变更历史记录
目录
目录 (3)
1、引言 (4)
1.1 编写目的 (4)
1.2 读者对象 (4)
1.3 软件项目概述 (4)
1.4 文档概述 (4)
1.5 定义 (5)
1.6 参考资料 (5)
2、任务概述 (5)
2.1目标 (5)
2.2软件的开发和运行环境 (5)
2.3 用户特征 (5)
2.4 假设与约束 (5)
2.5 进度要求 (5)
2.6验收要求 (5)
3、功能需求描述 (6)
3.1 基本功能.............................................................................................错误!未定义书签。
3.2 增加功能.............................................................................................错误!未定义书签。
4、界面要求 (6)
5、测试方案 (6)
6、功能设计 (10)
6.1类的关系描述 (10)
6.2类的设计 (11)
7、使用指南 (11)
8、维护接口 (11)
9、总结 (12)
1、引言
1.1 编写目的
学会MFC的一些基本操作,会使用其中的部分函数,编写一个五子连珠的小游戏,游戏由两人对弈,用鼠标操作,执黑子者先下。
1.2 读者对象
计算机专业的学生或对编程感兴趣的学生
1.3 软件项目概述
●项目名称:五子棋游戏
●简称:五子棋
●项目代号:无
●软件项目的大致功能和性能要求
可实现两人对弈,用鼠标操作,黑子先下。
要求:
1.设计一个五子连珠类;
2.记录游戏双方的落子过程,允许悔棋;
3.实现保存棋谱和根据棋谱复盘的功能;
4.判断双方输赢,先走出五子连珠的一方赢;
5.响应用户鼠标信息,并显示棋盘信息;
6.判断先下者落子禁手情况。
1.4 文档概述
将五子棋程序以文字的形式表达,包括设计思路、具体方法、具体实现、框架结构,使别人能够理解。
1.5 定义
1.6参考资料
《深入浅出MFC》
《Visual C++6.0 类参考详解》刘金龙高兆法巩玉国编
《程序设计课程设计》计算机学院编
2、任务概述
2.1目标
可实现两人对弈,用鼠标操作,黑子先下。
2.2软件的开发和运行环境
系统:Windows XP or Windows7
软件:VC 6.0
2.3 用户特征
双人对弈,熟悉游戏规则的任何用户
2.4 假设与约束
游戏中可能含有比较多的禁手规则使得先下的一方比较难以取得胜利2.5 进度要求
按期完成用户需求
2.6验收要求
各项功能如:新局、保存棋局、打开棋局、悔棋、禁手、判断胜利等功能都能实现
3、功能需求描述
可实现两人对弈,用鼠标操作,黑子先下。
要求:
1.设计一个五子连珠类;
2.记录游戏双方的落子过程,允许悔棋;
3.实现保存棋谱和根据棋谱复盘的功能;
4.判断双方输赢,先走出五子连珠的一方赢;
5.响应用户鼠标信息,并显示棋盘信息;
6.判断先下者落子禁手情况。
4、界面要求
人机界面要容易操作,有比较舒适的背景,遇到禁手、悔棋、保存、胜利等可弹出对话框。
人机交互和谐。
5、测试方案
1.检验判断胜利:
若胜利,则弹出对话框,并显示是何种胜利2.检验禁手
以上仅列出六种禁手,当然还有跟多情况
3.检验保存
当按下“保存”图标菜单时,会弹出对话框,可给棋局取个文件名,如“1”然后单击“保存(S)”
4.检验打开
重现打开游戏,按下“打开”图标菜单,现在打开“1”
会显示对话框,选择要打开的文件“1”
单击“打开”,则会复盘,显示上次未完成的游戏,继续对弈
5.悔棋(有个撤销按钮,不便验收展示)
6.综上,基本实现新局、保存棋局、打开棋局、悔棋、禁手、判断胜利
6、功能设计6.1类的关系描述
6.2类的设计
成员变量:
int step: 在CWzqView中,存储步数
int dstep: 在CWzqDoc中,存储步数
int tag[19][19]: 在CWzqView中存储落子的信息,即每个棋子的step
int dtag[19][19]: 在CWzqDoc中存储落子的信息,即每个棋子的dstep
受保护一般成员函数:
Getstep:在CWzqView中获取步数step
Getdstep:在CWzqDoc中获取步数dstep
Gettag(int,int): 在CWzqView中获取tag
Getdtag(int,int): 在CWzqDoc中获取dtag
Getpiecepos(int): 在CWzqView中,可根据int(即step)来获得棋子的坐标,返回一个CPoint类型
重要操作函数:
Ondraw():重画棋盘
OnLButtenDown():落子
Forbid():禁手判断
Winner():输赢判断
OnWzqGoback():悔棋操作
OnWzqNewgame():重新开局
Transfer():在CWzqView与CWzqDoc之间实现信息共享,以便系统保存和复盘
Serialize():实现棋盘的保存和复盘
7、使用指南
双人对弈
8、维护接口
程序中定义了好多可改变的量,可根据需要改变:
#define static int Getarray[19][19] {0}
#define XPOS_TopLeft 125
#define YPOS_TopLeft 50
#define WIDTH_BoardGrid 32//小方格宽度
#define WIDTH_Point 6 //四个标志点的宽度
#define WIDTH_Piece 15//棋子宽度
#define COLOR_Brush RGB(158,90,65)//棋盘底色
#define COLOR_PieceBlack RGB(0,0,0)
#define COLOR_PieceWhite RGB(255,255,255)
#define COLOR_Pen RGB(255,0,0)
#define WIDTH_Pen 1.5
9、总结
我个人通过对五子棋小游戏的编写,增加了对编写程序的兴趣,尤其是利用C++,MFC,不禁惊叹于微软编程人员为我们提供了那么多可以直接使用的类资源。
期间,我通过查资料,与同学交流,学到了许多课堂上所没有的新知识,增强了我的自主学习能力。
有时,添加一个功能可能会改变好多东西,可能会报好多error,但只要自己坚持不懈,认真查找,或问同学,或请教老师,总会把问题解决。
编写此程序还需要我们有良好的程序素养,即书写习惯,添加注释,方便日后查看理解甚至修改。
期间,需要设置好多变量如tag[][]、step等,分别存储棋子的标志(即该棋子是第几步,若基数步则为黑棋,若偶数步则为白棋)和当前步数。
有一个GetpiecePos(int)函数,可根据int(实际是改点的step)来确定改点的坐标,返回一个point,即相当于知道该点(point.x,point.y),便于操作。
在存取时,需要在CWzqDoc里调用一个函数,但CWzqView
与CWzqDoc继承的不是同一个父类,因此,需用一个函数Transfer()来将CWzqView的参数信息如tag[][]、step传递到CWzqDoc中去。
要十分完善的编写这个程序的确有点困难,这要求我必须多花心思与精力,多与别人交流探讨,多查处自己程序的bug,最最重要的是自己一定要有耐心,努力去完成。
主要程序段:wzqView.cpp
// wzqView.cpp : implementation of the CWzqView class
//
#include "stdafx.h"
#include "wzq.h"
#include "wzqDoc.h"
#include "wzqView.h"
#include<fstream.h>
#include<string.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define static int Getarray[19][19] {0}
#define XPOS_TopLeft 125
#define YPOS_TopLeft 50
#define WIDTH_BoardGrid 32//小方格宽度
#define WIDTH_Point 6 //四个标志点的宽度
#define WIDTH_Piece 15//棋子宽度
#define COLOR_Brush RGB(158,90,65)//棋盘底色
#define COLOR_PieceBlack RGB(0,0,0)
#define COLOR_PieceWhite RGB(255,255,255)
#define COLOR_Pen RGB(255,0,0)
#define WIDTH_Pen 1.5
/////////////////////////////////////////////////////////////////////////// //
// CWzqView
IMPLEMENT_DYNCREATE(CWzqView, CView)
BEGIN_MESSAGE_MAP(CWzqView, CView)
//{{AFX_MSG_MAP(CWzqView)
ON_WM_LBUTTONDOWN()
ON_WM_CANCELMODE()
ON_COMMAND(ID_WZQ_GOBACK, OnWzqGoback)
ON_COMMAND(ID_WZQ_NEWGAME, OnWzqNewgame)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////// //
// CWzqView construction/destruction
CWzqView::CWzqView()
{
// TODO: add construction code here
step=0;
wintag=0;//初始化获胜标志位
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
tag[i][j]=0;//将标志位初始化,0表示(i,j)点无棋子
}
CWzqView::~CWzqView()
{
}
BOOL CWzqView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
int CWzqView::Getstep()
{
return step;//获取步数
}
//DEL void CWzqView::vSetstep(int n)
//DEL {
//DEL step=step+n;
//DEL }
int CWzqView::Gettag(int m,int n)
{
return tag[m][n];//获取标志符
}
void CWzqView::vSettag(CPoint piecePos,int t)
{
tag[piecePos.x][piecePos.y]=t;//设置该点的标识符
}
CPoint CWzqView::GetPiecePos(int num)
{
CPoint point;
if(num!=0)
{
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
if( (tag[i][j])==num)
{
point.x=i;
point.y=j;
}//假如tag位为num,找到tag位符合的点
}
return point;
}
//**********************************************************************
//
// CWzqView::vDrawPiece
//
// Purpose:
//
// draw a piece according to board point //
// Parameters:
//
// pointBoard ---- the board coordinate of piece to be drawn.
// nType ---- draw type of the piece: COLOR_PieceBlack COLOR_PieceWhite. // pDC ---- device context.
//
// Return Value:
//
// None
//
// Comments:
//
//********************************************************************** void CWzqView::vDrawPiece(CPoint pointBoard,int nType,CDC* pDC)
{
CRgn rgnPiece;
CPoint pointView = ptConvertBP2VP(pointBoard);
rgnPiece.CreateEllipticRgn( pointView.x - WIDTH_Piece,
pointView.y - WIDTH_Piece,
pointView.x + WIDTH_Piece,
pointView.y + WIDTH_Piece);
CBrush brush;
if(!nType)//如果nType等于0
brush.CreateSolidBrush(COLOR_PieceWhite);
else
brush.CreateSolidBrush(COLOR_PieceBlack);
pDC->FillRgn(&rgnPiece, &brush);
rgnPiece.DeleteObject();
} // CWzqView::vDrawPiece
///////////////////////////////////////////////////
//////////////////////////
// CWzqView drawing
void CWzqView::OnDraw(CDC* pDC)
{
CWzqDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
/////////////////////////////////插入位图背景
/////////////////////////////
CBitmap Bitmap;
Bitmap.LoadBitmap(IDB_BITMAP1);
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap* OldBitmap=dc.SelectObject(&Bitmap);
BITMAP bm;
Bitmap.GetBitmap(&bm);
pDC->BitBlt(-20,-76,bm.bmWidth,bm.bmHeight,&dc,0,0,SRCCOPY);
pDC->SelectObject(OldBitmap);
//////////////////////////////////插入背景结束
///////////////////////////
//// draw the lines of board
step=pDoc->nGetdstep();/////////////////////////step需从文件中获取
/////////////////////////
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
tag[i][j]=pDoc->nGetdtag(i,j);
int nBoardRowNum = pDoc->nGetBoardRowNum(); // get the row number from doc
/* CBrush brush1;//定义棋盘画刷
//brush1.CreateSolidBrush(COLOR_Brush);//创建棋盘画刷
//CRect
RectBoard(XPOS_TopLeft-20,YPOS_TopLeft-20,XPOS_TopLeft+(nBoardRowNum-1)* WIDTH_BoardGrid+20,YPOS_TopLeft+(nBoardRowNum -1)* WIDTH_BoardGrid+20);
//pDC->FillRect(&RectBoard,&brush1);用画刷填充RectBoard矩形的范围
//RectBoard.DeleteObject();*/
// draw the row lines横线
CPen pen;//定义画笔
pen.CreatePen(PS_DOT, WIDTH_Pen, (int)COLOR_Pen);//创建画笔(类型--虚线、笔宽、颜色)
for(int nRow = 0; nRow < nBoardRowNum; nRow ++)
{
pDC->MoveTo(XPOS_TopLeft, YPOS_TopLeft + nRow * WIDTH_BoardGrid);//起始点
pDC->SelectObject(&pen);//选择画笔
pDC->LineTo(XPOS_TopLeft + (nBoardRowNum - 1) * WIDTH_BoardGrid,
YPOS_TopLeft + nRow * WIDTH_BoardGrid);//终止点}
pDC->TextOut(10,10,"Hello!welcome to five chess world");//在左上角写话
// draw the column lines竖线
for(int nColumn = 0; nColumn < nBoardRowNum; nColumn ++)
{
pDC->MoveTo(XPOS_TopLeft + nColumn * WIDTH_BoardGrid, YPOS_TopLeft);
pDC->SelectObject(&pen);
pDC->LineTo(XPOS_TopLeft + nColumn * WIDTH_BoardGrid,
YPOS_TopLeft + (nBoardRowNum - 1) * WIDTH_BoardGrid);
}
//// Graw 4 Points
CPoint pt;//定义四个标志点
CBrush brush;//定义四点的画刷
brush.CreateSolidBrush(COLOR_Pen);//创建画刷
CRgn rgnPoint; //定义某区域
pt = ptConvertBP2VP(3, 3);//将棋坐标转换成视坐标
rgnPoint.CreateEllipticRgn( pt.x - WIDTH_Point,
pt.y - WIDTH_Point,
pt.x + WIDTH_Point,
pt.y + WIDTH_Point);
pDC->FillRgn(&rgnPoint, &brush);//填充以上圆形区域
rgnPoint.DeleteObject();//删除
pt = ptConvertBP2VP(3, 15);
rgnPoint.CreateEllipticRgn( pt.x - WIDTH_Point,
pt.y - WIDTH_Point,
pt.x + WIDTH_Point,
pt.y + WIDTH_Point);
pDC->FillRgn(&rgnPoint, &brush);
rgnPoint.DeleteObject();
pt = ptConvertBP2VP(15, 3);
rgnPoint.CreateEllipticRgn( pt.x - WIDTH_Point,
pt.y - WIDTH_Point,
pt.x + WIDTH_Point,
pt.y + WIDTH_Point);
pDC->FillRgn(&rgnPoint, &brush);
rgnPoint.DeleteObject();
pt = ptConvertBP2VP(15, 15);
rgnPoint.CreateEllipticRgn( pt.x - WIDTH_Point,
pt.y - WIDTH_Point,
pt.x + WIDTH_Point,
pt.y + WIDTH_Point);
pDC->FillRgn(&rgnPoint, &brush);
rgnPoint.DeleteObject();
for(int s=0;s<=Getstep();s++)
{
pt = GetPiecePos(s);
if ( (pt.x >= 0) && (pt.y >= 0) )
vDrawPiece(pt,s%2, pDC);
}
ReleaseDC(pDC);//释放
}
/////////////////////////////////////////////////////////////////////////// //
// CWzqView printing
BOOL CWzqView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CWzqView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CWzqView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
/////////////////////////////////////////////////////////////////////////// //
// CWzqView diagnostics
#ifdef _DEBUG
void CWzqView::AssertValid() const
{
CView::AssertValid();
}
void CWzqView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CWzqDoc* CWzqView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWzqDoc)));
return (CWzqDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////视坐标、棋盘坐标的转换
////////////////////////////
// CWzqView message handlers
// convert view point into board point
CPoint CWzqView::ptConvertVP2BP(CPoint pointView) const
{
CPoint ptBoard;
ptBoard.x = (int)((float)(pointView.x - XPOS_TopLeft ) / WIDTH_BoardGrid + 0.5);
ptBoard.y = (int)((float)(pointView.y - YPOS_TopLeft ) / WIDTH_BoardGrid + 0.5);
return ptBoard;
} // CWzqView::ptConvertVP2BP
// convert view point into board point
CPoint CWzqView::ptConvertVP2BP(int x, int y) const
CPoint ptBoard;
ptBoard.x = (int)((float)(x - XPOS_TopLeft ) / WIDTH_BoardGrid + 0.5);
ptBoard.y = (int)((float)(y - YPOS_TopLeft ) / WIDTH_BoardGrid + 0.5);
return ptBoard;
} // CWzqView::ptConvertVP2BP
// convert board point into view point 棋坐标与视坐标的转换
CPoint CWzqView::ptConvertBP2VP(int x, int y) const
{
CPoint ptView;
ptView.x = XPOS_TopLeft + x * WIDTH_BoardGrid;
ptView.y = YPOS_TopLeft + y * WIDTH_BoardGrid;
return ptView;
} // CWzqView::ptConvertBP2VP
// convert board point into view point
CPoint CWzqView::ptConvertBP2VP(CPoint pointBoard) const
{
CPoint ptView;
ptView.x = XPOS_TopLeft + pointBoard.x * WIDTH_BoardGrid;
ptView.y = YPOS_TopLeft + pointBoard.y * WIDTH_BoardGrid;;
return ptView;
} // CWzqView::ptConvertBP2VP
/////////////////////////////////////////////////////////////////////////// ///////////////////
// check if the view point is in board
BOOL CWzqView::bPointInBoard(CPoint pointView, int nBoardRowNum) const
{
return ( (pointView.x >= XPOS_TopLeft - WIDTH_BoardGrid * 0.5) && (pointView.x <= XPOS_TopLeft + (nBoardRowNum - 1) * WIDTH_BoardGrid + WIDTH_BoardGrid * 0.5) &&
(pointView.y >= YPOS_TopLeft - WIDTH_BoardGrid * 0.5) &&
(pointView.y <= YPOS_TopLeft + (nBoardRowNum - 1) * WIDTH_BoardGrid + WIDTH_BoardGrid * 0.5)
);
} // CWzqView::bPointInBoard
void CWzqView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CWzqDoc* pDoc = GetDocument();
int nBoardRowNum = pDoc->nGetBoardRowNum(); // get the row number from doc
if ( bPointInBoard(point, nBoardRowNum) )
{
CPoint ptBoard = ptConvertVP2BP(point); //先视坐标转换棋盘坐标
pDoc->vSetPiecePos(ptBoard);//将棋盘棋子信息重新设置
pDoc->SetModifiedFlag();
if(Gettag(ptBoard.x,ptBoard.y)==0)//若该点标志位为0,即无棋子,则画棋
{
step++;//步数加一
vSettag(ptBoard,Getstep());//将tag设置成步数信息step
pDoc->vSetdstep(Getstep());//将doc里面的棋子步数存入
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
pDoc->vSetdtag(i,j,Gettag(i,j));
CClientDC pcDC(this);//管理窗口用户区对应的显示上下文句柄信息OnDraw(&pcDC);//每次走一步重画棋盘所有信息
if(Forbid())//判断禁手与否若Forbid()为0,则悔棋
{
OnWzqGoback();//悔棋一步
}
if(wintag==1)//若已获胜
{
OnWzqGoback();
MessageBox("一方已获胜,悔棋OR重新开始!");
}
winner();//若不禁手,则判断是否获胜
}
else//若该店标志位非零,则有棋子
{
if(wintag==0)
MessageBox("该点已有棋子!");
else
MessageBox("一方已获胜,请不要在原来的棋子上下!");
}
}
CView::OnLButtonDown(nFlags, point);
}
////////////////////////////////////////////////获胜判断
///////////////////////////////////////
void CWzqView::winner()
{
wintag=0;//预先设定没有胜利
int nType;//0、1判断标志位 0黑棋 1白棋
for(int n=0;n<19;n++)
for(int m=0;m<15;m++)//逐个棋子扫描
{
int count=0;//相同棋子计数器
nType=tag[m][n]%2;//确定该子标志位
for(int i=0;i<5;i++)
{
if(tag[m+i][n]!=0&&tag[m+i][n]%2==nType)//////////////横向连珠////////////
count++;//若有横向有一子与原棋子tag一致且非零计数器加1
else
break;
}
if(count==5)///////////////////////横向五子连珠
//////////////////////////////
{
wintag=1;
if(nType==0)
MessageBox("白棋获胜!横向连珠");
else
MessageBox("黑棋获胜!横向连珠");
}
}
for(int m=0;m<19;m++)
for(int n=0;n<15;n++)
{
nType=tag[m][n]%2;
for(int i=0;i<5;i++)
{
if(tag[m][n+i]!=0&&tag[m][n+i]%2==nType)///////////竖向连珠//////////////
count++;
else
break;
}
if(count==5)
{
wintag=1;
if(nType==0)
MessageBox("白棋获胜!竖向连珠");
else
MessageBox("黑棋获胜!竖向连珠");
}
}
for(n=0;n<15;n++)
for(int m=0;m<15;m++)
{
int count=0;
nType=tag[m][n]%2;
for(int i=0;i<5;i++)
{
if(tag[m+i][n+i]!=0&&tag[m+i][n+i]%2==nType)///////////右下斜连珠////////////////
count++;
else
break;
}
if(count==5)
{
wintag=1;
if(nType==0)
MessageBox("白棋获胜!右下斜连珠");
else
MessageBox("黑棋获胜!右下斜连珠");
}
}
for(n=0;n<15;n++)
for(int m=4;m<19;m++)
{
nType=tag[m][n]%2;
for(int i=0;i<5;i++)
{
if(tag[m-i][n+i]!=0&&tag[m-i][n+i]%2==nType)/////////////左下斜连珠//////////////////
count++;
else
break;
}
if(count==5)
{
wintag=1;
if(nType==0)
MessageBox("白棋获胜!左下斜连珠");
else
MessageBox("黑棋获胜!左下斜连珠");
}
}
if(step>=100&&wintag==0)
MessageBox("和棋!");
}
/////////////////////////////////////////////////////禁手判断
////////////////////////////////////////////////
int CWzqView::Forbid()
{
CPoint piecepos=GetPiecePos(Getstep());
int sum[8]={0};//八个方向
int NUM=0;//不是禁手条件
int x=piecepos.x;
int y=piecepos.y;
for(int i=0;i<5;i++)
{
if(tag[x+i][y]%2==1&&tag[x+1+i][y]%2==1)//右横向
sum[0]++;
if(tag[x+i][y]%2==0&&tag[x+i][y]!=0)//
sum[0]--;
}
for(i=0;i<5;i++)
{
if(tag[x-i][y]%2==1&&tag[x-i-1][y]%2==1)//左横向
sum[1]++;
if(tag[x-i][y]%2==0&&tag[x-i][y]!=0)//
sum[1]--;
}
for(i=0;i<5;i++)
{
if(tag[x][y+i]%2==1&&tag[x][y+1+i]%2==1)//上
sum[2]++;
if(tag[x][y+i]%2==0&&tag[x][y+i]!=0)//
sum[2]--;
}
for(i=0;i<5;i++)
{
if(tag[x][y-i]%2==1&&tag[x][y-i-1]%2==1)//下
sum[3]++;
if(tag[x][y-i]%2==0&&tag[x][y-i]!=0)//
sum[3]--;
}
for(i=0;i<5;i++)
{
if(tag[x+i][y+i]%2==1&&tag[x+i+1][y+1+i]%2==1)//右下sum[4]++;
if(tag[x+i][y+i]%2==0&&tag[x+i][y+i]!=0)//
sum[4]--;
}
for(i=0;i<5;i++)
{
if(tag[x-i][y-i]%2==1&&tag[x-i-1][y-1-i]%2==1)//左上sum[5]++;
if(tag[x-i][y-i]%2==0&&tag[x-i][y-i]!=0)//
sum[5]--;
}
for(i=0;i<5;i++)
{
if(tag[x-i][y+i]%2==1&&tag[x-i-1][y+1+i]%2==1)//左下sum[6]++;
if(tag[x-i][y+i]%2==0&&tag[x-i][y+i]!=0)//
sum[6]--;
}
for(i=0;i<5;i++)
{
if(tag[x+i][y-i]%2==1&&tag[x+i+1][y-1-i]%2==1)//右上sum[7]++;
if(tag[x+i][y-i]%2==0&&tag[x+i][y-i]!=0)//若有白子sum[7]--;
}
//////特殊禁手类型判断//////
////正方形禁手and菱形禁手///
if((tag[x-1][y-1]%2==1&&tag[x][y]%2==1&&tag[x+1][y+1]%2==1&&tag[x-1][y+1]%2 ==1&&tag[x+1][y-1]%2==1&&tag[x+2][y+2]==0&&tag[x-2][y-2]==0&&tag[x-2][y+2]= =0&&tag[x+2][y-2]==0)||(tag[x-1][y]%2==1&&tag[x][y]%2==1&&tag[x][y+1]%2==1& &tag[x][y-1]%2==1&&tag[x][y+1]%2==1&&tag[x-2][y]==0&&tag[x+2][y]==0&&tag[x] [y-2]==0&&tag[x][y+2]==0))
{
NUM=1;
// MessageBox("禁手!");
}
//////四四禁手“#####@#@#@#@######”////////
if((tag[x-3][y]%2==1&&tag[x-2][y]==0&&tag[x-1][y]%2==1&&tag[x][y]%2==1&&tag [x+1][y]%2==1&&tag[x+2][y]==0&&tag[x+3][y]%2==1)||(tag[x][y-3]%2==1&&tag[x] [y-2]==0&&tag[x][y-1]%2==1&&tag[x][y]%2==1&&tag[x][y+1]%2==1&&tag[x][y+2]== 0&&tag[x][y+3]%2==1))
{
NUM=1;
}
if((tag[x-3][y-3]%2==1&&tag[x-2][y-2]==0&&tag[x-1][y-1]%2==1&&tag[x][y] %2==1&&tag[x+1][y+1]%2==1&&tag[x+2][y+2]==0&&tag[x+3][y+3]%2==1)||(tag[x+3] [y-3]%2==1&&tag[x+2][y-2]==0&&tag[x+1][y-1]%2==1&&tag[x][y]%2==1&&tag[x-1][ y+1]%2==1&&tag[x-2][y+2]==0&&tag[x-3][y+3]%2==1))
{
NUM=1;
}
//////////四四禁手“空空白黑黑空黑黑空黑黑白空
空”/////////////////////////
if((tag[x-5][y]%2==0&&tag[x-5][y]!=0&&tag[x-4][y]%2==1&&tag[x-3][y]%2== 1&&tag[x-2][y]==0&&tag[x-1][y]%2==1&&tag[x][y]%2==1&&tag[x+1][y]==0&&tag[x+ 2][y]%2==1&&tag[x+3][y]%2==1&&tag[x+4][y]%2==0&&tag[x+4][y]!=0)||(tag[x][y-5]%2==0&&tag[x][y-5]!=0&&tag[x][y-4]%2==1&&tag[x][y-3]%2==1&&tag[x][y-2]==0 &&tag[x][y-1]%2==1&&tag[x][y]%2==1&&tag[x][y+1]==0&&tag[x][y+2]%2==1&&tag[x ][y+3]%2==1&&tag[x][y+4]%2==0&&tag[x][y+4]!=0))
{
NUM=1;
}
if((tag[x-5][y-5]%2==0&&tag[x-5][y-5]!=0&&tag[x-4][y-4]%2==1&&tag[x-3][y-3] %2==1&&tag[x-2][y-2]==0&&tag[x-1][y-1]%2==1&&tag[x][y]%2==1&&tag[x+1][y+1]=
=0&&tag[x+2][y+2]%2==1&&tag[x+3][y+3]%2==1&&tag[x+4][y+4]%2==0&&tag[x+4][y+ 4]!=0)||(tag[x+5][y-5]%2==0&&tag[x+5][y-5]!=0&&tag[x+4][y-4]%2==1&&tag[x+3] [y-3]%2==1&&tag[x+2][y-2]==0&&tag[x+1][y-1]%2==1&&tag[x][y]%2==1&&tag[x-1][ y+1]==0&&tag[x-2][y+2]%2==1&&tag[x-3][y+3]%2==1&&tag[x-4][y+4]%2==0&&tag[x-4][y+4]!=0))
{
NUM=1;
}
if((tag[x+5][y]%2==0&&tag[x+5][y]!=0&&tag[x+4][y]%2==1&&tag[x+3][y]%2== 1&&tag[x+2][y]==0&&tag[x+1][y]%2==1&&tag[x][y]%2==1&&tag[x-1][y]==0&&tag[x-2][y]%2==1&&tag[x-3][y]%2==1&&tag[x-4][y]%2==0&&tag[x-4][y]!=0)||(tag[x][y+ 5]%2==0&&tag[x][y+5]!=0&&tag[x][y+4]%2==1&&tag[x][y+3]%2==1&&tag[x][y+2]==0 &&tag[x][y+1]%2==1&&tag[x][y]%2==1&&tag[x][y-1]==0&&tag[x][y-2]%2==1&&tag[x ][y-3]%2==1&&tag[x][y-4]%2==0&&tag[x][y-4]!=0))
{
NUM=1;
}
if((tag[x+5][y+5]%2==0&&tag[x+5][y+5]!=0&&tag[x+4][y+4]%2==1&&tag[x+3][y+3] %2==1&&tag[x+2][y+2]==0&&tag[x+1][y+1]%2==1&&tag[x][y]%2==1&&tag[x-1][y-1]= =0&&tag[x-2][y-2]%2==1&&tag[x-3][y-3]%2==1&&tag[x-4][y-4]%2==0&&tag[x-4][y-4]!=0)||(tag[x-5][y+5]%2==0&&tag[x-5][y+5]!=0&&tag[x-4][y+4]%2==1&&tag[x-3] [y+3]%2==1&&tag[x-2][y+2]==0&&tag[x-1][y+1]%2==1&&tag[x][y]%2==1&&tag[x+1][ y-1]==0&&tag[x+2][y-2]%2==1&&tag[x+3][y-3]%2==1&&tag[x+4][y-4]%2==0&&tag[x+ 4][y-4]!=0))
{
NUM=1;
}
///////////////////////////////////////////
for(int j=0;j<=7;j++)//八个方向
{
for(int k=0;k<=7;k++)
{
if(k!=j)//若八个方向不相同
{
if((sum[j]>=2)&&(sum[k]>=2))
{
NUM=1;
break;
}
}
}
}
if(NUM)
{
MessageBox("禁手!");
//break;
}
return NUM;
}
void CWzqView::OnCancelMode()
{
CView::OnCancelMode();
// TODO: Add your message handler code here
}
/////////悔棋/////////////////////////////////////////
void CWzqView::OnWzqGoback()
{
// TODO: Add your command handler code here
if(Getstep()==0)//若棋盘已空,则重新开始
{
OnWzqNewgame() ;
}
else//若棋盘非空,则step-1
{
vSettag(GetPiecePos(Getstep()),0);
step--;//步数减一
wintag=0;//悔棋后,没有胜利
Transfer();//将信息从view导入doc
CClientDC pcDC(this);
OnDraw(&pcDC);
}
}
//////////////////////////////新棋局///////////////////////// void CWzqView::OnWzqNewgame()
{
// TODO: Add your command handler code here
step=0;
wintag=0;
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
tag[i][j]=0;
Transfer();//将信息从view导入doc
CClientDC pcDC(this);
OnDraw(&pcDC);
}
//transfer the parameter from wzqView.cpp to wzqDoc.cpp void CWzqView::Transfer()
{
CWzqDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->vSetdstep(Getstep());
for(int i=0;i<19;i++)
for(int j=0;j<19;j++)
pDoc->vSetdtag(i,j,Gettag(i,j));
}。