转载请标明是引用于 http://blog.csdn.net/chenyujing1234
前段时间在CSDN的资源里载得五子棋VC的源码,由于忘了链接地址,这里没有标明出处,请作者谅解。
但我也把在VS2005上编译通过且加入清楚的注释的源码放到了下面链接,请下载:
http://www.rayfile.com/zh-cn/files/9ae2f74a-8927-11e1-9e3d-0015c55db73d/
整个游戏的界面是建立的单文档的基础上。
很多小游戏不是建立在对话框的基础上,而是在单文档或是自己创建窗口的基础上。
因为它们自动提供了菜单栏和状态栏,方便进行游戏设置和控件。
(1)函数LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
进行处理的,如最大化、最小化、鼠标左键按下
(2) CWuziqiView类的响应消息。
通过它的有如:左键单击、右键单击、右键双击
绘制界面的地方是在
void CWuziqiView::OnDraw(CDC* pDC) { }
这里不做介绍,大家可以自行去看.
由于五子棋游戏中的角色不多只有白棋子、黑棋子: 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、判断是不是双三