求一个C语言小程序(五子棋)源代码
2024-07-16 11:17:21作者:饭克斯
*******************************************************************/
/*ALEX_LEE五子棋C语言小程序*/
/*o(∩_∩)o...可以用来复习一下C语言的小程序*/
/*MyBlog:hi.baidu.com/alexlee321*/
/******************************************************************/
/**********************************************************/
#include
#include
#include
#include
#include
/**********************************************************/
/*定义符号常量*/
/*定义画棋盘所需的制表符*/
#defineCROSSRU0xbf/*右上角点*/
#defineCROSSLU0xda/*左上角点*/
#defineCROSSLD0xc0/*左下角点*/
#defineCROSSRD0xd9/*右下角点*/
#defineCROSSL0xc3/*左边*/
#defineCROSSR0xb4/*右边*/
#defineCROSSU0xc2/*上边*/
#defineCROSSD0xc1/*下边*/
#defineCROSS0xc5/*十字交叉点*/
/*定义棋盘左上角点在屏幕上的位置*/
#defineMAPXOFT5
#defineMAPYOFT2
/*定义1号玩家的操作键键码*/
#definePLAY1UP0x1157/*上移--'W'*/
#definePLAY1DOWN0x1f53/*下移--'S'*/
#definePLAY1LEFT0x1e41/*左移--'A'*/
#definePLAY1RIGHT0x2044/*右移--'D'*/
#definePLAY1DO0x3920/*落子--空格键*/
/*定义2号玩家的操作键键码*/
#definePLAY2UP0x4800/*上移--方向键up*/
#definePLAY2DOWN0x5000/*下移--方向键down*/
#definePLAY2LEFT0x4b00/*左移--方向键left*/
#definePLAY2RIGHT0x4d00/*右移--方向键right*/
#definePLAY2DO0x1c0d/*落子--回车键Enter*/
/*若想在游戏中途退出,可按Esc键*/
#defineESCAPE0x011b
/*定义棋盘上交叉点的状态,即该点有无棋子*/
/*若有棋子,还应能指出是哪个玩家的棋子*/
#defineCHESSNULL0//没有棋子
#defineCHESS1'O'//一号玩家的棋子
#defineCHESS2'X'//二号玩家的棋子
/*定义按键类别*/
#defineKEYEXIT0/*退出键*/
#defineKEYFALLCHESS1/*落子键*/
#defineKEYMOVECURSOR2/*光标移动键*/
#defineKEYINVALID3/*无效键*/
/*定义符号常量:真,假---真为1,假为0*/
#defineTRUE1
#defineFALSE0
/**********************************************************/
/*定义数据结构*/
/*棋盘交叉点坐标的数据结构*/
structpoint
{
intx,y;
};
/**********************************************************/
/*自定义函数原型说明*/
voidInit(void);
intGetKey(void);
intCheckKey(intpress);
intChangeOrder(void);
intChessGo(intOrder,structpointCursor);
voidDoError(void);
voidDoOK(void);
voidDoWin(intOrder);
voidMoveCursor(intOrder,intpress);
voidDrawCross(intx,inty);
voidDrawMap(void);
intJudgeWin(intOrder,structpointCursor);
intJudgeWinLine(intOrder,structpointCursor,intdirection);
voidShowOrderMsg(intOrder);
voidEndGame(void);
/**********************************************************/
/**********************************************************/
/*定义全局变量*/
intgPlayOrder;/*指示当前行棋方*/
structpointgCursor;/*光标在棋盘上的位置*/
chargChessBoard[19][19];/*用于记录棋盘上各点的状态*/
/**********************************************************/
/**********************************************************/
/*主函数*/
voidmain()
{
intpress;
intbOutWhile=FALSE;/*退出循环标志*/
Init();/*初始化图象,数据*/
while(1)
{
press=GetKey();/*获取用户的按键值*/
switch(CheckKey(press))/*判断按键类别*/
{
/*是退出键*/
caseKEYEXIT:
clrscr();/*清屏*/
bOutWhile=TRUE;
break;
/*是落子键*/
caseKEYFALLCHESS:
if(ChessGo(gPlayOrder,gCursor)==FALSE)/*走棋*/
DoError();/*落子错误*/
else
{
DoOK();/*落子正确*/
/*如果当前行棋方赢棋*/
if(JudgeWin(gPlayOrder,gCursor)==TRUE)
{
DoWin(gPlayOrder);
bOutWhile=TRUE;/*退出循环标志置为真*/
}
/*否则*/
else
/*交换行棋方*/
ChangeOrder();
}
break;
/*是光标移动键*/
caseKEYMOVECURSOR:
MoveCursor(gPlayOrder,press);
break;
/*是无效键*/
caseKEYINVALID:
break;
}
if(bOutWhile==TRUE)
break;
}
/*游戏结束*/
EndGame();
}
/**********************************************************/
/*界面初始化,数据初始化*/
voidInit(void)
{
inti,j;
char*Msg[]=
{
Player1key:,
UP----w,
DOWN--s,
LEFT--a,
RIGHT-d,
DO----space,
,
Player2key:,
UP----up,
DOWN--down,
LEFT--left,
RIGHT-right,
DO----ENTER,
,
exitgame:,
ESC,
NULL,
};
/*先手方为1号玩家*/
gPlayOrder=CHESS1;
/*棋盘数据清零,即棋盘上各点开始的时候都没有棋子*/
for(i=0;i<19;i++)
for(j=0;j<19;j++)
gChessBoard[i][j]=CHESSNULL;
/*光标初始位置*/
gCursor.x=gCursor.y=0;
/*画棋盘*/
textmode(C40);
DrawMap();
/*显示操作键说明*/
i=0;
textcolor(BROWN);
while(Msg[i]!=NULL)
{
gotoxy(25,3+i);
cputs(Msg[i]);
i++;
}
/*显示当前行棋方*/
ShowOrderMsg(gPlayOrder);
/*光标移至棋盘的左上角点处*/
gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT);
}
/*画棋盘*/
voidDrawMap(void)
{
inti,j;
clrscr();
for(i=0;i<19;i++)
for(j=0;j<19;j++)
DrawCross(i,j);
}
/*画棋盘上的交叉点*/
voidDrawCross(intx,inty)
{
gotoxy(x+MAPXOFT,y+MAPYOFT);
/*交叉点上是一号玩家的棋子*/
if(gChessBoard[x][y]==CHESS1)
{
textcolor(LIGHTBLUE);
putch(CHESS1);
return;
}
/*交叉点上是二号玩家的棋子*/
if(gChessBoard[x][y]==CHESS2)
{
textcolor(LIGHTBLUE);
putch(CHESS2);
return;
}
textcolor(GREEN);
/*左上角交叉点*/
if(x==0&&y==0)
{
putch(CROSSLU);
return;
}
/*左下角交叉点*/
if(x==0&&y==18)
{
putch(CROSSLD);
return;
}
/*右上角交叉点*/
if(x==18&&y==0)
{
putch(CROSSRU);
return;
}
/*右下角交叉点*/
if(x==18&&y==18)
{
putch(CROSSRD);
return;
}
/*左边界交叉点*/
if(x==0)
{
putch(CROSSL);
return;
}
/*右边界交叉点*/
if(x==18)
{
putch(CROSSR);
return;
}
/*上边界交叉点*/
if(y==0)
{
putch(CROSSU);
return;
}
/*下边界交叉点*/
if(y==18)
{
putch(CROSSD);
return;
}
/*棋盘中间的交叉点*/
putch(CROSS);
}
/*交换行棋方*/
intChangeOrder(void)
{
if(gPlayOrder==CHESS1)
gPlayOrder=CHESS2;
else
gPlayOrder=CHESS1;
return(gPlayOrder);
}
/*获取按键值*/
intGetKey(void)
{
charlowbyte;
intpress;
while(bioskey(1)==0)
;/*如果用户没有按键,空循环*/
press=bioskey(0);
lowbyte=press&0xff;
press=press&0xff00+toupper(lowbyte);
return(press);
}
/*落子错误处理*/
voidDoError(void)
{
sound(1200);
delay(50);
nosound();
}
/*赢棋处理*/
voidDoWin(intOrder)
{
sound(1500);delay(100);
sound(0);delay(50);
sound(800);delay(100);
sound(0);delay(50);
sound(1500);delay(100);
sound(0);delay(50);
sound(800);delay(100);
sound(0);delay(50);
nosound();
textcolor(RED+BLINK);
gotoxy(25,20);
if(Order==CHESS1)
cputs(PLAYER1WIN!);
else
cputs(PLAYER2WIN!);
gotoxy(25,21);
cputs(\\/);
getch();
}
/*走棋*/
intChessGo(intOrder,structpointCursor)
{
/*判断交叉点上有无棋子*/
if(gChessBoard[Cursor.x][Cursor.y]==CHESSNULL)
{
/*若没有棋子,则可以落子*/
gotoxy(Cursor.x+MAPXOFT,Cursor.y+MAPYOFT);
textcolor(LIGHTBLUE);
putch(Order);
gotoxy(Cursor.x+MAPXOFT,Cursor.y+MAPYOFT);
gChessBoard[Cursor.x][Cursor.y]=Order;
returnTRUE;
}
else
returnFALSE;
}
/*判断当前行棋方落子后是否赢棋*/
intJudgeWin(intOrder,structpointCursor)
{
inti;
for(i=0;i<4;i++)
/*判断在指定方向上是否有连续5个行棋方的棋子*/
if(JudgeWinLine(Order,Cursor,i))
returnTRUE;
returnFALSE;
}
/*判断在指定方向上是否有连续5个行棋方的棋子*/
intJudgeWinLine(intOrder,structpointCursor,intdirection)
{
inti;
structpointpos,dpos;
constinttestnum=5;
intcount;
switch(direction)
{
case0:/*在水平方向*/
pos.x=Cursor.x-(testnum-1);
pos.y=Cursor.y;
dpos.x=1;
dpos.y=0;
break;
case1:/*在垂直方向*/
pos.x=Cursor.x;
pos.y=Cursor.y-(testnum-1);
dpos.x=0;
dpos.y=1;
break;
case2:/*在左下至右上的斜方向*/
pos.x=Cursor.x-(testnum-1);
pos.y=Cursor.y+(testnum-1);
dpos.x=1;
dpos.y=-1;
break;
case3:/*在左上至右下的斜方向*/
pos.x=Cursor.x-(testnum-1);
pos.y=Cursor.y-(testnum-1);
dpos.x=1;
dpos.y=1;
break;
}
count=0;
for(i=0;i<testnum*2+1;i++)
{
if(pos.x>=0&&pos.x=0&&pos.y<=18)
{
if(gChessBoard[pos.x][pos.y]==Order)
{
count++;
if(count>=testnum)
returnTRUE;
}
else
count=0;
}
pos.x+=dpos.x;
pos.y+=dpos.y;
}
returnFALSE;
}
/*移动光标*/
voidMoveCursor(intOrder,intpress)
{
switch(press)
{
casePLAY1UP:
if(Order==CHESS1&&gCursor.y>0)
gCursor.y--;
break;
casePLAY1DOWN:
if(Order==CHESS1&&gCursor.y<18)
gCursor.y++;
break;
casePLAY1LEFT:
if(Order==CHESS1&&gCursor.x>0)
gCursor.x--;
break;
casePLAY1RIGHT:
if(Order==CHESS1&&gCursor.x<18)
gCursor.x++;
break;
casePLAY2UP:
if(Order==CHESS2&&gCursor.y>0)
gCursor.y--;
break;
casePLAY2DOWN:
if(Order==CHESS2&&gCursor.y<18)
gCursor.y++;
break;
casePLAY2LEFT:
if(Order==CHESS2&&gCursor.x>0)
gCursor.x--;
break;
casePLAY2RIGHT:
if(Order==CHESS2&&gCursor.x<18)
gCursor.x++;
break;
}
gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT);
}
/*游戏结束处理*/
voidEndGame(void)
{
textmode(C80);
}
/*显示当前行棋方*/
voidShowOrderMsg(intOrder)
{
gotoxy(6,MAPYOFT+20);
textcolor(LIGHTRED);
if(Order==CHESS1)
cputs(Player1go!);
else
cputs(Player2go!);
gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT);
}
/*落子正确处理*/
voidDoOK(void)
{
sound(500);
delay(70);
sound(600);
delay(50);
sound(1000);
delay(100);
nosound();
}
/*检查用户的按键类别*/
intCheckKey(intpress)
{
if(press==ESCAPE)
returnKEYEXIT;/*是退出键*/
else
if
((press==PLAY1DO&&gPlayOrder==CHESS1)||
(press==PLAY2DO&&gPlayOrder==CHESS2)
)
returnKEYFALLCHESS;/*是落子键*/
else
if
(press==PLAY1UP||press==PLAY1DOWN||
press==PLAY1LEFT||press==PLAY1RIGHT||
press==PLAY2UP||press==PLAY2DOWN||
press==PLAY2LEFT||press==PLAY2RIGHT
)
returnKEYMOVECURSOR;/*是光标移动键*/
else
returnKEYINVALID;/*按键无效*/
}