#include #include "RenjuRule.h" unsigned char RenjuRule_CheckRule(PRenjuRule prule,PRenjuBoard pboard,unsigned char x,unsigned char y,unsigned char chOwner) { if(RenjuRule_GetNodeChip(pboard,x,y) != 0) return DJGAME_RENJU_RULE_FAILED; RenjuRule_SetNodeChip(pboard,x,y,chOwner); if(chOwner ==0 || chOwner > 2) return DJGAME_RENJU_RULE_SUCCESS; int i,dx[4]={1,0,1,1},dy[4]={0,1,1,-1}; unsigned char chSerials,ch6=0; for(i=0;i<4;i++) { chSerials = RenjuRule_GetSerials(pboard,x,y,dx[i],dy[i]); if(chSerials >= 5) { if(chOwner == DJGAME_RENJU_OWNER_WHITE || chSerials == 5) return DJGAME_RENJU_RULE_WIN; if( prule->chRuleSet & RENJU_RULESET_HASFORBID) { ch6 ++; //如果5连和长连同时出现则先5胜,因此长连未必为禁手 }else return DJGAME_RENJU_RULE_WIN; } } if(ch6 > 0) { RenjuRule_SetNodeChip(pboard,x,y,0); return DJGAME_RENJU_RULE_FORBID_6; } return DJGAME_RENJU_RULE_SUCCESS; } unsigned char RenjuRule_IsForbid(PRenjuBoard pboard,unsigned char x,unsigned char y) { if(RenjuRule_GetNodeChip(pboard,x,y) != DJGAME_RENJU_OWNER_BLACK) return DJGAME_RENJU_RULE_FORBID_NOT; int i,dx[8]={1,-1,0,0,1,-1,1,-1},dy[8]={0,0,1,-1,1,-1,-1,1}; unsigned char cx,cy,tx,ty,chChips,chBlanks,chMaxSerials,chMaxBlankSerials; unsigned char ch4=0,chA4=0,chA3=0; RenjuRule rule; RenjuBoard board; bool bRes; rule.chRuleSet = RENJU_RULESET_HASFORBID; for(i=0;i<8;i++) { memcpy(&board,pboard,sizeof(RenjuBoard)); cx = x; cy = y; bRes = RenjuRule_GetOwnerHead(&board,&cx,&cy,-dx[i],-dy[i]); if(!bRes) return DJGAME_RENJU_RULE_FORBID_NOT; RenjuRule_GetRowStatus(&board,cx,cy,dx[i],dy[i],5,DJGAME_RENJU_OWNER_BLACK, &chChips,&chBlanks,&chMaxSerials,&chMaxBlankSerials); //if(chMaxBlankSerials == 1) { if(chChips == 4 && chBlanks == 1) { tx = cx; ty = cy; bRes = RenjuRule_GetFirstBlank(&board,&tx,&ty,dx[i],dy[i],5,DJGAME_RENJU_OWNER_BLACK); if(bRes) { if(RenjuRule_CheckRule(&rule,&board,tx,ty,DJGAME_RENJU_OWNER_BLACK) == DJGAME_RENJU_RULE_WIN) { ch4 ++; if(ch4>=2 || chA3> 0) return DJGAME_RENJU_RULE_FORBID_44; if(chMaxSerials == 4 && !(i&1)) { memcpy(&board,pboard,sizeof(RenjuBoard)); if(RenjuRule_CheckRule(&rule,&board,cx+dx[i+1],cy+dy[i+1],DJGAME_RENJU_OWNER_BLACK) == DJGAME_RENJU_RULE_WIN) chA4 ++; //活4 //跳过同轴的另一方向 i++; } } } }//if(chChips == 4 && chBlanks == 1) else if(chChips == 3 && (chMaxSerials == 3 || chMaxBlankSerials==1) && chBlanks == 2) { tx = cx; ty = cy; bRes = RenjuRule_GetFirstBlank(&board,&tx,&ty,dx[i],dy[i],5,DJGAME_RENJU_OWNER_BLACK); if(bRes) { if(RenjuRule_CheckRule(&rule,&board,tx,ty,DJGAME_RENJU_OWNER_BLACK) == DJGAME_RENJU_RULE_SUCCESS && RenjuRule_IsForbid(&board,tx,ty) == DJGAME_RENJU_RULE_FORBID_NOT_WITH_A4) { chA3 ++; if(chA3 >=2 || ch4>0 ) return DJGAME_RENJU_RULE_FORBID_33; if( !(i&1) ) i++; } } } }//if(chMaxBlankSerials == 1) } if(chA4 >0) return DJGAME_RENJU_RULE_FORBID_NOT_WITH_A4; return DJGAME_RENJU_RULE_FORBID_NOT; } unsigned char RenjuRule_GetSerials(PRenjuBoard pboard,unsigned char x,unsigned char y, int dx,int dy) { unsigned char chSerials=0; unsigned char chChip,chOwner = RenjuRule_GetNodeChip(pboard,x,y); if(chOwner != DJGAME_RENJU_OWNER_BLACK && chOwner != DJGAME_RENJU_OWNER_WHITE) return 0; if(RenjuRule_GetOwnerHead(pboard,&x,&y,-dx,-dy)) { do { chChip = RenjuRule_GetNodeChip(pboard,x,y); if(chChip == chOwner) { chSerials ++; x += dx; y += dy; } }while(chChip == chOwner); } return chSerials; } bool RenjuRule_GetFirstBlank(PRenjuBoard pboard,unsigned char *x,unsigned char *y, int dx,int dy,unsigned char chRange,unsigned char chOwner) { int i =0; unsigned char chChip; for(i=0;i 2) return false; unsigned char chNext=0,cx,cy; cx = *x+dx; cy = *y+dy; do { chNext = RenjuRule_GetNodeChip(pboard,cx,cy); if(chNext == chOwner) { cx += dx; cy += dy; } }while(chNext == chOwner); *x = cx-dx; *y = cy-dy; return true; } unsigned char RenjuRule_GetRowStatus(PRenjuBoard pboard,unsigned char x,unsigned char y, int dx,int dy,unsigned char chRange,unsigned char chOwner, unsigned char *pchChips,unsigned char *pchBlanks, unsigned char *pchMaxSerials,unsigned char *pchMaxBlankSerials) { *pchChips = 0; *pchBlanks = 0; *pchMaxSerials = 0; *pchMaxBlankSerials = 0; int i; unsigned char chCur,chCurMaxS=0,chCurMaxBS=0; for(i=0;i *pchMaxSerials) *pchMaxSerials = chCurMaxS; (*pchChips)++; }else if(chCur == 0) { chCurMaxS = 0; chCurMaxBS ++; if(chCurMaxBS > *pchMaxBlankSerials) *pchMaxBlankSerials = chCurMaxBS; (*pchBlanks)++; }else break; x += dx; y += dy; } return 0; } ///////////////////////////////////////////////////////////////////////// bool RenjuRule_SetNodeChip(PRenjuBoard pboard,unsigned char x,unsigned char y,unsigned char chOwner) { if(x==0 || y== 0 || x > DJGAME_RENJU_WIDTH || y>DJGAME_RENJU_WIDTH || chOwner > 2) return false; unsigned char chIndex,chBit; chIndex = (y-1)*DJGAME_RENJU_WIDTH+x; chBit = (chIndex&3); chIndex >>= 2; switch(chBit) { case 0 : pboard->chBuf[chIndex] &= 0xFC; break; case 1 : pboard->chBuf[chIndex] &= 0xF3; chOwner <<= 2; break; case 2 : pboard->chBuf[chIndex] &= 0xCF; chOwner <<= 4; break; case 3 : pboard->chBuf[chIndex] &= 0x3F; chOwner <<= 6; break; } pboard->chBuf[chIndex] |= chOwner; return true; } char RenjuRule_GetNodeChip(PRenjuBoard pboard,unsigned char x,unsigned char y) { if(x==0 || y== 0 || x > DJGAME_RENJU_WIDTH || y>DJGAME_RENJU_WIDTH) return -1; unsigned char chIndex,chBit; chIndex = (y-1)*DJGAME_RENJU_WIDTH+x; chBit = (chIndex&3); chIndex >>= 2; switch(chBit) { case 0 : return (pboard->chBuf[chIndex] & 0x03); case 1 : return ((pboard->chBuf[chIndex] & 0x0C)>>2); case 2 : return ((pboard->chBuf[chIndex] & 0x30)>>4); case 3 : return ((pboard->chBuf[chIndex] & 0xC0)>>6); } return -1; }