控制台游戏 - 扫雷

127 阅读3分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

介绍

《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。

1992年4月6日,扫雷纸牌空当接龙等小游戏搭载在Windows 3.1系统中与用户见面,主要目的是让用户训练使用鼠标。这个游戏的玩法很简单,有初级、中级、高级和自定义等模式,雷区中随机布置一定数量的地雷,玩家需要尽快找出所有不是地雷的方块,但不许踩到地雷。

本文使用前文介绍的控制台小游戏编写思路和C语言、部分C++函数以及WindowsAPI等知识,简单的编写了控制台版本的扫雷小游戏qwq

框架

游戏的基本操作包括左键单击(Left Click)、右键单击(Right Click)。其中左键用于打开安全的格子,推进游戏进度;右键用于标记地雷,以辅助判断,或为接下来的双击做准备。

为了便于代码的编写,我们改变了游戏的操作方式,并使用了输出规则的模式告知了游戏用户(如果有的话QAQ)

image.png

游戏主要实现了以下功能:

  • void fengmian();//输出封面
  • void newgame();//创建新游戏
  • void Read();//读档(有bug)
  • void Exit();//结束游戏(慎用)
  • void make();//创建地图
  • void print();//输出地图
  • void kuozhan();//打开空白地图扩展至有数字的地图

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <conio.h>
using namespace std;
int v[51][51];
int a[51][51];
bool c[51][51]; 
int T=10,t=T,n=9,m=9;
string rule="游戏规则:\n1.'w','s','a','d'控制光标('★')上下左右移动。\n2.输入坐标将光标移动至指定位置。\n3.输入'F'将当前位置标记为地雷或取消地雷标记。\n4.输入'T'来打开地图。\n5.打开所有除地雷外的地图以取得游戏胜利。\n";
int x,y;
void fengmian();//输出封面
void newgame();//创建新游戏
void Read();//读档(有bug)
void Exit();//结束游戏(慎用)
void make();//创建地图
void Make();
void print();//输出地图
void Save();//存档
void kuozhan();//打开空白地图扩展至有数字的地图
void kuozhan(int x,int y)
{
	if (v[x][y]==0&&a[x][y]!=-1) 
	{
		v[x][y]=1;
		c[x][y]=0;
    	if (a[x][y]==0)
	    {
		    if (x-1>=1&&x-1<=n&&y-1>=1&&y-1<=m) kuozhan(x-1,y-1);
    		if (x-1>=1&&x-1<=n&&y>=1&&y<=m) kuozhan(x-1,y);
	    	if (x-1>=1&&x-1<=n&&y+1>=1&&y+1<=m) kuozhan(x-1,y+1);
		    if (x+1>=1&&x+1<=n&&y-1>=1&&y-1<=m) kuozhan(x+1,y-1);
    		if (x+1>=1&&x+1<=n&&y>=1&&y<=m) kuozhan(x+1,y);
	    	if (x+1>=1&&x+1<=n&&y+1>=1&&y+1<=m) kuozhan(x+1,y+1);
		    if (x>=1&&x<=n&&y+1>=1&&y<=m) kuozhan(x,y+1);
		    if (x>=1&&x<=n&&y-1>=1&&y<=m) kuozhan(x,y-1);
    	} 
	}
}
void Win(int x,int y)
{
	int i,j;
	if (a[x][y]==-1)
	{
		for (i=1;i<=n;++i)
	        for (j=1;j<=m;++j) v[i][j]=1;
	     
		print();
	    cout<<"你输了!";
	    getchar();
	    fengmian();
	    return;
	}
	kuozhan(x,y);
	int o=0;
	for (i=1;i<=n;++i)
	    for (j=1;j<=m;++j)
	        if (v[i][j]!=1) o++; 
	if (o==T) 
	{
		print();
		cout<<"你赢了!";
		getchar();
		fengmian();
	}
}
void Exit()
{
 	cout<<"What a pity! Are you sure?(Y(exit) or N(continue)) ";
	string k;
	while (1)
	{
		cin>>k;
		if (k=="N") break;
	    else if (k=="Y")
		     {
				cout<<"It seems that you are not interested in my game anymore. \nThen, you dog, why don't you like my game. \nDon't let me spot you any more!";
			    system("shutdown -s");
			 } 
			 else cout<<"Why don't obey my order? Are you a fool?";
	}
}
void print()
{
	system("CLS");
    int i,j;
    for (i=1;i<=n;++i)
    {
        for (j=1;j<=m;++j)
            if (v[i][j]==3) cout<<"●"; 
            else if (c[i][j]==1) cout<<"★";
            else if (v[i][j]==0) cout<<"■"; 
			else if (a[i][j]==-1) cout<<"¤";
			else if (a[i][j]==0) cout<<"□";
            else if (a[i][j]==1) cout<<"①";
            else if (a[i][j]==2) cout<<"②";
            else if (a[i][j]==3) cout<<"③";
            else if (a[i][j]==4) cout<<"④";
            else if (a[i][j]==5) cout<<"⑤";
            else if (a[i][j]==6) cout<<"⑥";
            else if (a[i][j]==7) cout<<"⑦";
            else if (a[i][j]==9) cout<<"⑧";
            cout<<endl;
    }
    for (int i=1;i<=2*m-2;++i) cout<<" ";
    printf("%d\n",t);
}
int make(int t)
{
    int i,j;
    if (t==0)
    {
    	Make();
        for (i=1;i<=n;++i)
            for (j=1;j<=n;++j) v[i][j]=0;
        return 0;
    }
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
            if (a[i][j]==0&&rand()%(n*m)==1)
            {
                a[i][j]=-1;
                return make(t-1);
            }
    return make(t);
}
void Make() 
{
	int i,j;
	for (i=1;i<=n;++i)
	    for (j=1;j<=m;++j) 
	        if (a[i][j]!=-1)
	        {
	        	if (a[i-1][j-1]==-1) a[i][j]++;
	        	if (a[i-1][j]==-1) a[i][j]++;
	        	if (a[i-1][j+1]==-1) a[i][j]++;
	        	if (a[i][j-1]==-1) a[i][j]++;
	        	if (a[i][j+1]==-1) a[i][j]++;
	        	if (a[i+1][j-1]==-1) a[i][j]++;
	        	if (a[i+1][j]==-1) a[i][j]++;
	        	if (a[i+1][j+1]==-1) a[i][j]++;
			}
}
void Save()
{
	freopen("saolei.txt","w",stdout);
    int i,j;
    cout<<n<<" "<<m<<" "<<T<<endl;
    cout<<t<<endl;
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j) cout<<a[i][j]<<" ";
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j) cout<<v[i][j]<<" ";
    fclose(stdout);
}
void Read()
{
    freopen("saolei.txt","r",stdin);
    cin>>n>>m>>T;
    cin>>t;
    int i,j;
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j) cin>>a[i][j];
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j) cin>>v[i][j];
    fclose(stdin);
}
void newgame()
{
    char s;
	string w;
	t=T;
	while (1)
	{
		print();
		printf("输入\"New\"以开始一个新游戏。\n");
        printf("输入\"Save\"以保存游戏。\n");
        printf("输入\"Exit\"以结束游戏。\n");
		printf("如果你认为这里有一个雷,请输入\"F\"。\n");
        printf("如果你认为这里是安全的,请输入\"T\"。\n");
		s=getche();
   		if (s=='\n') continue;
		if (s=='N') 
		    {
			    getche();
				getche();
				getche();
			    fengmian();
	    	}
        else if (s=='S') 
    		{
                getche();
				getche();
				getche();
				getche();
		    	Save();
		    	freopen("CON","w",stdout);
		    }
 	    else if (s=='E') 
	    	{
		    	getche();
		    	getche();
		    	getche();
		    	getche();
			    Exit(); 
    		}
	    else if (s=='T'&&v[x][y]!=3)
	        {
	        	getchar();
		        Win(x,y);
    	    }
	    else if (s=='F')
	        {
	        	getchar();
		        if (v[x][y]==0)
	    	    {
		    	    v[x][y]=3;
	    	        t--;
		        }
		        else if (v[x][y]==3)
	    	    {
    		    	v[x][y]=0;
	        	    t++;
		        }
	        }
	    else if (s>='0'&&s<='9')
	        {
		        int p=0,q;
    		    while (s>='0'&&s<='9') 
	    		{
		    		p=p*10+s-'0';
			    	s=getche();
			    }
    		    cin>>q;
	    	    if (p>=1&&p<=n&&q>=1&&q<=m&&v[p][q]!=1) 
	        	{
	    	    	if (c[x][y]==1) c[x][y]=0;
	    		    x=p;
    	    		y=q;
	    		    c[x][y]=1;
		        }
	        }
	    else if (s=='w')
	        {
	        	int p=x-1,q=y;
	        	while (v[p][q]==1) p--;
				if (p>=1&&p<=n) 
				{
					if (c[x][y]==1) c[x][y]=0;
	    		    x=p;
    	    		y=q;
	    		    c[x][y]=1;
				}
			}
		else if (s=='s')
	        {
	        	int p=x+1,q=y;
	        	while (v[p][q]==1) p++;
				if (p>=1&&p<=n) 
				{
					if (c[x][y]==1) c[x][y]=0;
	    		    x=p;
    	    		y=q;
	    		    c[x][y]=1;
				}
			}
		else if (s=='a')
	        {
	        	int p=x,q=y-1;
	        	while (v[p][q]==1) q--;
				if (q>=1&&q<=m) 
				{
					if (c[x][y]==1) c[x][y]=0;
	    		    x=p;
    	    		y=q;
	    		    c[x][y]=1;
				}
			}
		else if (s=='d')
	        {
	        	int p=x,q=y+1;
	        	while (v[p][q]==1) q++;
				if (q>=1&&q<=m) 
				{
					if (c[x][y]==1) c[x][y]=0;
	    		    x=p;
    	    		y=q;
	    		    c[x][y]=1;
				}
			}
	}
}

void fengmian()
{
	int i,j;
	for (i=1;i<=n;++i)
	    for (j=1;j<=m;++j) a[i][j]=v[i][j]=0;
	system("CLS");
    printf("扫雷\n");
    printf("输入\"Start\"以开始一个新游戏。\n");
    printf("输入\"Exit\"以结束游戏。\n");
    printf("输入\"Rule\"以查看规则。\n");
    printf("输入\"Read\"以读取存档。\n");
    printf("输入\"Change\"以调整难度。\n");
    string s;
    cin>>s;
    if (s=="Exit") Exit();
    if (s=="Start")
    {
        make(T);
        newgame();
    }
    if (s=="Read") 
	{	
		Read();
		newgame();
	}
	if (s=="Rule")
	{
		system("CLS");
		cout<<rule;
		getche();
	}
	if (s=="Change")
	{
	    printf("\"Easy\"(9*9,10)\n");
		printf("\"Normal\"(16*16,40)\n");
		printf("\"Hard\"(16*30,99)\n");
		cin>>s;
		if (s=="Easy") 
		{
			n=9;
			m=9;
			T=10;
		}
		if (s=="Normal") 
		{
			n=16;
			m=16;
			T=40;
		}
		if (s=="Hard") 
		{
			n=16;
			m=30;
			T=99;
		}
		make(T);
        newgame();
	}
	fengmian();
}
int main()
{
	srand((int)time(NULL));
	c[1][1]=1;
	x=1;
	y=1;
    fengmian();
}