#include<cstdio>
#include<cstring>
#include<algorithm>
#include<conio.h>
#include<windows.h>
#include<cstdlib>
#include<ctime>
using namespace std; #define MAXN 35
#define MIDX 10
#define MIDY 40
#define CG 25
#define CK 80 int G,K,Lnum,Wnum;//G为地图高,K为地图,Lnum为地图中的雷数,Wnum为剩余的小旗数
int nx,ny;//现在光标所在的位置
bool QR=0,Lose=0,is_flag_true[MAXN][MAXN];//QR为确认模式是否打开,Lose为是否输,第三个是这个位置上的旗是否放对
char map[MAXN][MAXN],tmap[MAXN][MAXN];//第一个是只有雷和空地的地图,第二个是玩家能看到的地图
int map1[MAXN][MAXN],mapc[MAXN][MAXN];//map1为数字的地图,其中0代表空地,-1为雷,1-8为周围雷的个数
//mapc为当前格子的颜色
int col[10]={240,249,242,252,241,244,243,240,248};//col[i]表示windows扫雷中i的颜色,col[0]为空格的颜色
int d[10][4]={{0},{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};//8个方向
bool ZB;//作弊是否打开 /*各种函数*/
void color(int);//颜色
void gto(int,int);//光标位置
void make();//制作随机地图
void print();//打印地图等
bool check(int,int);//判断坐标是否合法
bool is_win();//判断是否赢
bool is_lose();//是否输
void dfs(int,int);//用深搜来打开方块
void st(int,int);//试探,即windows扫雷中的左右键同时按
void flag(int,int);//小旗
void bj(int,int);//标记
void swt();//确认模式
void again();//重新开始
void zb();//作弊模式
void mainmain();//主函数
void print_real_map();//打印最终的地图
void begin();//各种操作 int main()
{
mainmain();
} void color(int a){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);}
void gto(int x,int y)
{
COORD pos;pos.X=y;pos.Y=x;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
} void make()
{
for(int i=1;i<=G;i++)
for(int j=1;j<=K;j++)
map[i][j]='#';//初始化
for(int i=1;i<=Lnum;i++)
{
int x=rand()%G+1,y=rand()%K+1;
while(map[x][y]=='O')
x=rand()%G+1,y=rand()%K+1;
map[x][y]='O';
}//随机放雷
for(int i=1;i<=G;i++)
for(int j=1;j<=K;j++)
{
if(map[i][j]=='O')map1[i][j]=-1,mapc[i][j]=240;//如果是雷
else
{
for(int k=1;k<=8;k++)
if(map[i+d[k][0]][j+d[k][1]]=='O')
map1[i][j]++;//计算周围雷的个数
mapc[i][j]=col[map1[i][j]];//根据格子上的数设置颜色
}
}
for(int i=1;i<=G;i++)
for(int j=1;j<=K;j++)
if(mapc[i][j]==0)//空地
mapc[i][j]=240;
}
void print()
{
system("cls");
gto(0,MIDY-4); color(233); printf("扫雷 cyh");
color(240);
gto(1,MIDY);
for(int i=2;i<=G+1;i++)
{
gto(i,0);
for(int j=1;j<=K;j++)
printf("#"),tmap[i-1][j]='#';//初始化玩家所看到的地图
} gto(2,0);
nx=2,ny=0;
color(15);
printf("@"); color(15);
gto(2,2*K+5);printf("-----规则-----");
gto(3,2*K+5);printf("wasd:选择位置");
gto(4,2*K+5);printf("空格:打开");
gto(5,2*K+5);printf("1键:试探周围8个方块,如果其中有雷则不会打开,无");
gto(6,2*K+5);printf(" 雷或旗帜标对了则会将周围无雷的位置打开,");
gto(7,2*K+5);printf(" 如果试探时周围有标错的旗帜,则会游戏失败");
gto(8,2*K+5);printf(" 必须额外确认一次,以便查看周围被试探的区域");
gto(9,2*K+5);printf("2键:放置/取消小旗(F)");
gto(10,2*K+5);printf("3键:放置/取消标记(?)");
gto(11,2*K+5);printf("4键:打开/关闭确认模式,即每次操作需再按一次确认");
gto(12,2*K+5);printf("5键:打开/关闭作弊模式,即显示原本地图");
gto(13,2*K+5);printf("0键:重新开始");//打印规则 gto(G+4,0);printf("-----操作提示-----\n");
printf("请选择方块进行操作"); gto(1,2*K+10);color(12);printf("剩余小旗数:%d",Wnum=Lnum);
} bool check(int x,int y){return y>=0&&y<K&&x>=2&&x<G+2;}
//因为地图是从2行0列开始打的,而地图是从1行1列开始存的,所以gto(x,y)走到的是map[x-1][y+1]
bool is_win()
{
int cnt=0;
for(int i=1;i<=G;i++)
for(int j=1;j<=K;j++)
if(map[i][j]=='#'&&map1[i][j]==-1)
cnt++;
if(cnt==Lnum) return 1;
//所有没被打开的方块都是雷=>胜利
for(int i=1;i<=G;i++)
for(int j=1;j<=K;j++)
if((tmap[i][j]!='F'&&map1[i][j]==-1)||(tmap[i][j]=='F'&&map1[i][j]!=-1))
return 0;
return 1;
//所有雷都标有旗
}
bool is_lose(){return Lose;} void dfs(int x,int y)
{
if(map1[x-1][y+1]>0)//只要边界全部是数字就return
{
gto(x,y),color(mapc[x-1][y+1]),printf("%d",map1[x-1][y+1]);
tmap[x-1][y+1]=map1[x-1][y+1]+'0';
return;
}
gto(x,y);color(255);
tmap[x-1][y+1]=' ';
printf(" ");//因为下面判断了雷,上面判断了数字,这里就一定是空地
for(int i=1;i<=8;i++)
{
int xx=x+d[i][0]-1,yy=y+d[i][1]+1;//这里的xx和yy是在map中的,而不是gto中的
if(check(xx+1,yy-1)&&tmap[xx][yy]=='#'&&map1[xx][yy]!=-1)//所以check和dfs的参数要变化
dfs(xx+1,yy-1);
}
}
void st(int x,int y)
{
for(int i=1;i<=8;i++)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(check(xx,yy))
{
gto(xx,yy);
if(tmap[xx-1][yy+1]!='#')
color(mapc[xx-1][yy+1]-128);//减去128使周围的8个格子的背景颜色变为灰色
else
color(112);//这里特判一下'#',应该可以不用
printf("%c",tmap[xx-1][yy+1]);
}
}
gto(G+5,0),color(15),printf("请确认 ");
//试探必须额外确认一次,规则上有说
char c=getch();
if(c=='1')
{
for(int i=1;i<=8;i++)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(check(xx,yy))
if(tmap[xx-1][yy+1]=='F'&&map1[xx-1][yy+1]!=-1)//试探时有格子的小旗标错了=>失败
{
Lose=1;
return;
}
}
for(int i=1;i<=8;i++)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(check(xx,yy))
if(map1[xx-1][yy+1]==-1&&tmap[xx-1][yy+1]!='F')//试探是有格子为雷=>取消打开
return;
}
for(int i=1;i<=8;i++)
{
int xx=x+d[i][0],yy=y+d[i][1];
if(check(xx,yy)&&tmap[xx-1][yy+1]=='#')//打开周围8个格子
dfs(xx,yy);
}
}
}
void flag(int x,int y)
{
x-=1,y+=1;
if(tmap[x][y]=='F')//原本为小旗=>取消小旗
{
tmap[x][y]='#';mapc[x][y]=240;
gto(x+1,y-1),color(240),printf("#");
Wnum++;//更新小旗数
}
else//否则就放置小旗
{
is_flag_true[x][y]=map1[x][y]==-1;//判断小旗是否放对
tmap[x][y]='F';mapc[x][y]=253;
gto(x+1,y-1),color(253),printf("F");
Wnum--;//更新小旗数
}
gto(1,2*K+10);color(12);printf("剩余小旗数: ");
gto(1,2*K+22);printf("%d",Wnum);//更新小旗数
}
void bj(int x,int y)//和放小旗差不多,只是不用更新is_flag_true
{
x-=1,y+=1;
if(tmap[x][y]=='?')
{
gto(x+1,y-1),color(240),printf("#");
tmap[x][y]='#';mapc[x][y]=240;
}
else
{
if(tmap[x][y]=='F')//如果原本这个位置上是小旗,而你把它变为了标记,就要更新小旗数
{
Wnum++;
gto(1,2*K+10);color(12);printf("剩余小旗数: ");
gto(1,2*K+22);printf("%d",Wnum);
}
gto(x+1,y-1),color(240),printf("?");
tmap[x][y]='?';mapc[x][y]=240;
}
}
void swt(){QR=!QR;}
void zb()
{
if(ZB)//如果本来作弊打开了就把作弊地图清除
{
for(int i=1;i<=G;i++)
{
gto(i+1,K+2);
for(int j=1;j<=K;j++)
color(15),printf(" ");
}
ZB=0;
}
else//否则打印作弊地图
{
for(int i=1;i<=G;i++)
{
gto(i+1,K+2);
for(int j=1;j<=K;j++)
{
color(mapc[i][j]);
if(map1[i][j]==-1) printf("O");
else if(map1[i][j]>0) printf("%d",map1[i][j]);
else printf(" ");
}
}
ZB=1;
}
}
void again()
{
G=K=Lnum=nx=ny=Lose=ZB=0;
QR=0;
memset(is_flag_true,0,sizeof(is_flag_true));
memset(map,0,sizeof(map));
memset(tmap,0,sizeof(tmap));
memset(map1,0,sizeof(map1));
memset(mapc,0,sizeof(mapc));
color(15);
system("cls");//初始化
mainmain();
} void begin()//各种操作
{
char c=getch();
gto(G+5,0),color(15),printf("请选择方块进行操作");
color(240);
if(c=='w'&&check(nx-1,ny))
{
gto(nx,ny);
if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')
color(mapc[nx-1][ny+1]);
printf("%c",tmap[nx-1][ny+1]);
gto(nx-=1,ny);color(15);printf("@");
}
else if(c=='s'&&check(nx+1,ny))
{
gto(nx,ny);if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')color(mapc[nx-1][ny+1]);printf("%c",tmap[nx-1][ny+1]);
gto(nx+=1,ny);color(15);printf("@");
}
else if(c=='a'&&check(nx,ny-1))
{
gto(nx,ny);if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')color(mapc[nx-1][ny+1]);printf("%c",tmap[nx-1][ny+1]);
gto(nx,ny-=1);color(15);printf("@");
}
else if(c=='d'&&check(nx,ny+1))
{
gto(nx,ny);if(tmap[nx-1][ny+1]!='#'||tmap[nx-1][ny+1]==' ')color(mapc[nx-1][ny+1]);printf("%c",tmap[nx-1][ny+1]);
gto(nx,ny+=1);color(15);printf("@");
}
//上下左右移动
else
{
if(c==' '&&(!(tmap[nx-1][ny+1]<='9'&&tmap[nx-1][ny+1]>='0'))&&tmap[nx-1][ny+1]!='F')
{
mapc[nx-1][ny+1]=col[map1[nx-1][ny+1]];//如果本来放了标记,mapc[nx-1][ny+1]的颜色为黑色,在打开时里面的颜色却不一定是黑色
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()==' ')
{
if(map1[nx-1][ny+1]==-1) {Lose=1;return;}
dfs(nx,ny);
}
}
else
{
if(map1[nx-1][ny+1]==-1) {Lose=1;return;}
dfs(nx,ny);
}
}
else if(c=='1')
{
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()=='1') st(nx,ny);
}
else st(nx,ny);
for(int i=1;i<=8;i++)
{
int xx=nx+d[i][0],yy=ny+d[i][1];
if(check(xx,yy))
{
gto(xx,yy);
if(tmap[xx-1][yy+1]!='#') color(mapc[xx-1][yy+1]);
else color(240);
printf("%c",tmap[xx-1][yy+1]);
}
}
}
else if(c=='2'&&(tmap[nx-1][ny+1]>'9'||tmap[nx-1][ny+1]<'1'))
{
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()=='2') flag(nx,ny);
}
else flag(nx,ny);
}
else if(c=='3'&&(tmap[nx-1][ny+1]>'9'||tmap[nx-1][ny+1]<'1'))
{
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()=='3') bj(nx,ny);
}
else bj(nx,ny);
}
else if(c=='4')
{
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()=='4') swt();
}
else swt();
}
else if(c=='5')
{
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()=='5') zb();
}
else zb();
}
else if(c=='0')
{
if(QR)
{
gto(G+5,0),color(15),printf("请确认 ");
if(getch()=='0') again();
}
else again();
}
}
} void mainmain()
{
system("mode con cols=120 lines=35");//设置窗口大小
srand((unsigned)time(NULL));
int mode;
printf("1.初级\n2.中级\n3.高级\n4.自定义\n");
scanf("%d",&mode);if(mode>4) mode=4;
if(mode==1) G=9,K=9,Lnum=10;
else if(mode==2) G=16,K=16,Lnum=40;
else if(mode==3) G=16,K=30,Lnum=99;//三种等级的参数
else
{
printf("请输入雷区高度:");scanf("%d",&G);
printf("请输入雷区宽度:");scanf("%d",&K);
printf("请输入雷个数(建议不超过总大小的三分之一):");scanf("%d",&Lnum);
if(G>24) G=24;if(K>30) K=30;
if(G<9) G=9;if(K<9) K=9;
if(Lnum<10) Lnum=10;if(Lnum>G*K*9/10) Lnum=G*K*9/10;
//控制参数的范围,最后一个if是雷的数量不超过地图大小的9/10
}
make();
print();
while(1)
{
begin();
bool f1=is_win(),f2=is_lose();
if(f1||f2)
{
gto(0,0);
if(f1)
color(202),gto(0,0),printf("你 赢 了!!是否重来?(y/n)");
if(f2)
color(137),gto(0,0),printf("你 输 了!!是否重来?(y/n)");//输赢
print_real_map();
char c=getch();
if(c=='y'||c=='Y') again();
else
{
color(15);
system("cls");
gto(MIDX,MIDY-5);
printf("欢迎下次再来");
return;
}
}
}
}
void print_real_map()
{
color(240);
for(int i=1;i<=G;i++)
{
gto(i+1,0);
for(int j=1;j<=K;j++)
{
if(tmap[i][j]=='F'&&is_flag_true[i][j]==0)//如果旗标错了显示红色的X
color(252),printf("X");
else if(map1[i][j]==-1)//雷为黑色O
color(240),printf("O");
else if(map1[i][j]==0)//空
color(240),printf(" ");
else//数字
color(mapc[i][j]),printf("%d",map1[i][j]);
}
}
}

c++小游戏——扫雷的更多相关文章

  1. c++小游戏———扫雷

    大家好,我是芝麻狐! 这是我自制的小游戏,目前仅支持devc++. 如果你没有c++软件, 请打开网站GDB online Debugger | Compiler - Code, Compile, R ...

  2. c语言小游戏-扫雷的完成

    C语言-扫雷游戏 本文将对此游戏做一个大致的概述,此代码适合初学者,编写软件使用了vs2017. 该代码可以实现如下功能: 1.用户可以选择3个难度,分别布置不同个数的雷. 2.随机数设置雷的位置. ...

  3. web版扫雷小游戏(一)

    作为一名程序猿,平时的爱好也不多,说起游戏,我不太喜欢大型的网游,因为太耗时间,偶尔玩玩经典的单机小游戏,比如windows下自带的游戏扫雷(秀一下,高级下最高纪录110s). 现阶段正在致力于web ...

  4. Angular4 扫雷小游戏

    扫雷小游戏,可以升级过关,难度随关卡增加.但是有很明显的bug,以后有时间会继续优化! HTML: <div class="mainContent"> <div ...

  5. 扫雷小游戏PyQt5开发【附源代码】

    也没啥可介绍哒,扫雷大家都玩过. 雷的分布算法也很简单,就是在雷地图(map:二维数组)中,随机放雷,然后这个雷的8个方位(上下左右.四个对角)的数字(非雷的标记.加一后不为雷的标记)都加一. 如何判 ...

  6. C++扫雷小游戏(基于CMD命令行)

    这个小游戏是笔者在大一C语言课程设计的时候写的,基于命令行,为了显得漂亮一些,特别加上了彩色特效~~~ 注意:Win10系统须将命令行调为旧版命令行,否则有可能会显示乱码! 代码示例: #includ ...

  7. 无聊的周末用Java写个扫雷小游戏

    周末无聊,用Java写了一个扫雷程序,说起来,这个应该是在学校的时候,写会比较好玩,毕竟自己实现一个小游戏,还是比较好玩的.说实话,扫雷程序里面核心的东西,只有点击的时候,去触发更新数据这一步. Sw ...

  8. C++复现经典游戏——扫雷

    国庆小长假,当大家都去看人山人海的时候,我独自一人狂码代码.这两天想要实现的内容是Windows上的一个经典游戏——扫雷.相信90后和一些上班族对此并不陌生.然而,从win8开始,扫雷就不再是Wind ...

  9. 使用cocos2d-x v3.1开发小游戏(基本框架)

    小游戏的组成 欢迎界面 在游戏资源未全部加载完之前就需要载入,避免进入游戏会有一段黑屏时间. 可以用来展示游戏名称或者开发者logo. 开始菜单界面 一般用于显示游戏名称和关卡选择(或者称游戏难度选择 ...

随机推荐

  1. tftp的安装及配置

    1.安装tftp服务客户端sudo apt-get install tftp 2.安装tftp服务器端sudo apt-get install tftpd 3.安装xinetd注意同类似的还有open ...

  2. Qt4.8.6与VS2008的集成开发环境的安装配置

    一.安装编译Qt 1. 在Windows下用Qt做开发,编译器可以用mingw的gcc/g++,也可以用VS. 2. 安装VS2008集成开发环境(完全安装).  3. 安装qt4.8.6(qt-op ...

  3. Linux运维工程师成长路线及应实现的目标

    作为一名运维工程师,需要学习的东西非常多,在学习的过程中也没有任何捷径可言,必须一步一个脚印地学习.积累才能把个人技能提升到相应的高度.根据目前流行的发行版及国际流行的Linux认证,红帽认证和LPI ...

  4. Qt之QGraphicsEffect阴影、模糊效果

    Qt之QGraphicsEffect阴影.模糊效果 Qt之QGraphicsEffect阴影模糊效果 效果图 阴影和模糊效果 正常效果 代码 customshadoweffecth customsha ...

  5. TCP使用注意事项总结

    目录 发送或者接受数据过程中对端可能发生的情况汇总 本端TCP发送数据时对端进程已经崩溃 本端TCP发送数据时对端主机已经崩溃 本端TCP发送数据时对端主机已经关机 某个连接长时间没有数据流动 TCP ...

  6. 常用的HTTP状态代码(4xx、5xx)详解

    HTTP状态代码常用的如下: 400 无法解析此请求. 401.1 未经授权:访问由于凭据无效被拒绝. 401.2 未经授权: 访问由于服务器配置倾向使用替代身份验证方法而被拒绝. 401.3 未经授 ...

  7. php对象在内存中创建于释放

    <?php /** * 1.对象的创建占用内存, * 对象内存释放,析构方法就是在对象释放前运行最后的一步.可以自动释放和手动释放 * 手动释放:通过unset($p);来释放对象,在这个时候会 ...

  8. Java 位域

    Java位域 这个概念是在 Effective Java中了解到的, 可以通过EnumSet来代替位域这种方式表达. 并不是很常见的概念, 因此记录下. 如果在这之前恰好了解过 bitmap这种数据结 ...

  9. 跟我学SpringCloud | 第八篇:Spring Cloud Bus 消息总线

    SpringCloud系列教程 | 第八篇:Spring Cloud Bus 消息总线 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特 ...

  10. HDU 5618:Jam's problem again(CDQ分治+树状数组处理三维偏序)

    http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:…… 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. #includ ...