📄 gomoku.cpp
字号:
// Gomoku.cpp: implementation of the Gomoku class.
//
//////////////////////////////////////////////////////////////////////
#include "Gomoku.h"
#include <string.h>
#include <stdio.h>
/*---------------------------------------------------
作者: 姜俊波
日期: 2005-12-19
版本: 1.0
目的: 应朋友邀请,用C++(不使用MFC)写一个windows下的五子棋程序
声明: 所有C++的爱好者均可以自由的使用和更改本软件
联系: csvj@sohu.com
---------------------------------------------------*/
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Gomoku::Gomoku()
{
}
Gomoku::~Gomoku()
{
list.RemoveAll();
}
Gomoku::Gomoku(int r, int c)
{
//
rc_continue.left = 2;
rc_continue.right = 100;
rc_continue.top = 2;
rc_continue.bottom= 25;
//
rc_newgame.left = rc_continue.right;
rc_newgame.right = 100+rc_continue.right;
rc_newgame.top = 2;
rc_newgame.bottom= 25;
//
rc_invite.left = rc_newgame.right;
rc_invite.right = 100+rc_newgame.right;
rc_invite.top = 2;
rc_invite.bottom= 25;
//
space = 20;
Xstart = 25;
Ystart = 30;
row = r;
col = c;
//
invite = computer;
cur_player = 0;//black
list.space = space;
for (int i=0; i<r; i++)
{
for (int j=0; j<c; j++)
{
Play play;
play.x = i*space+Xstart;
play.y = j*space+Ystart;
play.square = Empty;
list.AddTail(play);
}
}
}
void Gomoku::Display(HDC &hdc)
{
Play *p = NULL;
for (int i=0; i<list.GetSize(); i++)
{
p = list.GetNext(p);
if (p != NULL)
{
char dis[5];
switch(p->square)
{
case Black:
sprintf(dis,"X");
break;
case White:
sprintf(dis,"O");
break;
default:
sprintf(dis,".");
break;
}
TextOut(hdc,p->x,p->y,dis,strlen(dis));
}
}
/*
for (i=0; i<row; i++)
{
char pos[5];
sprintf(pos,"%d", i);
TextOut(hdc,i*space+Xstart,0,pos,strlen(pos));
}
for (i=0; i<col; i++)
{
char pos[5];
sprintf(pos,"%d", i);
TextOut(hdc,0,i*space+Ystart,pos,strlen(pos));
}
*/
//
MoveToEx(hdc,rc_continue.left,rc_continue.top,NULL);
LineTo(hdc,rc_continue.right,rc_continue.top);
LineTo(hdc,rc_continue.right,rc_continue.bottom);
LineTo(hdc,rc_continue.left,rc_continue.bottom);
LineTo(hdc,rc_continue.left,rc_continue.top);
TextOut(hdc,rc_continue.left+15,rc_continue.top+2,"continue",strlen("continue"));
//
MoveToEx(hdc,rc_newgame.left,rc_newgame.top,NULL);
LineTo(hdc,rc_newgame.right,rc_newgame.top);
LineTo(hdc,rc_newgame.right,rc_newgame.bottom);
LineTo(hdc,rc_newgame.left,rc_newgame.bottom);
LineTo(hdc,rc_newgame.left,rc_newgame.top);
TextOut(hdc,rc_newgame.left+15,rc_newgame.top+2,"new game",strlen("new game"));
//
MoveToEx(hdc,rc_invite.left,rc_invite.top,NULL);
LineTo(hdc,rc_invite.right,rc_invite.top);
LineTo(hdc,rc_invite.right,rc_invite.bottom);
LineTo(hdc,rc_invite.left,rc_invite.bottom);
LineTo(hdc,rc_invite.left,rc_invite.top);
if (invite == computer)
{
TextOut(hdc,rc_invite.left+15,rc_invite.top+2,"computer",strlen("computer"));
}
else
{
TextOut(hdc,rc_invite.left+15,rc_invite.top+2,"persion",strlen("persion"));
}
}
bool Gomoku::Input(POINT point)
{
Play *p = NULL;
for (int i=0; i<list.GetSize(); i++)
{
p = list.GetNext(p);
if (IsInRect(p->x,p->y,space,space,point) && (p->square == Empty))
{
if (cur_player == 0) {
p->square = Black;
cur_player = !cur_player;
if (invite == computer)//黑子下完后由计算机下子
{
ComputerPlay(point);
}
}
else {
p->square = White;
cur_player = !cur_player;
}
return true;
}
}
//菜单项
//是否点击了某个菜单
if (IsInRect(rc_continue.left,rc_continue.top,rc_continue.right-rc_continue.left,rc_continue.bottom-rc_continue.top,point))
{
Continue();
}
else if (IsInRect(rc_newgame.left,rc_newgame.top,rc_newgame.right-rc_newgame.left,rc_newgame.bottom-rc_newgame.top,point))
{
NewGame();
}
else if (IsInRect(rc_invite.left,rc_invite.top,rc_invite.right-rc_invite.left,rc_invite.bottom-rc_invite.top,point))
{
Invite();
}
return true;
}
BOOL Gomoku::IsInRect(int baseX, int baseY, int width, int high, POINT point)
{
if ((point.x>=baseX) && (point.x<=(baseX+width)) && (point.y>=baseY) && (point.y<=baseY+high))
{
return TRUE;
}
return FALSE;
}
void Gomoku::Continue()
{
list.RemoveAll();
ReadFromFile();
}
void Gomoku::NewGame()
{
Play *p = NULL;
for (int i=0; i<list.GetSize(); i++)
{
p = list.GetNext(p);
if (p != NULL)
{
p->square = Empty;
}
}
}
void Gomoku::Invite()
{
if (invite == computer)
invite = persion;
else
invite = computer;
NewGame();
}
Square Gomoku::IsSuccess(POINT point)
{
Play *p = list.Find(point);
if (p == NULL)
{
return Empty;
}
//检查在八个方向上是否有连成五个的棋子,如有,则获胜
if ((MaxChessmanNum(point,p->square,left2right) + MaxChessmanNum(point,p->square,right2left))>= 6) {
return p->square;
}
if ((MaxChessmanNum(point,p->square,up2down) + MaxChessmanNum(point,p->square,down2up))>= 6) {
return p->square;
}
if ((MaxChessmanNum(point,p->square,ldown2rup) + MaxChessmanNum(point,p->square,rup2ldown)) >= 6) {
return p->square;
}
if ((MaxChessmanNum(point,p->square,rdown2lup) + MaxChessmanNum(point,p->square,lup2rdown))>= 6) {
return p->square;
}
return Empty;
}
int Gomoku::MaxChessmanNum(POINT point, Square baseq, int dir)
{
int res = 1;
Play *ply;
POINT nextp = point;
nextp = GetNextPoint(point,dir);
while ((ply=list.Find(nextp)) != NULL)
{
if (ply->square != baseq)
{
break;
}
nextp = GetNextPoint(nextp,dir);
res ++;
}
return res;
}
POINT Gomoku::GetNextPoint(POINT base, int dir)
{
POINT point = base;
switch(dir)
{
case left2right:
point.x += space;
break;
case right2left:
point.x -= space;
break;
case up2down:
point.y += space;
break;
case down2up:
point.y -= space;
break;
case ldown2rup:
point.x += space;
point.y -= space;
break;
case rup2ldown:
point.x -= space;
point.y += space;
break;
case rdown2lup:
point.x -= space;
point.y -= space;
break;
case lup2rdown:
point.x += space;
point.y += space;
break;
}
return point;
}
//该算法非常简单,可以替换的剪枝算法,深度遍历的算法
//只判断对方落子后在八个方向上,哪个方向连成的棋子最多,就去截住它
void Gomoku::ComputerPlay(POINT point)
{
Play *p = list.Find(point);
if (p == NULL)
{
return;
}
int max[4], num = 0;
for (int i=0; i<8; i+=2)
{
max[num++] = MaxChessmanNum(point,p->square,i) + MaxChessmanNum(point,p->square,i+1) - 1;
}
int maxmax=max[0];
num = 0;
for (i=1; i<4; i++)
{
if (maxmax < max[i])
{
maxmax = max[i];
num = i;
}
}
int direction = num*2;
int m1 = MaxChessmanNum(point,p->square,direction);
int m2 = MaxChessmanNum(point,p->square,direction+1);
POINT pt = point;
for (i=0; i<m1; i++)
{
pt = GetNextPoint(pt,direction);
}
if ((p=list.Find(pt)) != NULL)
{
if (p->square == Empty)
{
Input(pt);
return;
}
}
pt = point;
for (i=0; i<m2; i++)
{
pt = GetNextPoint(pt,direction+1);
}
if ((p=list.Find(pt)) != NULL)
{
if (p->square == Empty)
{
Input(pt);
return;
}
}
//
p = NULL;
while ((p=list.GetNext(p)) != NULL)
{
if (p->square == Empty)
{
pt.x = p->x;
pt.y = p->y;
Input(pt);
return;
}
}
}
//C中的标准函数
void Gomoku::SaveToFile()
{
FILE *pFile;
char *sPath = "save.gu";
pFile = fopen(sPath,"w");
if(pFile == NULL)
return;
fprintf(pFile,"%d\n",row);
fprintf(pFile,"%d\n",col);
fprintf(pFile,"%d\n",invite);
fprintf(pFile,"%d\n",cur_player);
//
fprintf(pFile,"%d\n",list.space);
Play *py = NULL;
for (int i=0; i<list.GetSize(); i++)
{
if ((py=list.GetNext(py)) == NULL)
break;
fprintf(pFile,"%d\n",py->x);
fprintf(pFile,"%d\n",py->y);
fprintf(pFile,"%d\n",py->square);
}
}
void Gomoku::ReadFromFile()
{
FILE *pFile;
char *sPath = "save.gu";
pFile = fopen(sPath,"r");
fscanf(pFile, "%d", &row);
fscanf(pFile, "%d", &col);
fscanf(pFile, "%d", &invite);
fscanf(pFile, "%d", &cur_player);
fscanf(pFile, "%d", &list.space);
for (int i=0; i<row; i++)
{
for (int j=0; j<col; j++)
{
Play play;
fscanf(pFile, "%d", &play.x);
fscanf(pFile, "%d", &play.y);
fscanf(pFile, "%d", &play.square);
list.AddTail(play);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -