五子棋 算法-- 只考虑当前利益

#ifndef FIVECHESS_H
#define FIVECHESS_H
#define Board_LEN 15
#define Board_WID 15

// 定义 点的数据结构
typedef struct point {
   int x;
   int y;
   int mark;
}Point ;

//定义 走棋步骤链表  
typedef struct ChessStep
{
    Point             m_point;
    ChessStep     *PreStep;
ChessStep     *NextStep;
}StepList;



//棋盘类
class Board
{
public:
Board();
bool SetPoint( Point );     //落子
int getPoint( Point &);     //检查该点 
void  showBoard();
const StepList * getCurStep();

int    Revblacks();   // 返回当前棋盘 黑棋数
int    Revwhites();   // 返回当前棋盘 白棋数

bool GameOver(int );  //游戏结束 ?
bool GmOver;
private:
int m_Board[Board_LEN][Board_WID];   //棋盘的大小
    StepList    h_steps;   //走棋的顺序表 表头
StepList   *cur ;          //当前点的
    int                 iblacks;
    int                 iwhites;
};


//
class Player
{
public:
const enum Mark{ black = 1 , white = 2};
Player();
bool chkSide(Board  &, Point  ,int ,int,int (&board)[Board_LEN][Board_WID][4] ); // 从两个方向 判断一个点的权值
bool chkWeight( Board & , int (&board)[Board_LEN][Board_WID][4]);   //判断当前玩家的棋型,为棋型表 赋值
bool clearWeight();   // 将权值表 清0 便于下次判断
//bool chkCmpterWgt( Board &);  
Point MaxWeight(int (&board)[Board_LEN][Board_WID][4],Point & ,Board &);
    bool chkMode( Board &);   //判断先后手 ;
Point  Analyse(Board &);       //分析并 返回 下棋点;
void showCptWght();               // 打印 电脑棋型的 权值表
    void showGmrWght();             // 打印 选手棋型的权值表
private:
int  gamerBoardWgt[Board_LEN][Board_WID][4];     // 保存选手棋盘上各点4个方向棋型的权值
int  computerBoardWgt[Board_LEN][Board_WID][4];  //保存电脑棋盘上各点4个方向棋型的权值
int  mark ;    //标记 先手还是后手即 执 黑或白
int  mode;    //标记 当前是进攻还是防守

};

class Control
{
public:
  const enum Mode {Gamer =1 ,Computer};
  Control();
  //~Control();
  bool ModeSwitch();  //转换 走子方
 
  bool Control::inputPoint(Point & ,Board &);
  bool MainCtrl(Board &,Player &);  //控制 游戏主体 流程
  //Point goChess(Point);  // 走子
  int getPlayer();           //判断当前走棋方
private:
  Mode  player;
};

#endif

############################################################################################
#include <iostream>
#include "FiveChess.h"
using namespace std;


//初始化棋盘
Board::Board()
{
    for(int i = 0 ; i < Board_LEN;  i++)
{   
for(int j = 0 ; j < Board_WID; j ++)
   m_Board[i][j] = 0;
}
    h_steps.PreStep = NULL;
h_steps.m_point.mark = NULL;
h_steps.NextStep = NULL;
iblacks = iwhites = 0;
cur = &(h_steps);
this->GmOver = false;
};

int Board::ChkChess(int side,int dir ,int color,int x,int y)
{
   int c = 0 ;
   switch(dir)
  {
  case 0 :
  for( c = 0 ; c < 6 ; ++c)
  {
    if( y+c*side > 0 && y+c*side <Board_WID )
{
  if( color == m_Board[x][y+c*side] )
  {
    continue;
  }
  else 
    return c;
}
else 
return c;    
  }
  case 1:
  for( c = 0; c < 6 ; ++c)
  {
    if( x+c*side >0 && x+c*side < Board_WID)
{
  if(color == m_Board[x+c*side][y])
  continue;
  else
  return c;
}
else
return c;
  }
  case 2:
  for( c =0 ; c < 6 ; ++c)
  {
    if(x-side*c >= 0 && x-side*c < Board_LEN 
  && y-side*c >=0 && y-side*c< Board_WID)
{
  if(color == m_Board[x-side*c][y-c*side])
   continue;
  else
  return c;
}
else
return c;
  }
  case 3:
   for(c = 0; c < 6 ; ++c)
   {
     if(x+side*c >= 0 && x+side*c < Board_LEN 
    && y-side*c >=0 && y-side*c< Board_WID)
 {
   if(color == m_Board[x+side*c][y-c*side])
continue;
else
return c;
 }
  else
   return c;
   }
  default :
  return c;
   }

}
bool Board::GameOver()
{
// this->SetPoint(p);
int count = 0;
for(int x = 0 ; x < Board_LEN ; ++x)
    for( int y = 0 ; y < Board_WID ; ++y)
{
if(black == m_Board[x][y])
for(int direct = 0 ; direct < 4; ++direct)
 {
   count = 0;
   //一个方向 判断 棋型
count +=  ChkChess( 1,direct,black,x,y);
           // count +=  ChkChess(-1,direct,black,x,y);
if(count >= 5)
{
cout << "black win" << endl;
return GmOver=true;
}
 }
 
}
else if(white == m_Board[x][y])
{
 for(int direct = 0 ; direct < 4; ++direct)
 {
   //一个方向 判断 棋型
   count = 0;
count +=  ChkChess( 1,direct,white,x,y);
            //count +=  ChkChess(-1,direct,white,x,y);
  if(count >= 5)
  {
    cout << "white win " <<endl;
    return GmOver=true;
    }
 }



}
return false;
};

int Board::Revblacks()
{
  return iblacks;
};

int Board::Revwhites()
{
  return iwhites;
};
//填写当前棋盘
bool Board::SetPoint(Point p)          
{
m_Board[p.x][p.y] = p.mark;
if(p.mark == 1)
++iblacks;
else
++iwhites;
 
cur ->m_point.mark = p.mark;
cur ->m_point.x = p.x ;
cur ->m_point.y = p.y ;
     
//新增加点的记录 
cur ->NextStep= new StepList;
cur ->NextStep->PreStep = cur;
cur = cur ->NextStep;
cur->NextStep = NULL;
 


return true;
};
const StepList * Board::getCurStep()
{
  return  cur;
};
//打印 当前棋盘
void Board::showBoard()
{
   for(int i = 0 ;  i < Board_LEN ; i ++)
   {    
  for (int j = 0 ; j < Board_WID ; j ++)
    cout <<m_Board[i][j] <<' ';
      cout << endl;   
   }
   cout << endl;
};

//返回当前点的 状态
int Board::getPoint(Point &p)
{
return   m_Board[p.x][p.y];
};

//初始 电脑 和 选手的棋型 权值表

Player::Player(  )
{
     for(int i = 0 ; i < Board_LEN;  i++)
for(int j = 0 ; j < Board_WID; j ++)
{
for ( int d= 0 ; d < 4 ; d ++)
{
gamerBoardWgt[i][j][d] = 0;
computerBoardWgt[i][j][d]  = 0 ;
}
}
}
//mark = m;  // 指定 先后手 
};

bool Player::chkSide(Board  &board, Point p , int  s,int d,int (&myChessWeight)[Board_LEN][Board_WID][4])
{
  int weight ;
  int x = p.x ;
  int y = p.y;
  Point p1;
  p1.mark = mark;  //当前的走子方
  switch(d)
  {
  case 0 :   // 垂直方向上的棋型
          // 对一 个方向上的棋子个数 记录
for( int c = 0 ; c < Board_LEN - y ; ++c)  
{
//越界 检查
if( y + s*(c+1) >= 0 && y +s*(c+1) < Board_WID)
{
p1.x = x ;
p1.y = y +s*(c+1);
//if( c > 5 )  //胜利条件 判断
//{
// board.GameOver(p1);
// return 0;
//}
  if( board.getPoint(p1) == 0 )
{
if( c != 0) //对于棋型是否是 冲 还是活的判断
      myChessWeight[x][y][d] += 1;  
 return 0 ; 
}
else if( board.getPoint(p1) == mark)
{
weight = 1; //个数 赋权值
myChessWeight[x][y][d] += weight*10 ; 
}
else 
return 0;
}
else 
return 0 ;
}
return 0 ;
  case 1:
 for( int c = 0 ; c < Board_LEN - x; ++c)
{
if( x+s*(c+1) >= 0 && x+s*(c+1) < Board_LEN )
{
p1.x = x +s*(c+1);
p1.y = y;
  // if( c > 5)
//{
// board.GameOver(p1);
// return 0;
//}
if( board.getPoint(p1) == 0 )
{
if( c != 0)
      myChessWeight[x][y][d] += 1;  
 return 0 ; 
}
else if(board.getPoint(p1) == mark)
{
weight = 1; 
myChessWeight[x][y][d] += weight*10; 
}
      else 
return 0;
}
else 
return 0 ;
}
   return 0 ;
  case 2 :
for( int c = 0 ; c <Board_LEN - x; ++c)
{
if(x+s*(c+1) >= 0 && x+s*(c+1)<Board_LEN && y-s*(c+1)>= 0 && y-s*(c+1)<Board_WID)
 
{
p1.x = x+s*(c+1);
p1.y = y-s*(c+1);
//if( c > 5)
//{
// board.GameOver(p1);
// return 0;
//}
if( board.getPoint(p1) == 0 )
{
if( c != 0)
       myChessWeight[x][y][d] += 1;  
 return 0 ; 
}
else if(board.getPoint(p1) == mark)
{
weight = 1; 
myChessWeight[x][y][d] += weight*10; 
}
else 
return 0;
}
else 
return 0 ;
}
   return 0 ;
  case 3:
 for( int c = 0 ; c < Board_LEN - x; ++c)
{
if(x+s*(c+1)>= 0 && x+s*(c+1) < Board_LEN && y+s*(c+1)>=0 && y+s*(c+1)< Board_WID)
{
p1.x = x+s*(c+1);
p1.y = y+s*(c+1);
//if( c > 5)
//{
// board.GameOver(p1);
// return 0;
//}
if( board.getPoint(p1) == 0 )
{
if( c != 0)
 myChessWeight[x][y][d] += 1;    return 0 ; 
}
else if(board.getPoint(p1) == mark)
{
weight = 1; 
myChessWeight[x][y][d] += weight*10; 
}
else 
return 0 ;
}
else 
return 0 ;
}
   return 0 ;
  default :
 cout << "error direct " << endl;
 return 0 ;

  }
};

// 权值表 清零 便于 重新判断 
bool Player::clearWeight()
{
   for(int x = 0 ; x < Board_LEN ; ++x)
  for(int y = 0 ;  y <Board_WID; ++y)
  {
  for (int d= 0 ; d< 4; ++d)
  {
  this->gamerBoardWgt[x][y][d] = 0;
  this->computerBoardWgt[x][y][d] = 0;
  }
  }
  return 0;
};
// 扫描己方棋盘的棋型,4个方向进行赋权值 
bool Player::chkWeight( Board &cBoard, int (&b)[Board_LEN][Board_WID][4])
{
     Point  p ;
int  s = 1;

for( int i = 0 ;  i < Board_LEN ; ++i)
{
for ( int j = 0 ; j <Board_WID ; ++j)
{
p.x = i ;  p.y = j;
   //判断是否是空白点
   if( 0 == cBoard.getPoint(p) )  
 {  
 for( int direct = 0; direct < 4 ;  ++direct)
 { 
      chkSide(cBoard, p,s,direct,b);   // 对一个点的在一个方向上两面 棋型判断
  chkSide(cBoard, p,-s,direct,b);
 }
 }
}
}
return 0 ;
};
// 打印电脑棋型的 权重值表
void Player:: showCptWght()
{
   for(int i = 0 ; i < Board_LEN ; i ++)
   {
  for (int j = 0 ; j < Board_WID ; j++)
  {
 for(int d= 0 ; d <4 ; d++)
  cout  << computerBoardWgt[i][j][d] << ' ' ;
 cout << endl ;
  }
  cout << endl;
   }
};
//打印选手棋型的 权值表
void Player::showGmrWght()
{
   for(int i = 0 ; i < Board_LEN ; i ++)
   {
  for (int j = 0 ; j < Board_WID ; j++)
  {
 for(int d= 0 ; d <4 ; d++)
  cout  << gamerBoardWgt[i][j][d] << ' ' ;
 cout << endl ;
  }
  cout << endl;
   }
};

//判断  棋盘走棋的 先后手 
bool Player::chkMode(Board &b)
{
if( b.getCurStep()->PreStep->m_point.mark == NULL)
this ->mark = black;
else if( b.getCurStep()->PreStep->m_point.mark == black)
mark = white;
else if(b.getCurStep()->PreStep->m_point.mark == white)
mark = black;
return 0;

};
//
// 找寻 棋型表中的 最大值 点
bool Player::MaxWeight(int (&b)[Board_LEN][Board_WID][4],Point &p,Board &board)
{
p.mark = 1;
//Point pt;
int cptWgt1=0, gmrWgt1=0,cptWgt2=0,gmrWgt2=0;
int p1Wgt,p2Wgt; 

//寻找当前一方棋型权值最大的点
    for(int x = 0 ; x < Board_WID ; ++x)
 {
 for (int y = 0 ;  y < Board_LEN ; ++y)
 {
 for(int d = 0 ; d < 4; ++d)
 {  
 if( b[x][y][d] > p.mark)
 {
 p.x = x ; p.y = y ;  
 p .mark = b[x][y][d];
 }
 else if( p.mark ==b[x][y][d]) //当 当前一方 棋型权值相同的时候 ,比较相同点双方棋型的权值
 {
                            cptWgt1=0, gmrWgt1=0,cptWgt2=0,gmrWgt2=0;
for( int direct= 0; direct <4 ; ++direct)
{
cptWgt1 += this->computerBoardWgt[x][y][direct];
gmrWgt1 +=this->gamerBoardWgt[x][y][direct];

cptWgt2 += this->computerBoardWgt[p.x][p.y][direct];
gmrWgt2 += this->gamerBoardWgt[p.x][p.y][direct];

}
p1Wgt = cptWgt1 + gmrWgt1;
p2Wgt = cptWgt2 + gmrWgt2;
if( p1Wgt > p2Wgt) 
{
p.x = x; p.y = y;
}
 }
 }
 }
 }
  return 0;
};
Point Player::Analyse(Board &board)
{
  Point point,temp1,temp2;
  point .x = 0;  
  point .y = 0;
  chkMode(board);  
  point.mark = mark; // 为将要落的子, 赋值

  if( mark == black)  //执黑先行的话,落子到棋盘中央
  {
 point.x = Board_LEN/2; point.y = Board_WID/2;
 point.mark = black;
      return point;
  }
  else
  {
 clearWeight();
 mark = black;
 chkWeight(board,gamerBoardWgt);
   // showGmrWght();
 cout << "**********************************" << endl;
 mark = white;
 chkWeight(board,computerBoardWgt);

   // showCptWght();


//棋盘 下第一个子的时候
 if( board.Revblacks() == 1)
 {
 int x =  board.getCurStep()->PreStep->m_point.x;
 int y =  board.getCurStep()->PreStep->m_point.y;

if( Board_LEN - x -1> x)
point.x = x+1;
else
point.x = x-1;
if( Board_WID -y - 1>y)
point.y = y +1;
else
point.y = y -1;
 
return  point;
 }
 
 
     MaxWeight(computerBoardWgt,temp1,board);
MaxWeight(gamerBoardWgt,temp2,board);
 //判断电脑的 棋型是否 冲三 以上
 //进攻 优先
 if( temp2.mark < 21)
 {
   point.x = temp1.x;
   point.y = temp1.y;    
 }

 // #**#  #*#*#  o***#   三种棋型   *黑棋  #空位  o白棋
 else if(temp2.mark > 20 && temp2.mark < 31)
 {
 if(temp1.mark >20 && temp1.mark != 30)
 {
   point.x = temp1.x;
   point.y = temp1.y;
 }
 else
 {
   point.x = temp2.x;
   point.y = temp2.y;
 }
 
 }
 // #***#  #*#**#  
 else if( temp2.mark > 30 && temp2.mark < 40)
 {
 if(temp1.mark> 30)
 {
 point.x=temp1.x;
 point.y=temp1.y;
 }
 else
 {
 point.x=temp2.x;
 point.y=temp2.y;
 }
 }
 else if( temp2.mark > 39)
 {
 if(temp1.mark > 39)
 {
   point.x = temp1.x;
   point.y = temp1.y;
 }
 else
 {
   point.x=temp2.x;
    point.y=temp2.y;
 }
 }
 else 
 {
 
 point.x = temp2.x ;
 point.y = temp2.y ;
 }
  
  }

return point;
};

// 初始化 
Control::Control()
{
player = Gamer;
};

// 输入走棋的坐标
bool Control::inputPoint(Point &p,Board &b)
{
p.mark = Gamer;
cout << "输入 你想走棋的坐标" << endl;
cin >> p.x  >> p.y ;
//输入合法性 检查

if(b.getPoint(p) == 0)
{
return 0;
}
else 
while( b.getPoint(p) !=0)
{
cout << "你输入的点不合法,重新输入" << endl;
cin >> p.x  >> p.y ;
     }
return 0;
};
bool Control::MainCtrl(Board & board,Player &cpter)
{
Point p;
    while(!board.GameOver() )
{
board.showBoard();
inputPoint(p,board);
board.SetPoint(p);
board.SetPoint(cpter.Analyse(board) );
}
board.showBoard();
getchar();
getchar();
return 0; 
};
####################################################################################
#include<iostream>
#include "FiveChess.h"

using namespace std;

int main()
{
Board board;
Player computer;
Control ctrl;
ctrl.MainCtrl(board,computer);
return 0;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值