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

本文分析了一款VC编译的五子棋游戏的核心算法,主要包括棋盘界面设计、逻辑类设计以及关键的OnLButtonDown函数中实现的棋局判断逻辑。算法集中在判断双四、双三和五子长连等禁手规则,确保游戏公平性和结束条件的正确性。
摘要由CSDN通过智能技术生成

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

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

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

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

一、界面简介

1、 界面框架设计整个游戏的界面是建立的单文档的基础上。

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

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

1339827128_2545.jpg

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

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

(2) CWuziqiView类的响应消息。

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

1339827821_4568.jpg

绘制界面的地方是在

void CWuziqiView::OnDraw(CDC* pDC)

{

}

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

2、 逻辑类设计由于五子棋游戏中的角色不多只有白棋子、黑棋子: chess

再加上棋盘: Overall

1339828226_5565.jpg

二、 算法分析主要的算法集中在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、判断是不是双三

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值