怎么用C语言写五子棋游戏
创始人
2024-12-24 23:01:44
0次
#include #include #include #include #include #define CROSSRU 0xbf /*右上角点*/#define CROSSLU 0xda /*左上角点*/#define CROSSLD 0xc0 /*左下角点*/#define CROSSRD 0xd9 /*右下角点*/#define CROSSL 0xc3 /*左边*/#define CROSSR 0xb4 /*右边*/#define CROSSU 0xc2 /*上边*/#define CROSSD 0xc1 /*下边*/#define CROSS 0xc5 /*十字交叉点*/ /*定义棋盘左上角点在屏幕上的位置*/#define MAPXOFT 5#define MAPYOFT 2 /*定义1号玩家的操作键键码*/#define PLAY1UP 0x1157/*上移--'W'*/#define PLAY1DOWN 0x1f53/*下移--'S'*/#define PLAY1LEFT 0x1e41/*左移--'A'*/#define PLAY1RIGHT 0x2044/*右移--'D'*/#define PLAY1DO 0x3920/*落子--空格键*/ /*定义2号玩家的操作键键码*/#define PLAY2UP 0x4800/*上移--方向键up*/#define PLAY2DOWN 0x5000/*下移--方向键down*/#define PLAY2LEFT 0x4b00/*左移--方向键left*/#define PLAY2RIGHT 0x4d00/*右移--方向键right*/#define PLAY2DO 0x1c0d/*落子--回车键Enter*/ /*若想在游戏中途退出, 可按 Esc 键*/#define ESCAPE 0x011b /*定义棋盘上交叉点的状态, 即该点有无棋子 *//*若有棋子, 还应能指出是哪个玩家的棋子 */#define CHESSNULL 0 /*没有棋子*/#define CHESS1 'O'/*一号玩家的棋子*/#define CHESS2 'X'/*二号玩家的棋子*/ /*定义按键类别*/#define KEYEXIT 0/*退出键*/#define KEYFALLCHESS 1/*落子键*/#define KEYMOVECURSOR 2/*光标移动键*/#define KEYINVALID 3/*无效键*/ /*定义符号常量: 真, 假 --- 真为1, 假为0 */#define TRUE 1#define FALSE 0 /**********************************************************//* 定义数据结构 */ /*棋盘交叉点坐标的数据结构*/struct point{int x,y;}; /**********************************************************//*自定义函数原型说明 */void Init(void);int GetKey(void);int CheckKey(int press);int ChangeOrder(void);int ChessGo(int Order,struct point Cursor);void DoError(void);void DoOK(void);void DoWin(int Order);void MoveCursor(int Order,int press);void DrawCross(int x,int y);void DrawMap(void);int JudgeWin(int Order,struct point Cursor);int JudgeWinLine(int Order,struct point Cursor,int direction);void ShowOrderMsg(int Order);void EndGame(void);/**********************************************************/ /**********************************************************//* 定义全局变量 */int gPlayOrder; /*指示当前行棋方 */struct point gCursor; /*光标在棋盘上的位置 */char gChessBoard[19][19];/*用于记录棋盘上各点的状态*//**********************************************************/ /**********************************************************//*主函数*/void main(){int press;int bOutWhile=FALSE;/*退出循环标志*/printf("Welcome [url]www.schoolhacker.com[/url]");Init();/*初始化图象,数据*/ while(1){press=GetKey();/*获取用户的按键值*/switch(CheckKey(press))/*判断按键类别*/{/*是退出键*/case KEYEXIT:clrscr();/*清屏*/bOutWhile = TRUE;break; /*是落子键*/case KEYFALLCHESS:if(ChessGo(gPlayOrder,gCursor)==FALSE)/*走棋*/DoError();/*落子错误*/else{DoOK();/*落子正确*/ /*如果当前行棋方赢棋*/if(JudgeWin(gPlayOrder,gCursor)==TRUE){DoWin(gPlayOrder);bOutWhile = TRUE;/*退出循环标志置为真*/}/*否则*/else/*交换行棋方*/ChangeOrder();ShowOrderMsg(gPlayOrder);}break; /*是光标移动键*/case KEYMOVECURSOR:MoveCursor(gPlayOrder,press);break; /*是无效键*/case KEYINVALID:break;} if(bOutWhile==TRUE)break;} /*游戏结束*/EndGame();}/**********************************************************/ /*界面初始化,数据初始化*/void Init(void){int i,j;char *Msg[]={"Player1 key:"," UP----w"," DOWN--s"," LEFT--a"," RIGHT-d"," DO----space","","Player2 key:"," UP----up"," DOWN--down"," LEFT--left"," RIGHT-right"," DO----ENTER","","exit game:"," 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);} /*画棋盘*/void DrawMap(void){int i,j; clrscr(); for(i=0;i<19;i++)for(j=0;j<19;j++)DrawCross(i,j); } /*画棋盘上的交叉点*/void DrawCross(int x,int y){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);} /*交换行棋方*/int ChangeOrder(void){if(gPlayOrder==CHESS1)gPlayOrder=CHESS2;elsegPlayOrder=CHESS1; return(gPlayOrder);} /*获取按键值*/int GetKey(void){char lowbyte;int press; while (bioskey(1) == 0);/*如果用户没有按键,空循环*/ press=bioskey(0);lowbyte=press&0xff;press=press&0xff00 + toupper(lowbyte);return(press);} /*落子错误处理*/void DoError(void){sound(1200);delay(50);nosound();} /*赢棋处理*/void DoWin(int Order){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("PLAYER1 WIN!");elsecputs("PLAYER2 WIN!");gotoxy(25,21);cputs(" \\<^+^>/");getch();} /*走棋*/int ChessGo(int Order,struct point Cursor){/*判断交叉点上有无棋子*/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;return TRUE;}elsereturn FALSE;} /*判断当前行棋方落子后是否赢棋*/int JudgeWin(int Order,struct point Cursor){int i;for(i=0;i<4;i++)/*判断在指定方向上是否有连续5个行棋方的棋子*/if(JudgeWinLine(Order,Cursor,i))return TRUE;return FALSE;} /*判断在指定方向上是否有连续5个行棋方的棋子*/int JudgeWinLine(int Order,struct point Cursor,int direction){int i;struct point pos,dpos;const int testnum = 5;int count; switch(direction){case 0:/*在水平方向*/pos.x=Cursor.x-(testnum-1);pos.y=Cursor.y;dpos.x=1;dpos.y=0;break;case 1:/*在垂直方向*/pos.x=Cursor.x;pos.y=Cursor.y-(testnum-1);dpos.x=0;dpos.y=1;break;case 2:/*在左下至右上的斜方向*/pos.x=Cursor.x-(testnum-1);pos.y=Cursor.y+(testnum-1);dpos.x=1;dpos.y=-1;break;case 3:/*在左上至右下的斜方向*/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=0&&pos.x<=18&&pos.y>=0&&pos.y<=18){if(gChessBoard[pos.x][pos.y]==Order){count++;if(count>=testnum)return TRUE;}elsecount=0;}pos.x+=dpos.x;pos.y+=dpos.y;} return FALSE;} /*移动光标*/void MoveCursor(int Order,int press){switch(press){case PLAY1UP:if(Order==CHESS1&&gCursor.y>0)gCursor.y--;break;case PLAY1DOWN:if(Order==CHESS1&&gCursor.y<18)gCursor.y++;break;case PLAY1LEFT:if(Order==CHESS1&&gCursor.x>0)gCursor.x--;break;case PLAY1RIGHT:if(Order==CHESS1&&gCursor.x<18)gCursor.x++;break; case PLAY2UP:if(Order==CHESS2&&gCursor.y>0)gCursor.y--;break;case PLAY2DOWN:if(Order==CHESS2&&gCursor.y<18)gCursor.y++;break;case PLAY2LEFT:if(Order==CHESS2&&gCursor.x>0)gCursor.x--;break;case PLAY2RIGHT:if(Order==CHESS2&&gCursor.x<18)gCursor.x++;break;} gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT);} /*游戏结束处理*/void EndGame(void){textmode(C80);} /*显示当前行棋方*/void ShowOrderMsg(int Order){gotoxy(6,MAPYOFT+20);textcolor(LIGHTRED);if(Order==CHESS1)cputs("Player1 go!");elsecputs("Player2 go!"); gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT);} /*落子正确处理*/void DoOK(void){sound(500);delay(70);sound(600);delay(50);sound(1000);delay(100);nosound();} /*检查用户的按键类别*/int CheckKey(int press){if(press==ESCAPE)return KEYEXIT;/*是退出键*/ elseif( ( press==PLAY1DO && gPlayOrder==CHESS1) ||( press==PLAY2DO && gPlayOrder==CHESS2))return KEYFALLCHESS;/*是落子键*/ elseif( press==PLAY1UP || press==PLAY1DOWN ||press==PLAY1LEFT || press==PLAY1RIGHT ||press==PLAY2UP || press==PLAY2DOWN ||press==PLAY2LEFT || press==PLAY2RIGHT)return KEYMOVECURSOR;/*是光标移动键*/ elsereturn KEYINVALID;/*按键无效*/}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...