本程序算法资料来自下面网站.
----https://www.cnblogs.com/buptzym/archive/2012/06/20/2556052.html----
先定义一个数组 用于存储整个棋盘的数据.
u16 ChessBoard[15][15];//棋盘数据.
一.己方下棋 基础函数.
1.在屏幕上显示出来一个15*15的棋盘.
void DrawTable(void)//画出15x15的棋盘.
{
int i;
for(i=0;i<15;i++)
{
LCD_DrawLine(8,16+i*16,232,16+i*16);
LCD_DrawLine(8+i*16,16,8+i*16,240);
}
}
2.//两个数之差的绝对值
//x1,x2:需取差值的两个数
//返回值:|x1-x2|
u16 my_abs(u16 x1,u16 x2)
{
if(x1>x2)return x1-x2;
else return x2-x1;
}
3.//x,y是横纵坐标,Data是数组
//返回0:无子,1 :黑子,2:白子
u8 ReadData(u8 x,u8 y)
{
int temp;
temp=ChessBoard[x][y];
return temp;
}
4.//x,y是横纵坐标,Data是数组
//dat 0:无子,1 :黑子,2:白子
void WriteData(u8 x,u8 y,u8 dat)
{
ChessBoard[x][y]=dat;
}
5.//画出棋子,黑色或者白色.
void DrawChess(int x,int y,u16 color)
{
POINT_COLOR=color; //画笔色....
LCD_Draw_ALLCircle(8+x*16,16+y*16,8);
}
二.己方下棋应用函数
1.根据触摸的位置在屏幕上落子.
将棋子限制在棋盘的交叉格上.
void TouchChess(u8 dat)//触摸屏落子,
{
int x,y;
int chess_x,chess_y;
for(x=0;x<15;x++)
{
if(my_abs(8+x*16,tp_dev.x[0])<8)//附近范围<8
{
chess_x=x;
}
}
for(y=0;y<15;y++)
{
if(my_abs(16+y*16,tp_dev.y[0])<8)
{
chess_y=y;
}
}
if(ReadData(chess_x,chess_y) == 0)//空白区域才能落子.
WriteData(chess_x,chess_y,dat);
}
三.单片机下棋.(单片机需要知道每个格子的各个方向上的权值,哪里权值大就下哪里.简而言之就是哪个位置容易"成子"就下那里,如果是对方容易"成子"就下在哪里"堵他".
1.单片机下棋基础函数.
u16 GlobalData[8][15][15];
//黑棋 四个方向上的数据放在 GlobalData[0][15][15]----GlobalData[3][15][15]
//白棋 四个方向上的数据放在 GlobalData[4][15][15]----GlobalData[7][15][15]
u8 Max_x,Max_y;//最有利位置的坐标.
//读取白方或黑方的各个位置的权值.
u8 ReadGlobalData(u8 x,u8 y,u8 i)
{
u8 temp;
temp=GlobalData[i][x][y];
return temp;
}
//写入白方或黑方的各个位置的权值.
void WriteGlobalData(u8 temp,u8 x,u8 y,u8 dat)
{
GlobalData[temp][x][y] = dat;
}
//置零白方或黑方的各个位置的权值.
void RestGlobalData(void)
{
u8 i,j,k;
for(i=0;i<8;i++)
{
for(j=0;j<15;j++)
{
for(k=0;k<15;k++)
{
WriteGlobalData(i,j,k,0);
}
}
}
}
四.单片机下棋应用函数.
1.//得到白方或黑方各个位置上,四个方向上的权值.
void Optimal(u8 color)//全局zuiyou棋子分析.color 1--黑棋 2--白棋
{
int i,d;
int x,y;
u8 temp;
switch(color)
{
case (1): temp=0; break;
case (2):temp=4; break;
}
for(x=0;x<15;x++)
{
for(y=0;y<15;y++)
{
if(ReadData(x,y) == 0)
{
d=0;
for(i=1;i<5;i++)//x方向.
{
if(ReadData(x-i,y) != color || (x-i) == 0)
break;
else
d++;
}
for(i=1;i<5;i++)
{
if(ReadData(x+i,y) != color || (x+i) == 14)
break;
else
d++;
}
WriteGlobalData(temp,x,y,d);
d=0;
for(i=1;i<5;i++)//y方向.
{
if(ReadData(x,y-i) != color || (y-i) == 0)
break;
else
d++;
}
for(i=1;i<5;i++)
{
if(ReadData(x,y+i) != color || (y+i) ==14)
break;
else
d++;
}
WriteGlobalData(temp+1,x,y,d);
d=0;
for(i=1;i<5;i++)//
{
if(ReadData(x-i,y-i) != color || (x-i) == 0 || (y-i) == 0)// "\"方向
break;
else
d++;
}
for(i=1;i<5;i++)
{
if(ReadData(x+i,y+i) != color || (x+i) == 14 || (y+i) == 14)//
break;
else
d++;
}
WriteGlobalData(temp+2,x,y,d);
d=0;
for(i=1;i<5;i++)//
{
if(ReadData(x-i,y+i) != color || (x-i) == 0 || (y+i) == 14)// "/"方向
break;
else
d++;
}
for(i=1;i<5;i++)
{
if(ReadData(x+i,y-i) != color || (x+i) == 14 || (y-i) == 0)//
break;
else
d++;
}
WriteGlobalData(temp+3,x,y,d);
}
}
}
}
2.//选择白方或者黑方的最有利的位置落子.
//黑棋 四个方向上的数据放在 GlobalData[0][15][15]----GlobalData[3][15][15]
//白棋 四个方向上的数据放在 GlobalData[4][15][15]----GlobalData[7][15][15]
void Situationu(void)
{
int x,y;
u8 i;
u16 Mark;
u16 TotalMark,MaxMark=0;
u16 MarkTransform[5]={0,100,400,2000,10000};
Optimal(1);//heizi.
for(x=0;x<15;x++)
{
for(y=0;y<15;y++)
{
TotalMark=0;
for(i=0;i<4;i++)//四个方向
{
Mark = ReadGlobalData(x,y,i);
TotalMark += MarkTransform[Mark];
}
if(TotalMark > MaxMark)
{
Max_x=x;
Max_y=y;
MaxMark = TotalMark;
}
}
}
Optimal(2);//baizi.
for(x=0;x<15;x++)
{
for(y=0;y<15;y++)
{
TotalMark=0;
for(i=0;i<4;i++)
{
Mark = ReadGlobalData(x,y,i+4);
TotalMark += MarkTransform[Mark];
}
if(TotalMark > MaxMark)
{
Max_x=x;
Max_y=y;
MaxMark = TotalMark;
}
}
}
}
3.//选择有利位置落子.
void SetChess(void)
{
Situationu();
WriteData(Max_x,Max_y,2);
}
单片机下棋之后要置零权值数组.
RestGlobalData();//置位权值数组.
五.判断结果(判断黑棋或者白棋是否达到胜利条件,在某个棋子的各个方向上是否有任意一方向上有四个相同棋子)
u8 ResultCheck(u8 color)// 返回值:0:都未成功,1 白方胜利, 2黑方胜利
{
int x,y;
// 判断横向
for(y=0;y<15;y++)
{
for(x=0;x<11;x++)
{
if(color == ReadData(x,y) &&
color == ReadData(x+1,y) &&
color == ReadData(x+2,y) &&
color == ReadData(x+3,y) &&
color == ReadData(x+4,y) )
return color;
}
}
// 判断纵向
for(y=0;y<11;y++)
{
for(x=0;x<15;x++)
{
if(color == ReadData(x,y) &&
color == ReadData(x,y+1) &&
color == ReadData(x,y+2) &&
color == ReadData(x,y+3) &&
color == ReadData(x,y+4) )
return color;
}
}
// 判断"\"方向
for(y=0;y<11;y++)
{
for(x=0;x<11;x++)
{
if(color == ReadData(x,y) &&
color == ReadData(x+1,y+1) &&
color == ReadData(x+2,y+2) &&
color == ReadData(x+3,y+3) &&
color == ReadData(x+4,y+4) )
return color;
}
}
// 判断"/"方向
for(y=0;y<11;y++)
{
for(x=4;x<15;x++)
{
if(color == ReadData(x,y) &&
color == ReadData(x-1,y+1) &&
color == ReadData(x-2,y+2) &&
color == ReadData(x-3,y+3) &&
color == ReadData(x-4,y+4) )
return color;
}
}
// 不满足胜利条件
return 0;
}
(1)这个程序没有添加任何的交互界面,只有能够运行的函数.
如果想添加胜利交互界面可以根据ResultCheck()的返回值,弹出相应界面.
并清零棋盘数组ChessBoard[15][15]重新开始.
(2)显而易见的这个程序只是机械式的向权值最大处落子,如果赢了一局之后按原先的步骤再次落子你依然会赢,并且单片机所走的步骤也不有任何的改变.所以请把它当做一个小小的游戏.
(3)希望对你有所帮助.一起学习~
因个人能力有限,难免有疏漏之处.
望通知已便改正.