VC编译的五子棋游戏核心算法分析(附源码)

2023-10-27

 

 转载请标明是引用于 http://blog.csdn.net/chenyujing1234

前段时间在CSDN的资源里载得五子棋VC的源码,由于忘了链接地址,这里没有标明出处,请作者谅解。

但我也把在VS2005上编译通过且加入清楚的注释的源码放到了下面链接,请下载:

http://www.rayfile.com/zh-cn/files/9ae2f74a-8927-11e1-9e3d-0015c55db73d/

一、界面简介

1、 界面框架设计

整个游戏的界面是建立的单文档的基础上。

很多小游戏不是建立在对话框的基础上,而是在单文档或是自己创建窗口的基础上。

因为它们自动提供了菜单栏和状态栏,方便进行游戏设置和控件。

 

(1)函数LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)

进行处理的,如最大化、最小化、鼠标左键按下

(2) CWuziqiView类的响应消息。

通过它的有如:左键单击、右键单击、右键双击

 

绘制界面的地方是在

void CWuziqiView::OnDraw(CDC* pDC)
{

}

这里不做介绍,大家可以自行去看.

2、 逻辑类设计

由于五子棋游戏中的角色不多只有白棋子、黑棋子: chess

再加上棋盘: Overall

 

 二、 算法分析

 主要的算法集中在OnLButtonDown函数里,下面贴出此段代码:

void CWuziqiView::OnLButtonDown(UINT nFlags, CPoint point) {  float temp;int com;  int x,y;  CRect rectClient;  GetClientRect(rectClient);

 // 精确定位棋子位置 x位置  temp=point.x*15;  temp=temp/rectClient.right;  com=temp;  if(temp - com > 0.5)   x = temp+1;  else   x =temp;

 // 精确定位棋子位置 y位置  temp=point.y*15;  temp=temp/rectClient.bottom;  com = temp;  if(temp - com > 0.5)   y = temp + 1;  else   y = temp;    // 没有连接,直接更新数据  if(connect == 0)  {   // 判断是不是所点位置没有放棋子   if(all.allqipan[x][y] == 0)   {       MessageBeep(MB_OK);

   if(who == 1)  // 此时是黑棋    {     //  黑棋自己做标记     black.keydown(x, y, who);     // 全局棋盘做标记     all.allqipan[x][y] = 1;          // 双四且禁手     if(all.shuangsi(x,y)==1 && whohasjinshou == 1)     {      Invalidate();      resultwin lost;      lost.m_Who.Format("黑棋输!有2种4个棋子一条线!");      lost.DoModal();      OnRuleRestart();      return;     }

    // 判断当前的位置是不是五子长连     int win = all.winchanglian(x, y);     if(win == 1) // 刚好有5个棋子颜色一样,则黑棋胜     {      Invalidate();      resultwin win;      win.m_Who.Format("黑棋胜!");      win.DoModal();      OnRuleRestart();      return;      }       if(win == 0 && whohasjinshou==1) // 少于5个棋子颜色一样,且自己是禁手了,黑棋输     {      Invalidate();      resultwin lost;      lost.m_Who.Format("黑棋输!long!");      lost.DoModal();      OnRuleRestart();      return;     }     // 双三且是禁手     if(all.shuangsan(x,y) == 1&& whohasjinshou == 1)     {      Invalidate();      resultwin fail;      fail.m_Who.Format("黑棋输!double 3!");      fail.DoModal();      OnRuleRestart();      return;       }

   }

 

 以下是游戏的规则:

//以下是规则判断,双三,双四都使禁手
//活三定义:再下一步成为活四
//活四定义:有多于一种的方法成为五颗
//冲四定义:只有一步能够成为五颗
//同时形成两个以上的活三,冲四,或者长连就是禁手

 

它们对应的函数如下:

1、判断是不是双冲四

	
// 判断是不是双冲四
// 冲四定义:只有一步能够成为五颗
// 返回值:
//      1   是双冲四
//       0   不是双冲四
int Overall::shuangsi(int x, int y)
{
	int nCountx,nCounty,nColor,nCount,recordx,recordy;

	nCount=0;
	nColor = allqipan[x][y];

	/*=================================横的方向======================================*/
	// 横向判断,先向左
	for(nCountx = x; allqipan[nCountx][y] == nColor && nCountx>=0; nCountx--);
	// 如果下往左边走,边缘的位置上是空的
	if(nCountx >= 0 && allqipan[nCountx][y] == 0)
	{
		// 那么就把此位置填充为当前的颜色,再判断是不是能连五
		allqipan[nCountx][y] = nColor;
		if(winchanglian(nCountx,y) == 1) // 能够连五
		{
			// 记录此位置及个数
			nCount++;
			recordx = nCountx;
			recordy = y;
		}
		// 清除临时填充的棋子
		allqipan[nCountx][y] = 0;
	}
	// 横向判断,向左
	for(nCountx=x + 1; allqipan[nCountx][y] == nColor && nCountx<=17; nCountx++);
	if(nCountx <= 17 && allqipan[nCountx][y] == 0)
	{
		allqipan[nCountx][y]=nColor;
		if(winchanglian(nCountx, y) == 1)
		{
			// 跨度不是5
			if(nCountx - recordx != 5) 
				nCount++;
		}
		allqipan[nCountx][y]=0;
	}
	recordx = recordy = -50;
	

	/*=================================竖的方向======================================*/
	// 竖的,向下
	for(nCounty = y; allqipan[x][nCounty] == nColor && nCounty >= 0; nCounty--);
	if(nCounty >= 0 &&  allqipan[x][nCounty] == 0)
	{
		allqipan[x][nCounty] = nColor;
		if(winchanglian(x,nCounty)==1)
		{
			nCount++;
			recordx=x;
			recordy=nCounty;
		}
		allqipan[x][nCounty]=0;	
	}
	// 竖的,向上
	for(nCounty = y+1; allqipan[x][nCounty] == nColor&&nCounty<=17;nCounty++);
	if(nCounty <= 17 && allqipan[x][nCounty] == 0)
	{
		allqipan[x][nCounty] = nColor;
		if(winchanglian(x,nCounty) == 1)
		{
			if(nCounty - recordy != 5)
			{
				nCount++;
			}
		}
		allqipan[x][nCounty] = 0;	
	}
	recordx=recordy=-50;

	/*=================================左右的方向======================================*/
	//  左右方向,先左
	for(nCountx=x, nCounty=y; allqipan[nCountx][nCounty]==nColor && nCountx >= 0 && nCounty>=0; nCountx--,nCounty--);
	if(nCounty>=0&&nCountx>=0&&allqipan[nCountx][nCounty]==0)
	{
		allqipan[nCountx][nCounty]=nColor;
		if(winchanglian(nCountx,nCounty)==1)
		{
			nCount++;
			recordx=nCountx;
			recordy=nCounty;
		}
		allqipan[nCountx][nCounty]=0;	
	}
	// 左右方向,再右
	for(nCountx=x+1,nCounty=y+1;allqipan[nCountx][nCounty]==nColor&&nCountx<=17&&nCounty<=17;nCountx++,nCounty++);
	if(nCounty<=17&&nCountx<=17&&allqipan[nCountx][nCounty]==0)
	{
		allqipan[nCountx][nCounty]=nColor;
		if(winchanglian(nCountx,nCounty)==1)
		{
			if(nCountx-recordx!=4&&nCounty-recordy!=5)
			{
				nCount++;
			}
		}
		allqipan[nCountx][nCounty]=0;	
	}
	recordx=recordy=-50;
	

	/*=================================右左的方向======================================*/
	// 右左
	for(nCountx=x,nCounty=y;allqipan[nCountx][nCounty]==nColor&&nCountx>=0&&nCounty<=17;nCountx--,nCounty++);
	if(nCounty>=0&&nCountx<=17&&allqipan[nCountx][nCounty]==0)
	{
		allqipan[nCountx][nCounty]=nColor;
		if(winchanglian(nCountx,nCounty)==1)
		{
			nCount++;
			recordx=nCountx;
			recordy=nCounty;
		}
		allqipan[nCountx][nCounty]=0;	
	}
	for(nCountx=x+1,nCounty=y-1;allqipan[nCountx][nCounty]==nColor&&nCountx<=17&&nCounty<=17;nCountx++,nCounty--);
	if(nCounty<=17&&nCountx>=0&&allqipan[nCountx][nCounty]==0)
	{
		allqipan[nCountx][nCounty]=nColor;
		if(winchanglian(nCountx,nCounty)==1)
		{
			if(nCountx-recordx!=4&&recordy-nCounty!=5)
			{
				nCount++;
			}
		}
		allqipan[nCountx][nCounty]=0;	
	}

	/*=================================结果======================================*/
	// 有两个或两个以上可能产生双四
	if(nCount >= 2)
		return 1;
	else
		return 0;
}


2、 判断当前的位置是不是五子长连

// 判断当前的位置是不是五子长连
int Overall::winchanglian(int x, int y)
{
	// 判断是不是长连禁手
	int nCountx, nCounty, nColor, nCount;

	
	// 当前位置的颜色
	nColor = allqipan[x][y];

	// 横向方向判断
	nCount = 0;
	for(nCountx=x; allqipan[nCountx][y]==nColor&&nCountx>=0; nCountx--,nCount++);
	for(nCountx=x+1; allqipan[nCountx][y]==nColor&&nCountx<=17; nCountx++,nCount++);
	// 达到5个棋子,胜了
	if(nCount == 5)		return 1;
	if(nCount > 5)		return 0;


	// 纵向方向判断
	nCount = 0;
	for(nCounty=y;allqipan[x][nCounty]==nColor&&nCounty>=0;nCounty--,nCount++);
	for(nCounty=y+1;allqipan[x][nCounty]==nColor&&nCounty<=17;nCounty++,nCount++);
	if(nCount==5)		return 1;
	if(nCount>5)		return 0;

	// 左右方向判断
	nCount = 0;
	for(nCountx=x,nCounty=y;allqipan[nCountx][nCounty]==nColor&&nCountx>=0&&nCounty>=0;nCountx--,nCounty--,nCount++);
	for(nCountx=x+1,nCounty=y+1;allqipan[nCountx][nCounty]==nColor&&nCountx<=17&&nCounty<=17;nCountx++,nCounty++,nCount++);
	if(nCount==5)		return 1;
	if(nCount>5)		return 0;

	// 右左方向判断
	nCount = 0;
	for(nCountx=x,nCounty=y;allqipan[nCountx][nCounty]==nColor&&nCountx>=0&&nCounty>=0;nCountx--,nCounty++,nCount++);
	for(nCountx=x+1,nCounty=y-1;allqipan[nCountx][nCounty]==nColor&&nCountx<=17&&nCounty<=17;nCountx++,nCounty--,nCount++);
	if(nCount==5)	return 1;
	if(nCount>5)	return 0;

	// 小于5个棋子颜色一样
	return -1; 
}


3、判断是不是双三

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VC编译的五子棋游戏核心算法分析(附源码) 的相关文章

随机推荐