📄 scgo_219_16huidu.txt
字号:
//=============================================================================================
// <<山尘围棋_灰度版_ver2.19>>
//
// by 山尘(SHARP_APPLE)
// QQ:185027516
//---------------------------------------------------------------------------------------------
//特别感谢 Mslug 和 MickyCat 提供的建议和帮助
//---------------------------------------------------------------------------------------------
//Log:
// 2.11 棋块搜索Search()采用非递归算法,并做了一些相关优化,提高搜索速度 04.7.26
// 2.12 添加帮助 help(); 04.12.14
// 2.13 修改文件操作,在LavaData建立SCGO存档目录,读取采用FileList 04.12.09
// 2.14 修改LoadSGF 05.5.1
// 2.15 Search()等一些函数发现小问题,但不影响正确性,修正 05.5.1
// 2.16 增加调节播放速度的功能 05.5.2
// 2.17 为适应V7100的屏幕,将棋盘左移8个点,滚动轴移动到右边 05.5.5
// 2.18 改正一些小bugs,稍微调整了显示选项的界面 05.8.5
// 2.19 添加了打劫判断 05.8.23
//---------------------------------------------------------------------------------------------
#define OK 1
#define NO 0
#define YES 1
#define TRUE 1
#define FALSE 0
//----------------------
#define NOSTONE 0
#define BLACKSTONE 1
#define WHITESTONE 2
#define BLACKTURN 1
#define WHITETURN 0
//----------------------
#define UP 0x14
#define DOWN 0x15
#define LEFT 0x17
#define RIGHT 0x16
#define ENTER 0x0d
#define ESC 0x1b
#define SHIFT 0x1a
#define NET 0x8c
#define F1 0x1c
#define F2 0x1d
#define F3 0x1e
#define F4 0x1f
#define EXIT 27
#define JUMP 27
#define HELP 25
#define PGUP 19
#define PGDN 14
#define DOT 46
#define BLANKKEY 32
#define CPR 20
//----------------------
//绘图棋子类型
#define BLANK 0//空位置
#define LEFTTYPE 3//棋盘左边缘
#define RIGHTYPE 4// 右边缘
#define TOPTYPE 5// 上边缘
#define BUTTOMTYPE 6// 下边缘
#define CORNER00 7// 左上角
#define CORNER01 8// 右上角
#define CORNER10 9// 左下角
#define CORNER11 10// 右下角
#define STAR 11//星位
#define NULLTYPE 12//画空白
//---------------------
#define SEARCH_STKLEN 150
#define REMOVED_STKLEN 256
#define BACK_MAX_TIMES 350
#define FLASH_TIME 120
//---------------------
//图象数据
char Graphic_Qi[][32]={
0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x88,0x88,0x88,0x88, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00,
0x00,0x44,0x44,0x00, 0x04,0x67,0x76,0x40, 0x46,0x89,0x98,0x64, 0x46,0x89,0x98,0x64, 0x46,0x89,0x98,0x64, 0x46,0x89,0x98,0x64, 0x04,0x67,0x76,0x40,0x00,0x44,0x44,0x00,
0x00,0x88,0x88,0x00, 0x08,0xab,0x45,0x80, 0x8a,0xd8,0x44,0xa8, 0x8a,0xdf,0xfd,0xa8, 0x8a,0xdf,0xfd,0xa8, 0x8a,0xdf,0xfd,0xa8, 0x08,0xab,0xba,0x80, 0x00,0x88,0x88,0x00,
0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x88,0x88, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00,
0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x88,0x88,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd,
0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd, 0x00,0x00,0x00,0x00, 0x88,0x88,0x88,0x88, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00,
0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x00,0x08,0x00,0x00, 0x88,0x88,0x88,0x88, 0x00,0x00,0x00,0x00, 0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,
0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd, 0xdd,0x00,0x00,0x00, 0xdd,0x08,0x88,0x88, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00,
0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd, 0x00,0x00,0x00,0xdd, 0x88,0x88,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd,
0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x00,0x00, 0xdd,0x08,0x88,0x88, 0xdd,0x00,0x00,0x00, 0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,
0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x00,0x00,0x80,0xdd, 0x88,0x88,0x80,0xdd, 0x00,0x00,0x00,0xdd, 0xdd,0xdd,0xdd,0xdd, 0xdd,0xdd,0xdd,0xdd,
0x00,0x08,0x00,0x00, 0x00,0x0d,0x00,0x00, 0x00,0xdf,0xd0,0x00, 0x86,0xdf,0xd6,0x58, 0x00,0xdd,0xd0,0x00, 0x00,0x06,0x00,0x00, 0x00,0x05,0x00,0x00, 0x00,0x08,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
};
int dx[4]={ 0xffff,0x0000,0x0001,0x0000 },//四个方向坐标增量
dy[4]={ 0x0000,0xffff,0x0000,0x0001 },
Shou,
RmvdFlagStack_Top,
RedoTimesMax,
SplitDelayTime=2000;
char TopOffset,
SearchType,
SearchStackATop,
RmvdStkTop,
CursorX,
CursorY,
Auto,
BuZi,
Turn,
Dead,
DoTimes,
WDO=0,
SiZiShu,//每下一步提掉的死子数
FlashSwitch=TRUE,
FlashAlert=TRUE,
SeachTimesCounter;
char Board[20][19],//棋盘
Foot[19][19],//足迹
dir[SEARCH_STKLEN],//非递归遍历棋块时存储搜索方向
RmvdFlagStack[BACK_MAX_TIMES+2],//存储每一步提掉的死子堆栈的顶部位置
FileName[20],
QIPUINFO[130];
struct strQiZi
{
/*
char type;
*/
char x;
char y;
};
struct strQiZi TempQiForDaJie,
RemovedStack[REMOVED_STKLEN],//存储提掉的死子
PutDownXY_Stack[BACK_MAX_TIMES+2],//存储每一步的下子坐标
SearchStack[SEARCH_STKLEN];//用于遍历棋块时存储搜索到的棋子坐标
//----------------------
void InitStack() //初始化棋谱堆栈
{
RedoTimesMax=0;
RmvdStkTop=0;
RmvdFlagStack_Top=0;
}
void InitFoot() //初始化足迹
{
int i;
SeachTimesCounter++;
if(SeachTimesCounter==0){
SeachTimesCounter=1;
for(i=0;i<361;i++)Foot[0][i]=0;
}
}
void InitRemovedStack()
//将移子堆栈顶部指针置于刚走过的那一步
{
RmvdStkTop=RmvdFlagStack[RmvdFlagStack_Top];
}
void InitSearchStack()
//初始化遍历堆栈
{
SearchStackATop=SEARCH_STKLEN;
InitFoot();
}
void Init() //全体初始化(新局)
{
int i;
SeachTimesCounter=255;
TopOffset=9;
CursorX=3;
CursorY=6;
BuZi=FALSE;
Auto=TRUE;
Turn=BLACKTURN;
Shou=1;
DoTimes=0;
QIPUINFO[0]=0;
InitStack();
InitRemovedStack();
for(i=0;i<365;i++)Board[0][i]=NOSTONE;
}
int Message(int s,int NeedConfirm)
//画对话框(WDO是竖直(Y方向)偏移量WindowsDisplayOffSet,当NeedConfirm==1时确认,否则以该参数延时
{
int i,StringLen;
char Key;
SetScreen(0);
StringLen=strlen(s);
for(i=0;i<3;i++)
{
Block(72-StringLen*3+i,11+i+WDO,83+StringLen*3+i,30+i+WDO,1);
Block(73-StringLen*3+i,12+i+WDO,82+StringLen*3+i,29+i+WDO,0);
}
TextOut(80-StringLen*3,18+WDO,s,1);
Refresh();
if(NeedConfirm==YES)
{
Key=getchar();
if(Key=='y')
return TRUE;
else
return FALSE;
}
else
Delay(NeedConfirm);
}
int IsInSight(int y)
//Y行是否在屏幕视界中
{
if(y<TopOffset||y>TopOffset+9)
return FALSE;
else
return TRUE;
}
void DrawQiZi(char x,char y,int type)
//在屏幕 (x*8,y*8) 处画棋子
{
WriteBlock(++x*8-8,y*8,8,8,1,Graphic_Qi[type]);
}
void DrawBlank(char x,char y)
//在棋盘坐标x,y 无子处画棋盘
{
int temp;
temp=0;
if(y==0)temp=TOPTYPE;
if(y==18)temp=BUTTOMTYPE;
if(x==0)temp=LEFTTYPE;
if(x==18)temp=RIGHTYPE;
if(!x&&!y)temp=CORNER00;
if(x==18&&!y)temp=CORNER01;
if(!x&&y==18)temp=CORNER10;
if(x==18&&y==18)temp=CORNER11;
if((x+3)%6==0 && (y+3)%6==0)temp=STAR;
DrawQiZi(x,y-TopOffset,temp);
}
void DrawScroll()
{
int i;i=9;
Block(152,0,159,79,0);
Rectangle(153,10,158,70,1);
Block(155,63*TopOffset/19+12,156,63*(TopOffset+i)/19+9,1);
DrawQiZi(19,Turn*i,Turn+1);
}
void DrawBoardXY(int x,int y)
//画棋盘上x,y处的棋子
{
if(!IsInSight(y))return;
if(!Board[x][y])DrawBlank(x,y);
else DrawQiZi(x,y-TopOffset,Board[x][y]);
}
void DrawFullScreen()
//画整屏
{
int i,k,Post;
ClearScreen();
for(k=0;k<10;k++)
for(i=0;i<19;i++)
DrawBoardXY(i,k+TopOffset);
DrawScroll();
Refresh();
}
void DrawCurrent()
//重绘当前坐标处棋子
{
int Y;
Y=CursorY+TopOffset;
if(!Board[CursorX][Y])
DrawBlank(CursorX,Y);
else
DrawQiZi(CursorX,CursorY,Board[CursorX][Y]);
Refresh();
}
void DrawFullBoard()
//全局
{
int i,k,x,y;
char ch;
ClearScreen();
TextOut(28,5, "全",1);
TextOut(28,21,"局",1);
TextOut(28,37,"浏",1);
TextOut(28,53,"览",1);
Rectangle(22,0,45,70,1);
Rectangle(24,2,43,68,1);
Rectangle(54,0,130,76,1);
DrawQiZi(3,9,Turn+1);
for(i=0;i<19;i++){Block(56,i*4+2,128,i*4+2,1);Block(i*4+56,3,i*4+56,74,1);}
for(i=0;i<19;i++)
for(k=0;k<19;k++)
{
x=56+i*4;y=k*4+2;
if(Board[i][k]){
Block(x-2,y-1,x+2,y+1,1);
Block(x-1,y-2,x+1,y+2,1);
if(Board[i][k]==1)
Block(x-1,y-1,x+1,y+1,0);
}
}
Refresh();
getchar();
ClearScreen();
}
void FlashXY(int x,int y)
//在x,y处闪动
{
int i;
if(!FlashSwitch)return;
for(i=0;i<3;i++)
{
DrawQiZi(x,y-TopOffset,NULLTYPE);
Refresh();
Delay(FLASH_TIME);
DrawBoardXY(x,y);
Refresh();
Delay(FLASH_TIME);
}
}
int IsInBoard(char x,char y)
//坐标(x,y)是否在棋盘内
{
if(x<0||y<0||x>18||y>18)return FALSE;
else return TRUE;
}
void Search(char x,char y)
//非递归遍历x,y处的棋块
{
int SearchStackBTop,tdir;
SearchStackBTop=0;
do{
if (!Board[x][y]&&IsInBoard(x,y)){Dead=0;return;}
if(IsInBoard(x,y)&&(Foot[x][y]!=SeachTimesCounter)&&(Board[x][y]==SearchType))
{Foot[x][y]=SeachTimesCounter;
tdir=1;
SearchStackBTop++;
SearchStack[SearchStackBTop].x=x;SearchStack[SearchStackBTop].y=y;dir[SearchStackBTop]=tdir;
y++;
}
else{if(SearchStackBTop!=0){x=SearchStack[SearchStackBTop].x;y=SearchStack[SearchStackBTop].y;tdir=dir[SearchStackBTop];SearchStackBTop--;
while(tdir==4&&SearchStackBTop!=0)
{
Foot[x][y]=SeachTimesCounter;SearchStackATop--;
SearchStack[SearchStackATop].x=x;
SearchStack[SearchStackATop].y=y;
x=SearchStack[SearchStackBTop].x;y=SearchStack[SearchStackBTop].y;tdir=dir[SearchStackBTop];SearchStackBTop--;
}
if(tdir==4&&SearchStackBTop==0){SearchStackATop--;
SearchStack[SearchStackATop].x=x;
SearchStack[SearchStackATop].y=y;
}
if(tdir<4)
{tdir++;
SearchStackBTop++;SearchStack[SearchStackBTop].x=x;SearchStack[SearchStackBTop].y=y;dir[SearchStackBTop]=tdir;
if(tdir==1)y++;else
if(tdir==2)x++;else
if(tdir==3)y--;else
x--;
}
}
}
}while(SearchStackBTop!=0);
}
void Remove()
//移除刚经搜索的棋块
{
int i;
for(i=SearchStackATop;i<SEARCH_STKLEN;i++)
{
Board[SearchStack[i].x][SearchStack[i].y]=0;
RemovedStack[++RmvdStkTop].x=SearchStack[i].x;
RemovedStack[RmvdStkTop].y=SearchStack[i].y;
}
InitFoot();
}
int IsDead(char x, char y)//棋块死活
{
InitSearchStack();
Dead=TRUE;
SearchType=Board[x][y];
Search(x,y);
return Dead;
}
int IsDeadRound(char x,char y)
//x,y处周围是否有死子
{
int i,tx,ty;
for(i=0;i<4;i++)
{
tx=x+dx[i];ty=y+dy[i];
if(IsInBoard(tx,ty))
if(Board[tx][ty]==2-Turn)
if(IsDead(tx,ty))
return TRUE;
}
return FALSE;
}
void RemoveRound(char x,char y)
//移除x,y周围的死子
{
int i,tx,ty;
InitRemovedStack();
SiZiShu=0;
for(i=0;i<4;i++)
{
tx=x+dx[i];ty=y+dy[i];
if(IsInBoard(tx,ty))
if(Board[tx][ty]==3-Board[x][y])
if(IsDead(tx,ty))Remove();
}
RmvdFlagStack[RmvdFlagStack_Top+1]=RmvdStkTop;
Shou++;
}
void TryRemoveForDaJie()
{
int i;
for(i=SearchStackATop;i<SEARCH_STKLEN;i++)
{
SiZiShu++;
TempQiForDaJie.x=SearchStack[i].x;
TempQiForDaJie.y=SearchStack[i].y;
}
InitFoot();
}
void TryRemoveRoundForDaJie(char x,char y)
{
int i,tx,ty;
InitRemovedStack();
SiZiShu=0;
for(i=0;i<4;i++)
{
tx=x+dx[i];ty=y+dy[i];
if(IsInBoard(tx,ty))
if(Board[tx][ty]==3-Board[x][y])
if(IsDead(tx,ty))TryRemoveForDaJie();
}
}
int IsDaJieJinShou(char tempx,char tempy)
{
TryRemoveRoundForDaJie(tempx,tempy);
if(SiZiShu==1)
if(RmvdFlagStack_Top>1)
if(RmvdFlagStack[RmvdFlagStack_Top]-RmvdFlagStack[RmvdFlagStack_Top-1]==1)
if(tempx==RemovedStack[RmvdFlagStack[RmvdFlagStack_Top]].x && tempy==RemovedStack[RmvdFlagStack[RmvdFlagStack_Top]].y )
if(TempQiForDaJie.x==PutDownXY_Stack[RmvdFlagStack_Top].x && TempQiForDaJie.y==PutDownXY_Stack[RmvdFlagStack_Top].y )
{
Message("打劫禁手!",1);
DrawFullScreen();
return TRUE;
}
return FALSE;
}
void Push(char x,char y)
//将x,y及周围的死子压入堆栈
{
int i,temp;
if(RmvdFlagStack_Top==BACK_MAX_TIMES)
{
temp=RmvdFlagStack[1];
RmvdStkTop=RmvdStkTop-temp;
for(i=1;i<=RmvdStkTop;i++)
{
RemovedStack[i].x=RemovedStack[i+temp].x;
RemovedStack[i].y=RemovedStack[i+temp].y;
}
for(i=0;i<=BACK_MAX_TIMES+1;i++)
{
PutDownXY_Stack[i].x=PutDownXY_Stack[i+1].x;
PutDownXY_Stack[i].y=PutDownXY_Stack[i+1].y;
RmvdFlagStack[i]=RmvdFlagStack[i+1]-temp;
}
}//endif
else RmvdFlagStack_Top++;//endelse
RedoTimesMax=RmvdFlagStack_Top;
PutDownXY_Stack[RmvdFlagStack_Top].x=x;
PutDownXY_Stack[RmvdFlagStack_Top].y=y;
}
void SetScreenTopOffset(char y)
//调整y方向偏移量TopOffset
{
if(!IsInSight(y))
{
if(y>12)TopOffset=9;
else
if(y<6)TopOffset=0;
else
TopOffset=6;
DrawFullScreen();
}
}
void ReUnSta(int type)
//这是Redo()及Undo()的共用体
{
int i;
char x,y;
Board[PutDownXY_Stack[RmvdFlagStack_Top+1].x][PutDownXY_Stack[RmvdFlagStack_Top+1].y]=(1+Turn)*(1-type);
Turn=1-Turn;
for(i=RmvdFlagStack[RmvdFlagStack_Top]+1;i<=RmvdFlagStack[RmvdFlagStack_Top+1];i++)
{
Board[RemovedStack[i].x][RemovedStack[i].y]=(2-Turn)*type;
if(FlashAlert)DrawBoardXY(RemovedStack[i].x,RemovedStack[i].y);
}
if(FlashAlert){x=PutDownXY_Stack[RmvdFlagStack_Top+1].x;
y=PutDownXY_Stack[RmvdFlagStack_Top+1].y;
SetScreenTopOffset(y);
DrawScroll();
DrawBoardXY(x,y);
Refresh();
FlashXY(x,y);
}
}
void Undo(int times)
//撤销times步棋
{
while(times--)
{
if(!RmvdFlagStack_Top)
{
Beep();
Message("已到初局!",50);
DrawFullScreen();
return;
}
RmvdFlagStack_Top--;
Shou--;
ReUnSta(1);
}
}
void Redo(int times)
//重走times步棋
{
int i;
while(times--)
{
if(RmvdFlagStack_Top==RedoTimesMax){
Beep();Message("已到局末!",50);
DrawFullScreen();
return;
}
ReUnSta(0);
RmvdFlagStack_Top++;
Shou++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -