用C++复现经典扫雷,供大家参考,具体内容如下

主要是dfs实现打开一片的操作,数字带有颜色,很真实。

windows扫雷中鼠标左右键同时按也实现了,即试探。

先上图,详见下面代码:

代码中有详细注释,编译无任何错误警告。

Ps.有bug请评论指出,谢谢啦~

另外我觉得代码比较臃肿,有什么可以优化的也请提出~

#include

#include

#include

#include

#include

#include

#include

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("扫雷");

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=2&&x

//因为地图是从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]

{

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]

{

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]);

}

}

}

更多精彩游戏小代码,请点击《游戏专题》阅读

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

oracle 小游戏编程,C++实现扫雷经典小游戏相关推荐

  1. python游戏编程网课_Python菜鸟快乐游戏编程_pygame(1)

    作者Toby, 持牌照金融股份公司模型验证专家,国内最大医药数据中心担任过数据库负责人.擅长python 机器学习,应用于医疗,英语,金融风控领域. 课程介绍: 编程正在逐步改变世界,程序员不是搬砖的 ...

  2. python游戏编程入门书籍推荐-游戏编程入门书籍推荐:想要游戏编程尽快入门这些书不要错过...

    游戏编程一直都是编程之中的一大热点,这也是由于游戏本身的火热造成的结果,所以每年都有很多人在关注着游戏编程.介于此小编今天就来将一些好的游戏编程入门书籍推荐给大家,希望对想要了解和学习游戏编程的朋友能 ...

  3. 3D游戏编程:介绍一款功能游戏

    3D游戏编程:介绍一款功能游戏 功能游戏简介 介绍游戏:Single N-back 游戏简介 设计元素分析 社会贡献与价值 功能游戏简介 功能游戏(Serious Game)可被理解为严肃性游戏或应用 ...

  4. easyx游戏编程:五子棋(C语言游戏开发)

    easyx游戏编程:五子棋(C语言游戏开发) 五子棋: 本游戏用到了图形界面库graphics.h,图形界面库下载安装: 下载链接: https://easyx.cn/downloads/. 下方有源 ...

  5. 视频教程-C++游戏编程实例精讲--3D射击游戏作弊-C/C++

    C++游戏编程实例精讲--3D射击游戏作弊 80后,游戏作弊工程师,从事C++开发14年,擅长语言:C,C++ 领域:服务器开发,精通MFC,STL,Boost,熟悉TCP/IP协议,熟练运用IOCP ...

  6. python经典小游戏-用Python设计一个经典小游戏:猜大小

    码农那点事儿 关注我们,一起学习进步 本文主要介绍如何用Python设计一个经典小游戏:猜大小. 游戏规则: 初始本金是1000元,默认赔率是1倍,赢了,获得一倍金额,输了,扣除1倍金额. 玩家选择下 ...

  7. 20行python代码的入门级小游戏-用Python设计一个经典小游戏

    本文主要介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习. 游戏规则: 初始本金是 ...

  8. python经典小游戏-用Python设计一个经典小游戏

    本文主要介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习. 游戏规则: 初始本金是 ...

  9. python简单代码制作小游戏-用Python设计一个经典小游戏

    本文主要介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习. 游戏规则: 初始本金是 ...

最新文章

  1. 每打一通AI骚扰电话,就会被罚款7万块,这是美国国会刚刚通过的法案
  2. 从员工出走仅剩 5 人,到一支打胜仗的铁军
  3. java句子中找单词_java程序找到一个句子中每个单词的字母数
  4. TIOBE 2011年7月编程语言排行榜:Objective-C成为年度语言
  5. 表的插入、更新、删除、合并操作_11_更新表的记录
  6. jquery表单验证源码
  7. 实验四Java_《Java实验四》
  8. (c语言)判断一个正整数是否是回文数
  9. JavaScript是什么
  10. 【EOS】2.2 发行Token,转移Token
  11. webRTC之Mesh/MCU/SFU通信架构区别(九)
  12. 什么是低代码(LowCode)/无代码(NoCode)平台?
  13. 化工厂需要人员定位的原因,高精度UWB化工厂人员定位-新导智能
  14. SEO优化:6个方法提升网站排名
  15. 如何在html中在线预览pdf文件?
  16. AnnotationMethodHandlerAdapter废弃的解决方法
  17. 李一男离开华为时给属下的忠告
  18. 计算机桌面偏移,​电脑屏幕偏移怎么调整
  19. 又发闪电贷价格操纵攻击?—— welnance.finance事件分析
  20. 最佳实践丨阿里云ECI如何助力西软构建酒店行业多租户高弹性PaaS平台?

热门文章

  1. AudioRecord获取分贝值
  2. 计算机不能上网怎么检查,电脑不能上网如何通过Ping命令检查网络
  3. 32、网络工程师必知的华为命令大全
  4. 聊聊Python ctypes 模块
  5. Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica
  6. 将微服务应用于物联网
  7. 平面曲线曲率的计算-MATLAB
  8. Java开发在线打开编辑保存Word文件(支持多浏览器)
  9. Win7系统自动更新关闭不了的解决方法
  10. 竞价账户时好时坏怎样分析找到原因?