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

来源:互联网 发布:php异步执行 编辑:程序博客网 时间:2024/04/19 08:25

 

 转载请标明是引用于 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){// 跨度不是5if(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;elsereturn 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、判断是不是双三

原创粉丝点击