#include"stdafx.h"
#include"plane.h"
#include<time.h>
#ifndef PLANECPP
#define PLANECPP
plane** plane::zu = new plane*[16];//为zu数组申请空间
plane::plane(int a, int c) :col((color)a), stat1(stand), value(c), plus(false), origin(c){}//构造函数
void plane::getready()//棋子从stand状态走向ready状态所进行的操作
{
value = (int)col + 76;
stat1 = ready;
if (col == blue)
plus = true;//蓝棋从刚出家门的时候,plus就为true,其他颜色需要经过51位置后plus才变成true
}
void plane::gohome()//棋子被摧毁时进行的操作
{
value = origin;
stat1 = stand;
plus = false;
}
plane::~plane()//析构函数,只是delete掉所有new过的空间
{
num--;
if (num != 0)
return;
delete[] zu;
zu = nullptr;
}
int plane::getvalue()
{
return value;
}
int plane::getstat()
{
return (int)stat1;
}
int plane::beicuishu()const
{
switch (col)
{
case blue:return 66;
case yellow:return 72;
case green:return 54;
case red:return 60;
}
}
void plane::crash(const int position)//判断棋子是否被摧毁
{
int count = 0;
for (int i = 0; i < 16; ++i)//对16个棋子进行遍历
{
if (position == (*zu[i]).value && (*zu[i]).col != col)//当前位置已经有其他颜色的棋子的情况
{
(*zu[i]).gohome();//已经在此地的棋子被摧毁回家
count++;//计数,此时已在此地的棋子的数量
}
}
if (count > 1)//如果count>1,说明此地之前有其他颜色的迭子,此时这个后来的棋子也回家
gohome();
}
void plane::judge()//判断棋子当前位置是否跳格
{
int tiao = ((int)col * 13 + 17) % 52;//各个颜色棋子到加油站的位置格数:蓝色17,黄色30……
int turn = (49 + (int)col * 13) % 52;//各个颜色棋子即将进入终点线的格数:蓝色49,黄色10……
if (value == tiao || value == tiao - 4)//若棋子当前位置满足飞棋的条件
{
if (value == tiao)
crash((tiao + 16) % 52);
else
crash(tiao);
if (stat1 == stand)
return;
value += 16;
if (col == green)
{
plus = true;
value %= 52;
}
crash(beicuishu());
if (stat1 == stand)
return;
}
else if (value % 4 == (((int)col + 1) % 4) && (value < turn || !plus))//不满足飞棋的条件但满足普通跳四格的条件
{
value += 4;
if (value > 51)
{
value %= 52;
plus = true;
}
}
crash(value);
}
void plane::move(int length)
{
int corr = (int)col * 13;//各个颜色离家最近的位置编号,蓝色0,黄色13……
int rea = 76 + (int)col;//各个颜色的ready区的位置编号
if (stat1 == stand)//在调用move函数之前先判断是否满足可动条件(若该子为stand状态而点数小于5则不可动,就不会调用move函数)
getready();
else if (stat1 == ready)
{
for (int i = corr; i < corr + length - 1; i++)//判断是否有敌方迭子在自己家门口
{
int number = 0;
for (int k = 0; k < 16; k++)
if ((*zu[k]).value == i && (*zu[k]).col != col)
number++;
if (number > 1)//若敌方迭子在自己家门口
{
value = i - (length + corr - 1 - i);//多余的点数往回跳
stat1 = run;
if (value < corr)//由于敌方迭子离自家家门太近,回跳距离超过前跳距离,那么该棋子不动,仍留在ready区
{
value = rea;
stat1 = ready;
return;
}
crash(value);
return;
}
}
value = -1 + (int)col * 13 + length;//家门口没有敌方迭子,那么value变量正常加
stat1 = run;
crash(value);
if (stat1 == stand)
return;
judge();//判断当前位置是否跳格
}
else if (stat1 == run)
{
int po = value + length;//一个辅助变量
int turn = (49 + (int)col * 13) % 52;//各个颜色棋子即将进入终点线的格数:蓝色49,黄色10……
for (int i = value + 1; i < (po > turn&&plus ? turn + 1 : po); i++)//判断若直接走该棋子会不会遇到敌方迭子
{
int number = 0;
for (int k = 0; k < 16; k++)
if ((*zu[k]).value == (i % 52) && (*zu[k]).col != col)
number++;
if (number > 1)//若遇到了敌方迭子
{
value = 2 * i - po;
if (value > 51)
{
value %= 52;
plus = true;
}
else
plus = false;
if (value < corr&&!plus)//规定棋子回跳不会比离家最近的位置更往后
value = corr;
crash(value);
return;
}
}
value += length;//value暂时与点数相加
if (value > turn&&value - length <= turn&&plus)//棋子满足进入终点线的条件
value = value + ((54 - (int)col * 7) % 52);//对value进行修正,此时棋子已经在终点线内
else if (value > 51 && !plus)//棋子不满足进入终点线的条件,判断棋子在走完这段路程是否经过了51
{
value %= 52;//若是,则修正value变量,并且plus变为ture
plus = true;
}
crash(value);
if (stat1 == stand)
return;
judge();
if (stat1 == stand)
return;
int winnum = 57 + (int)col * 6;//棋子走完整个流程的点数
if (value >= winnum)//判断棋子移动完之后是否已经走完整个流程
{
value = origin;
stat1 = win;
}
}
}
int plane::evalutaion(int length)
{
//weight:单个棋子的综合价值
int weight = 0;
//pos:position value 棋子位置价值
int pos = 0;
//preagg: present aggressiveness 棋子当前攻击性价值
//prethr: present threaten 棋子当前受威胁性价值
//latagg: later aggressiveness 棋子走后攻击性价值
//latthr: later threaten 棋子走后受威胁性价值
int preagg = 0, prethr = 0, latagg = 0, latthr = 0;
//fin:final-line value 可入终点线价值
int fin = 0;
//jum: jump value 可跳性价值,含四格跳与加油站跳
int jum = 0;
//plu: plural value 迭子价值
int plu = 0;
//sta: status value 当前状态价值
int sta = 0;
if (stat1 == stand)
sta += 400;
else if (stat1 == ready)
sta += 100;
else
{
if (!(value >= 52 && value <= 95))//已经安全进入终点线,则没有位置价值;或在stand/ready区域,价值另计。
{
//其余位置有位置价值
if (value >= col * 13)
pos = (value - col * 13) * 10;
else
pos = (value + 52 - col * 13) * 10;
}
for (int i = value - 6; i <= value + 6; i++)//棋子当前/走后的前/后六步会影响到攻击性/受威胁性价值
{
for (int j = 0; j < 16; j++)
{
if ((*zu[j]).value == i % 52 && (*zu[j]).col != col)
{
if (i - value>0)
preagg -= 40 * (7 - i);
if (i - value < 0)
prethr += 40 * (7 + i);
}
if ((*zu[j]).value == (i + length) % 52 && (*zu[j]).col != col)
{
if (i - value>0)
latagg += 40 * (7 - i);
if (i - value < 0)
latthr -= 40 * (7 + i);
}
}
}
int landpos1 = (value + (4 - col) % 4 * 13) + length;//landpos1: land position1 从外圈跑道上转入终点线的落地点
int landpos2 = value + length;//landpos2: land position2 飞机走前已在终点线的落地点
if (((value + ((4 - col) % 4) * 13) + length) >= 50 && ((value + ((4 - col) % 4) * 13) + length) <= 54 && ((value + ((4 - col) % 4) * 13) + length) != 50)//走后若可进入终点线且不落在毁机点
{
fin += 300;
}
if ((value < 52 && landpos1 >= 50 && landpos1 <= 54 && landpos1 != 52) || (value >= 52 && landpos2 == 54 + col * 6))//若走后落在毁机点
{
fin -= 1000;
}
if (value == beicuishu())//若当前正在毁机点上
{
fin += 1000;
}
int tiao = ((int)col * 13 + 17) % 52;
int turn = (49 + (int)col * 13) % 52;
if (value % 4 == (((int)col + 1) % 4) && (value < turn || !plus))//若是四格跳,可跳性价值增加200
{
jum += 200;
if (value == tiao || value == tiao - 4)//若是加油站跳,再附加额外的价值
jum += 200;
}
int enenum[4][6] = { 0 };//enenum数组用于计数走步之内各格子他方的棋子数
bool isbro = false;//isbro用于判断落地点是否已有己方同色棋子
int enepluvalue = 0;//eneplu: enermy plural 他方在落地点处的迭子位置价值
for (int i = (value + 1) % 52, num = 1; num <= length; i = (i + 1) % 52, num++)//对走步之内(含途经点与落地点)进行判断
//for循环中,num用于计数,当num从1到length时,终止循环
{
for (int j = 0; j < 16; j++)//对16个棋子逐一判断
{
if ((*zu[j]).value == i && (*zu[j]).col == col)//己方棋子
{
if (num == length)
{
isbro = true;//落地点为己方棋子
}
}
if ((*zu[j]).value == i && (*zu[j]).col != col)//他方棋子
{
enenum[j / 4][num - 1]++;
if (enenum[j / 4][num - 1] > 1 && num == length)//落地点他方棋子数目大于1,即落在他方迭子处
{
enepluvalue = (*zu[j]).v