//五子棋小游戏 #include #include #include #include //使用getch()函数 int startchoice,winner,player,Q[200][200]= {0}; //Q数组记录旗子 char button; //读入键盘输入的指令,如→ struct Point { //点坐标的结构体 int x,y; } point,game_xy; struct Piece { //棋子的坐标记录 struct Point coord; struct Piece *fore; }; struct Piece *head,*p,*ptr,*ptr1; struct Point win_point[5]; void goto_xy(int x, int y) { //光标移动函数 COORD c; c.X=2*x; c.Y=y; SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE), c); } void Init() { //初始化函数,将记录棋子的数组初始化 for(int i=0; i<200; i++) for(int j=0; j<200; j++) Q[i][j]=0; startchoice=0; player=1; p=(struct Piece *)malloc(sizeof(struct Piece)); head=p; } void Welcome() { //欢迎界面 system("color B0"); //#include B 背景淡浅绿色 0 字体黑色 goto_xy(10,3); printf("-→"); goto_xy(17,1); printf("主菜单"); goto_xy(13,3); printf(" ***人人对战***"); goto_xy(13,4); printf(" ***退出***"); point.x=12; point.y=3; goto_xy(0,0); } void ShowWho() { //显示轮到哪一方下棋 goto_xy(17,24); if(player==0) printf("轮到甲方落子"); else printf("轮到乙方落子"); goto_xy(point.x,point.y); } void Draw() { //绘画游戏界面 game_xy.x=10; game_xy.y=3; system("cls"); system("color 3F"); //3 湖蓝色 F 亮白色 goto_xy(15,1); printf("欢迎play our 五子棋!"); /*goto_xy(29,22); printf("重新开始 r");*/ goto_xy(1,24); printf("悔棋 b"); goto_xy(1,25); printf("退出 ESC"); const int i=8; //const 定义的数据不可以被改变 而且修改数据比较方便 const int j=19; const int k=3; goto_xy(game_xy.x-i,game_xy.y+k); //输出甲方的下棋方法 printf("甲方: ●"); goto_xy(game_xy.x-i,game_xy.y+k+2); printf("移动: 上 W"); goto_xy(game_xy.x-i,game_xy.y+k+4); printf(" 下 S"); goto_xy(game_xy.x-i,game_xy.y+k+6); printf(" 左 A"); goto_xy(game_xy.x-i,game_xy.y+k+8); printf(" 右 D "); goto_xy(game_xy.x-i,game_xy.y+k+10); printf("落子: 空 格"); goto_xy(game_xy.x+j,game_xy.y+k); //输出乙方的下棋方法 printf("乙方: ○"); goto_xy(game_xy.x+j,game_xy.y+k+2); printf("移动: 上 ↑"); goto_xy(game_xy.x+j,game_xy.y+k+4); printf(" 下 ↓"); goto_xy(game_xy.x+j,game_xy.y+k+6); printf(" 左 ←"); goto_xy(game_xy.x+j,game_xy.y+k+8); printf(" 右 →"); goto_xy(game_xy.x+j,game_xy.y+k+10); printf("落子: Enter"); for(int k1=0; k1<200; k1++) //初始化棋子记录,在第二局时有明确的作用 for(int k2=0; k2<200; k2++) Q[k1][k2]=0; for(int i=0; i<20; i++) { //画棋盘 if(i==0) { //画第一行 goto_xy(10,i+3); printf("┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐"); } if(i!=0&&i!=19) { //画出中间16行 goto_xy(10,i+3); printf("├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤"); } if(i==19) { //画最后一行 goto_xy(10,i+3); printf("└┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘"); } } point.x=19; point.y=12; goto_xy(19,12); } void Clean() { //清除-→运动的轨迹 goto_xy(10,3); printf(" "); goto_xy(24,3); printf(" "); goto_xy(10,4); printf(" "); goto_xy(24,4); printf(" "); } void menu_choose(char press) { //选择游戏还是退出 if(press==72) { //↑的ASCLL码 if(point.y==3) point.y=4; else point.y=3; Clean(); goto_xy(10,point.y); printf("-→"); } if(press==80) { //↓的ASCLL码 if(point.y==4) point.y=3; else point.y=4; Clean(); goto_xy(10,point.y); printf("-→"); } if(press==13) { // 13:回车键的ASCLL码 startchoice=point.y-2; //startchoice 为1或2 } } void go_back(int x1,int y1) { //悔棋函数 goto_xy(x1,y1); if(x1==10) { if(y1==3) { printf("┌"); } else if(y1==20) { printf("└"); } else { printf("├"); } } else if(x1==27) { if(y1==3) { printf("┐"); } else if(y1==20) { printf("┘"); } else { printf("┤"); } } else { if(y1==3) { printf("┬"); } else if(y1==20) { printf("┴"); } else { printf("┼"); } } Q[point.x][point.y]=0; //在数组中将弹出的棋子对应的数据设为0 goto_xy(x1,y1); } void Record() { //记录棋子的情况 p->coord.x=point.x; p->coord.y=point.y; ptr=p; p=(struct Piece *)malloc(sizeof(struct Piece)); p->fore=ptr; ShowWho(); Q[point.x][point.y]=player+1; if(player) { player=0; return; } player=1; goto_xy(point.x,point.y); } void PutDown() { //显示落子函数 if(Q[point.x][point.y]==0) { //先判断该位置是否有棋子 if(player) { printf("●"); printf("\a"); //'\a'表示蜂鸣声 Record(); } else { printf("○"); printf("\a"); Record(); } goto_xy(point.x,point.y); } } void Play(char ch) { //键盘的操作 移动光标 下棋和悔棋操作 if(player==1) { //甲方 if(ch== 'W' || ch=='w') //W 光标上移 { if(point.y<=3) point.y=22; else point.y--; goto_xy(point.x,point.y); } if(ch=='A' || ch=='a') { //A 光标左移 if(point.x<=10) point.x=20; else point.x--; goto_xy(point.x,point.y); } if(ch=='D' || ch=='d') { //D 光标右移 if(point.x>=20) point.x=10; else point.x++; goto_xy(point.x,point.y); } if(ch=='S' || ch=='s') { //S 光标下移 if(point.y>=22) point.y=3; else point.y++; goto_xy(point.x,point.y); } if(ch==32) { //空格键的ASCLL码 下棋 PutDown(); } } else { if(ch==72) { //↑的ASCLL码 光标上移 if(point.y<=3) point.y=22; else point.y--; goto_xy(point.x,point.y); } if(ch==75) { //←的ASCLL码 光标左移 if(point.x<=10) point.x=20; else point.x--; goto_xy(point.x,point.y); } if(ch==77) { //→的ASCLL码 光标右移 if(point.x>=20) point.x=10; else point.x++; goto_xy(point.x,point.y); } if(ch==80) { //↓的ASCLL码 光标下移 if(point.y>=22) point.y=3; else point.y++; goto_xy(point.x,point.y); } if(ch==13) { //回车键的ASCLL码 下棋 PutDown(); } } if(button=='b'||button=='B') { //悔棋的操作 ptr1=p; if(p!=head) { p=p->fore; free(ptr1); point.x=p->coord.x; point.y=p->coord.y; go_back(point.x,point.y); } } } void judgeWinRecodePointXY(int count, int rr, int cc){ win_point[count].x=rr; //记录坐标 win_point[count].y=cc; //记录坐标 } void judgeWinSetPointCOlor() { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//创建并实例化句柄 CONSOLE_SCREEN_BUFFER_INFO csbiInfo; //获取当前颜色 GetConsoleScreenBufferInfo(handle, &csbiInfo); //获取当前颜色 WORD wOldColorAttrs = csbiInfo.wAttributes; //获取当前颜色 SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY |FOREGROUND_RED|BACKGROUND_INTENSITY|BACKGROUND_GREEN); //设置输出的新颜色 for(int i=0; i<5; i++) { //重新输出一遍 goto_xy(win_point[i].x, win_point[i].y); if(!player) { //谁赢谁就是最后下了一子,那么player变量就反向了 printf("●"); } else { printf("○"); } } SetConsoleTextAttribute(handle, wOldColorAttrs); //恢复原来的颜色 } int Judge() { int count=0; int pp=player==0?2:1; //三目运算 for(int c=0; c<200; c++) { for(int r=0; r<200; r++) { if(Q[r][c]!=pp) continue; //检查列 int rr=r; int cc=c; judgeWinRecodePointXY(count, rr, cc); //记录坐标 while(--cc>=3 &&Q[rr][cc]==pp) { count++; judgeWinRecodePointXY(count, rr, cc); //记录坐标 } cc=c; judgeWinRecodePointXY(count, rr, cc); //记录坐标 while(++cc<23 &&Q[rr][cc]==pp) { count++; judgeWinRecodePointXY(count, rr, cc); //记录坐标 } cc=c; if(count>=4) { judgeWinSetPointCOlor(); return pp; } //检查行 count=0; judgeWinRecodePointXY(count, rr, cc); //记录坐标 while(--rr>=10 &&Q[rr][cc]==pp) { count++; judgeWinRecodePointXY(count, rr, cc); //记录坐标 } rr=r; judgeWinRecodePointXY(count, rr, cc); //记录坐标 while(++rr<30 &&Q[rr][cc]==pp) { count++; judgeWinRecodePointXY(count, rr, cc); //记录坐标 } rr=r; if(count>=4) { judgeWinSetPointCOlor(); return pp; } //检查反斜边 count=0; judgeWinRecodePointXY(count, rr, cc); //记录坐标 cc--; rr--; while((cc>=3||rr>=10) &&Q[rr][cc]==pp) { count++; judgeWinRecodePointXY(count, rr, cc); //记录坐标 cc--; rr--; } rr=r; cc=c; judgeWinRecodePointXY(count, rr, cc); //记录坐标 cc++; rr++; while((cc<23||rr<30) &&Q[rr][cc]==pp) { count++; judgeWinRecodePointXY(count, rr, cc); //记录坐标 cc++; rr++; } rr=r; cc=c; if(count>=4) { judgeWinSetPointCOlor(); return pp; } //检查正斜边 count=0; judgeWinRecodePointXY(count, rr, cc); //记录坐标 cc++; rr--; while((cc<23||rr>=10) &&Q[rr][cc]==pp) { judgeWinRecodePointXY(count, rr, cc); //记录坐标 count++; cc++; rr--; } rr=r; cc=c; judgeWinRecodePointXY(count, rr, cc); //记录坐标 cc--; rr++; while((cc>=3||rr<30) &&Q[rr][cc]==pp) { judgeWinRecodePointXY(count, rr, cc); //记录坐标 count++; cc--; rr++; } rr=r; cc=c; if(count>=4) { judgeWinSetPointCOlor(); return pp; } count=0; } } return 0; } int main(void) { int j=0,k=0; system("color 4E"); //#include 4 背景红色 E 字体淡黄色 printf("\n 欢迎play五子棋!"); goto_xy(15,3); printf("作者:杜盼"); goto_xy(17,5); printf(" 周拓"); Sleep(3000); system("cls"); while(1) { Init(); //初始化 int winner=0; Welcome(); //欢迎界面 while(1) { //读取菜单选项 char choice=getch(); menu_choose(choice); if(startchoice!=0) break; } if(startchoice==1) { //选择人人对战 Draw(); goto_xy(17,24); printf("轮到甲方落子"); goto_xy(point.x,point.y); while(1) { button=getch(); Play(button); //读取键盘的操作 移动光标 下棋和悔棋操作 if(button==27) { //ESC的ASCLL码 if(MessageBox(NULL,TEXT("确定退出?"),TEXT(""),MB_ICONQUESTION|MB_OKCANCEL)==IDOK) { system("cls"); printf("\n 谢谢使用!\n"); return 0; } } if(button==13 || button==32) //回车键或者空格键ASCLL码 按下后开始判断输赢 winner=Judge(); if(winner!=0) { goto_xy(15,26); if(winner==2) { printf("恭喜!甲方赢!\n"); j=j+1; } if(winner==1) { printf("恭喜!乙方赢!\n"); k=k+1; } goto_xy(29,24); printf("甲 %d : %d 乙",j,k); } if(winner!=1&&winner!=2) { continue; } goto_xy(13,24); printf(" 继续游戏?(Y/N): "); while(1) { button=getch(); if(button=='n'||button=='N'||button=='y'||button=='Y') break; } if(button=='n'||button=='N') { if(MessageBox(NULL,TEXT(" 确定退出?"),TEXT(""),MB_ICONQUESTION|MB_OKCANCEL)==IDOK) { system("cls"); printf("\n 谢谢使用!\n"); return 0; } } if(button=='y'||button=='Y') { winner=0; system("cls"); break; } } } if(startchoice==2) { if(MessageBox(NULL,TEXT(" 确定退出?"),TEXT(""),MB_ICONQUESTION|MB_OKCANCEL)==IDOK) { printf("\n\n 谢谢使用!\n"); return 0; } } } return 0; }