You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dpzt/升级版(着色构成连珠的5个子).cpp

555 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//五子棋小游戏
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include<conio.h> //使用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<windows.h> 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<windows.h> 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;
}