//转自:https://www.luogu.com.cn/paste/c1fvaio2
//作者:https://www.luogu.com.cn/user/217233
/*
制作者:SqrtSecond
版本号:v1.1.9
v1.1.9更新内容:
压行
v1.1.8更新内容:
修复了一些bug
v1.1.7更新内容:
增加了设置页面和两个功能
v1.1.6更新内容:
1.增强了人机程序
2.修复了一些bug
3.更新了单人游戏的操作系统
v1.1.5更新内容:
1.修改了棋盘边框系统,使64位电脑与32位电脑兼容
2.修改了键盘的控制系统
3.增加新功能:按Enter或空格键可快速跳过剧情。
4.更新了5次神秘事件之后的buff特效
5.新增了人机系统和单人游戏
可以转载,但请务必注明出处!
*/
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
int Speed=3,pianhao=1;
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)&0x8000)?1:0)
#define color(COLOR) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),COLOR);
void putss(string a)
{
while(KEY_DOWN('\r')||KEY_DOWN(' '));
bool flag=true;int len=a.length();
for(int i=0;i<len-1;++i)
{
if(KEY_DOWN('\r')||KEY_DOWN(' '))flag=false;
putchar(a[i]);
if(flag)Sleep(Speed*10);
}
putchar(a[len-1]);
while(KEY_DOWN('\r')||KEY_DOWN(' '));
}
int win1,win2,AIturn;bool flag,p;
int game(int turn);
void hint();
int Setting()
{
system("cls");
puts("速度调节——s\n");
puts("键盘偏好——k\n");
puts("退出——e\n");
while(true)
{
if(KEY_DOWN('E')){while(KEY_DOWN('E'));return 0;}
if(KEY_DOWN('S'))
{
while(true)
{
system("cls");
color(112);for(int i=1;i<=6-Speed;++i)puts(" ");
color(7);for(int i=6-Speed+1;i<=5;++i)puts("");
printf("当前速度:%d\n",6-Speed);
puts("按方向上下键进行设置,E键退出\n");
while(true)
{
if(KEY_DOWN(VK_UP))
{
while(KEY_DOWN(VK_UP));
Speed++;
if(Speed==6)Speed=5;
break;
}
if(KEY_DOWN(VK_DOWN))
{
while(KEY_DOWN(VK_DOWN));
Speed--;
if(Speed==0)Speed=1;
break;
}
if(KEY_DOWN('E')){while(KEY_DOWN('E'));return 1;}
}
}
}
if(KEY_DOWN('K'))
{
while(true)
{
system("cls");
puts("按左右键进行设置,E键退出\n");
puts(pianhao==0?"当前偏好:wsad控制方向,空格键放置棋子":"当前偏好:方向键控制方向,Enter键放置棋子");
puts("\n注:本设置仅在单人游戏时有效");
while(true)
{
if(KEY_DOWN(VK_LEFT)||KEY_DOWN(VK_RIGHT))
{
pianhao=1-pianhao;
while(KEY_DOWN(VK_LEFT)||KEY_DOWN(VK_RIGHT));
break;
}
if(KEY_DOWN('E')){while(KEY_DOWN('E'));return 1;}
}
}
}
}
}
int home()
{
system("cls");
puts("主菜单\n");
puts("开始游戏 —— s\n");
puts("游戏说明 —— h\n");
puts("设置 —— p\n");
puts("退出 —— e\n");
puts("制作人:SqrtSecond\n");
puts("(P.S.按Enter或空格键可快速跳过剧情)");
while(true)
{
if(KEY_DOWN('E'))
{
while(true)
{
system("cls");
puts("确定要离开吗?\n");
puts("是 —— y\n");
puts("否 —— n\n");
while(true)
{
if(KEY_DOWN('N'))return 1;
if(KEY_DOWN('Y'))
{
system("cls");
puts("qwq");
return 0;
}
}
}
}
if(KEY_DOWN('H'))
{
hint();
return 1;
}
if(KEY_DOWN('P'))
{
while(Setting());
return 1;
}
if(KEY_DOWN('S'))
{
system("cls");
putss("那么,开始游戏吧!\n");system("pause");
system("cls");
puts("你要玩什么模式?\n");
puts("单人,人机先走——a\n");
puts("单人,人机后走——b\n");
puts("双人——c\n");
win1=win2=0;p=0;
while(true)
{
if(KEY_DOWN('A'))AIturn=1,p=1;
if(KEY_DOWN('B'))AIturn=-1,p=1;
if(KEY_DOWN('C'))AIturn=0,p=1;
if(p)
{
putss("好的,开始吧!");system("pause");
int r=1;
while(true)
{r=-game(r);if(r==0)break;}
return 1;
}
}
}
}
}
void hint()
{
system("cls");
putss("首先,这是一个双人游戏。\n");system("pause");
putss("基本规则和标准的三子棋相同。\n");system("pause");
putss("双方需要每人轮流下一手。\n");system("pause");
putss("每人下完一手后,都会触发一个随机的事件。\n");system("pause");
putss("有可能会消除场上已有的棋子……\n");system("pause");
putss("但也有可能帮你多下一手棋!\n");system("pause");
putss("这正是这个游戏的好玩之处。\n");system("pause");
putss("也很靠运气。\n");system("pause");
putss("另外……\n");system("pause");
putss("别触发5次神秘事件,否则后果自负……\n");system("pause");
putss("准备好了就开始吧!\n");system("pause");
return;
}
int mp[5][5],X,Y;
void putchess()
{
system("cls");
printf("比分:%d:%d\n\n",win1,win2);
puts("◤ ◥");
for(int i=1;i<=3;++i)
{
printf(" ");
for(int j=1;j<=3;++j)
{
if(X==i&&Y==j)color(112);
printf(mp[i][j]==1?"×":mp[i][j]==-1?"○":" ");
if(X==i&&Y==j)color(7);
}
puts(" ");
}
puts("◣ ◢");
}
int l;
int win()
{
l=0;
for(int i=1;i<=3;++i)
{
if(mp[i][1]+mp[i][2]+mp[i][3]==3)l=1;
if(mp[i][1]+mp[i][2]+mp[i][3]==-3)l=-1;
if(mp[1][i]+mp[2][i]+mp[3][i]==3)l=1;
if(mp[1][i]+mp[2][i]+mp[3][i]==-3)l=-1;
}
if(mp[1][1]+mp[2][2]+mp[3][3]==3)l=1;
if(mp[1][1]+mp[2][2]+mp[3][3]==-3)l=-1;
if(mp[1][3]+mp[2][2]+mp[3][1]==3)l=1;
if(mp[1][3]+mp[2][2]+mp[3][1]==-3)l=-1;
if(l==0)
{
l=2;
for(int i=1;i<=3;++i)for(int j=1;j<=3;++j)if(mp[i][j]==0)l=0;
}
if(l==2)
{
putchess();
printf("恭喜双方打成平局!\n");system("pause");
return true;
}
if(l!=0)
{
putchess();
printf("%s获得了胜利!\n",l==1?(AIturn==1?"人机":AIturn==-1?"玩家":"玩家1"):(AIturn==-1?"人机":AIturn==1?"玩家":"玩家2"));system("pause");
l==1?win1++:win2++;
return true;
}
return false;
}
int xx,yy,h,boom,rx,ry,rz;
void effect(int playyer)
{
rx=rand()%12+1;putchess();
puts("事件发生!\n");system("pause");
if(rx<=4)
{
ry=rand()%3+1;rz=rand()%3+1;mp[ry][rz]=0;
putchess();printf("消除格子(%d,%d)!\n",ry,rz);
}
else if(rx==5)
{
ry=rand()%3+1;mp[ry][1]=mp[ry][2]=mp[ry][3]=0;
putchess();printf("消除第%d行!\n",ry);
}
else if(rx==6)
{
ry=rand()%3+1;mp[1][ry]=mp[2][ry]=mp[3][ry]=0;
putchess();printf("消除第%d列!\n",ry);
}
else if(rx==7)
{
mp[1][1]=mp[2][2]=mp[3][3]=0;
putchess();printf("消除左上到右下的对角线!\n");
}
else if(rx==8)
{
mp[1][3]=mp[2][2]=mp[3][1]=0;
putchess();printf("消除右上到左下的对角线!\n");
}
else if(rx==9)
{
do
{
ry=rand()%3+1;
rz=rand()%3+1;
}while(mp[ry][rz]);
mp[ry][rz]=h;
putchess();printf("帮你下一手(%d,%d)!\n",ry,rz);
}
else if(rx==10)
{
ry=rand()%2;
if(ry)
{
for(int i=1;i<=3;++i)for(int j=1;j<=3;++j)mp[i][j]=-mp[i][j];
putchess();printf("反转局势!!!");h=-h;
}
else puts("无事发生!(偷笑)");
}
else
{
boom++;
if(boom==5)
{
system("color 4F");printf("神秘事件×%d!!!\n",boom);
boom=0;system("pause");
putss("5次神秘事件凑齐了……\n");Sleep(Speed*1000);
putss("Windows的数据遭受了毁灭性的打击!!!\n");Sleep(Speed*1000);
for(int i=1;i<=50;++i){system("color 2C");system("color AE");system("color 7A");system("color E4");system("color 58");system("color B6");}
system("color 4F");
for(int i=1;i<=3;++i)for(int j=1;j<=3;++j)mp[i][j]=0;
putchess();
MessageBox(NULL,"您的Windows可能出现了点问题。","Windows系统自动提示",MB_OK+48);
MessageBox(NULL,"Windows正在尝试修复您的系统中……","Windows系统自动提示",MB_OK+64);
MessageBox(NULL,"系统内部存储器已被破坏!","Windows系统自动提示",MB_OK+48);
putss("数据已被破坏……请重新开始……\n");Sleep(Speed*1000);h=-1;
int x=rand()%2;
if(x){
MessageBox(NULL,"什么?你竟然活下来了!","天理",MB_OK+48);
MessageBox(NULL,"看来要加大打击力度","天理",MB_OK+48);
MessageBox(NULL,"一个计算机病毒以光速传入你的电脑","Windows系统自动提示",MB_OK+48);
system("shutdown -s -t 31");
}
}
else printf("神秘事件×%d!!!\n",boom);
}
system("pause");
if(rx>=11)system("color 07");
}
/*
x=1,2,3,4(1/3):随机消除一个格子
x=5(1/12):随机消除一行
x=6(1/12):随机消除一列
x=7(1/12):消除左上到右下的对角线
x=8(1/12):消除左上到右下的对角线
x=9(1/12):帮自己下一手
x=10(1/12):反转局势或无事发生
x=11,12(1/6):神秘事件
*/
bool player1(){return (((h==1&&AIturn!=-1)||(h==-1&&AIturn==-1))&&pianhao==1)||(((h==1&&AIturn!=1)||(h==-1&&AIturn==1))&&pianhao==0);}
void puthint(){printf("现在轮到%s(执%s)了,你要下在哪一行,哪一列?%s\n",h==1?(AIturn==1?"人机":AIturn==-1?"玩家":"玩家1"):(AIturn==-1?"人机":AIturn==1?"玩家":"玩家2"),h==1?"×":"○",player1()?"(用wsad控制方向,空格键放置棋子)":"(用方向键控制方向,Enter键放置棋子)");}
int AI(int t)
{
for(int i=1;i<=3;++i)
{
if(mp[i][1]+mp[i][2]+mp[i][3]==2*t)return mp[i][1]==0?i*3+1:mp[i][2]==0?i*3+2:i*3+3;
if(mp[1][i]+mp[2][i]+mp[3][i]==2*t)return mp[1][i]==0?1*3+i:mp[2][i]==0?2*3+i:3*3+i;
}
if(mp[1][1]+mp[2][2]+mp[3][3]==2*t)return mp[1][1]==0?4:mp[2][2]==0?8:12;
if(mp[1][3]+mp[2][2]+mp[3][1]==2*t)return mp[1][3]==0?6:mp[2][2]==0?8:10;//判断己方二子连珠
for(int i=1;i<=3;++i)
{
if(mp[i][1]+mp[i][2]+mp[i][3]==-2*t)return mp[i][1]==0?i*3+1:mp[i][2]==0?i*3+2:i*3+3;
if(mp[1][i]+mp[2][i]+mp[3][i]==-2*t)return mp[1][i]==0?1*3+i:mp[2][i]==0?2*3+i:3*3+i;
}
if(mp[1][1]+mp[2][2]+mp[3][3]==-2*t)return mp[1][1]==0?4:mp[2][2]==0?8:12;
if(mp[1][3]+mp[2][2]+mp[3][1]==-2*t)return mp[1][3]==0?6:mp[2][2]==0?8:10;//判断对方二子连珠
if(mp[2][2]==0)return 8;//判中心
if(mp[1][1]+mp[2][2]+mp[3][3]==t&&(mp[1][1]==0||mp[2][2]==0))return mp[2][2]==0?8:mp[1][1]==0?4:12;
if(mp[1][3]+mp[2][2]+mp[3][1]==t&&(mp[1][3]==0||mp[2][2]==0))return mp[2][2]==0?8:mp[1][3]==0?6:10;
for(int i=1;i<=3;++i)
{
if(mp[i][1]+mp[i][2]+mp[i][3]==t&&(mp[i][1]==0||mp[i][2]==0))return mp[i][1]==0?i*3+1:mp[i][3]==0?i*3+3:i*3+2;
if(mp[1][i]+mp[2][i]+mp[3][i]==t&&(mp[1][i]==0||mp[2][i]==0))return mp[1][i]==0?1*3+i:mp[3][i]==0?3*3+i:2*3+i;//判断己方一子连珠
}//判己方一子连珠
return mp[1][1]==0?4:mp[1][3]==0?6:mp[3][1]==0?10:mp[3][3]==0?12:mp[1][2]==0?5:mp[2][1]==0?7:mp[2][3]==0?9:11;
}
int game(int turn)
{
boom=0;h=turn;memset(mp,0,sizeof(mp));
while(true)
{
X=Y=2;putchess();
if(h!=AIturn)
{
puthint();
while(((KEY_DOWN('W')||KEY_DOWN('S')||KEY_DOWN('A')||KEY_DOWN('D')||KEY_DOWN(' '))&&player1())||((KEY_DOWN(VK_UP)||KEY_DOWN(VK_DOWN)||KEY_DOWN(VK_LEFT)||KEY_DOWN(VK_RIGHT)||KEY_DOWN('\r'))&&!player1()));
while(true)
{
if((KEY_DOWN('W')&&player1())||(KEY_DOWN(VK_UP)&&!player1()))
{
X=(X+1)%3+1;
putchess();puthint();
while((KEY_DOWN('W')&&player1())||(KEY_DOWN(VK_UP)&&!player1()));
}
if((KEY_DOWN('A')&&player1())||(KEY_DOWN(VK_LEFT)&&!player1()))
{
Y=(Y+1)%3+1;
putchess();puthint();
while((KEY_DOWN('A')&&player1())||(KEY_DOWN(VK_LEFT)&&!player1()));
}
if((KEY_DOWN('S')&&player1())||(KEY_DOWN(VK_DOWN)&&!player1()))
{
X=(X%3)+1;
putchess();puthint();
while((KEY_DOWN('S')&&player1())||(KEY_DOWN(VK_DOWN)&&!player1()));
}
if((KEY_DOWN('D')&&player1())||(KEY_DOWN(VK_RIGHT)&&!player1()))
{
Y=(Y%3)+1;
putchess();puthint();
while((KEY_DOWN('D')&&player1())||(KEY_DOWN(VK_RIGHT)&&!player1()));
}
if((KEY_DOWN(' ')&&player1())||(KEY_DOWN('\r')&&!player1()))
{
while((KEY_DOWN(' ')&&player1())||(KEY_DOWN('\r')&&!player1()));
if(!mp[X][Y])break;
}
}
}
else
{
puts("人机计算中……");
int m=AI(AIturn),y=(m+2)%3+1,x=(m-y)/3;
if(x==y&&x==2)Sleep(Speed*100);
else if(x+y==3||x+y==5)
{
Sleep(Speed*50);
X=x;Y=y;putchess();puts("人机计算中……");Sleep(Speed*50);
}
else
{
Sleep(Speed*33.33);
X=x;putchess();puts("人机计算中……");Sleep(Speed*33.33);
Y=y;putchess();puts("人机计算中……");Sleep(Speed*33.33);
}
}
mp[X][Y]=h;X=Y=4;
if(win())break;
effect(h);
if(win())break;
h=-h;
}
while(true)
{
system("cls");
puts("要再玩一局吗?\n");
puts("是 —— y\n");
puts("否 —— n\n");
while(true)
{
if(KEY_DOWN('N'))
{
system("cls");
putss("正在计算最终得分……\n");
Sleep(Speed*666.66);
if(win1!=win2)
{
putss("最终的胜利者是:\n");Sleep(Speed*333.33);
printf("%s!\n",win1>win2?(AIturn==1?"人机":AIturn==-1?"玩家":"玩家1"):(AIturn==-1?"人机":AIturn==1?"玩家":"玩家2"));system("pause");
}
else
{
putss("最终结果是……\n");Sleep(Speed*333.33);
puts("平局!");system("pause");
}
printf("你们的比分为:%d:%d。\n",win1,win2);system("pause");
putss("欢迎下次再玩!\n");system("pause");
return 0;
}
if(KEY_DOWN('Y'))return h;
}
}
}
int main()
{
srand(time(NULL));
while(home());
return 0;
}