【C++】游戏之扫雷游戏

程序大致四部分:

1、设置雷区 函数有 lei_set_sub(int x,int y) lei_set()

2、响应键盘 函数有key() move_()

3、显示 函数有gotoxy(int x,int y) HideCursor() cprintf()show()set_ground()show_lei_sub() show_lei() show_left()

4、检测是否游戏结束 函数有is_gameover()

还有一些比较杂的函数,像是open函数、up_fun函数等具体功能见注释
不说太多,代码奉上

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <cstdio>
#include <ctime>
#include <cstdio>

using namespace std;
const int x_max=5,y_max=5,x_base=3,y_base=4,num_lei=4;
int x_pos,y_pos;
int lei[y_max][x_max];
int lei_click[y_max][x_max];
int x_cursor,y_cursor;
char c;

class Basic
{
public:
    void gotoxy(int x,int y)       //将光标移动到指定位置
    {
        COORD c;
        c.X=x;c.Y=y;
        SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);
    }
    void HideCursor()      //隐藏光标
    {
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_CURSOR_INFO cci;
        GetConsoleCursorInfo(hOut, &cci);
        cci.bVisible = FALSE;
        SetConsoleCursorInfo(hOut, &cci);
    }
    void cprintf(string str, WORD color, ...)  //输出带有颜色的字符
    {
        WORD colorOld;
        HANDLE handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(handle, &csbi);
        colorOld = csbi.wAttributes;
        SetConsoleTextAttribute(handle, color);
        cout << str;
        SetConsoleTextAttribute(handle, colorOld);
    }
    void delay_s(int t)            //秒级延时函数
    {
        clock_t t1=time(0);
        while(time(0)-t1<t);
    }                                  
    void show(int x,int y,int show_type,int num,bool is_cursor)   //将上面几个输出函数综合起来
    {
        gotoxy(x,y);
        string s;
        int color=2;
        s='0'+num;
        if (show_type==0&&is_cursor==false)
        {
            cout<<"@";
        }
        if (show_type==0&&is_cursor==true)
        {
            cprintf("@",color);
        }
        if (show_type==1&&is_cursor==false)
        {
            cout<<num;
        }
        if (show_type==1&&is_cursor==true)
        {
            cprintf(s,color);
        }
        if (show_type==2&&is_cursor==false)
        {
            cout<<"#";
        }
        if (show_type==2&&is_cursor==true)
        {
            cprintf("#",color);
        }
    }
    void setground()     //设置背景
    {
        for(int i=0;i<y_max+2;++i)
        {
            for (int j=0;j<x_max+2;++j)
            {
                if (i==0||i==y_max+1)
                    show(j+x_base,i+y_base,3,0,false);
                else if (j==0||j==x_max+1)
                    show(j+x_base,i+y_base,3,0,false);
            }
        }
    }
    int lei_set_sub(int x,int y)   //下面的函数要用到这个函数,返回lei[y][x]应该填的数字
    {
        int result=0;
        if (lei[y][x]==9)
            return 9;
        for (int i=y-1;i<=y+1;++i)
        {
            for (int j=x-1;j<=x+1;++j)
            {
                if(j>=0&&j<x_max&&i>=0&&i<y_max)
                {
                    if (lei[i][j]==9)
                        result++;
                }
            }
        }
        return result;
    }
    void lei_set()                   //向lei这个数组中赋值把雷填满,然后为雷周边的元素也赋上值
    {
        srand(time(0));
        int pos_x,pos_y;
        memset(lei,0,sizeof(lei));
        memset(lei_click,0,sizeof(lei_click));
        for(int i=0;i<num_lei;++i)
        {
            pos_x=rand()%x_max;
            pos_y=rand()%y_max;
            if (lei[pos_y][pos_x]!=9)
                lei[pos_y][pos_x]=9;
            else
                --i;
        }
        for(int i=0;i<y_max;++i)
        {
            for (int j=0;j<x_max;++j)
            {
                lei[i][j]=lei_set_sub(j,i);
            }
        }
        x_cursor=rand()%x_max;
        y_cursor=rand()%y_max;
    }
    void show_lei_sub(int x,int y)         //(x,y) 这个位置这个应该显示什么
    {
        if (x==x_cursor&&y==y_cursor)
        {
            show(x_base+1+x,y_base+1+y,lei_click[y][x],lei[y][x],true);
        }
        else
        {
            show(x_base+1+x,y_base+1+y,lei_click[y][x],lei[y][x],false);
        }
    }
    void show_lei()                   //整个扫雷区域应该怎么显示
    {
        for(int i=0;i<y_max;++i)
        {
            for (int j=0;j<x_max;++j)
            {
                show_lei_sub(j,i);
            }
        }
    }
    void open()             //一旦点开一个并且这个数是0,会将周围都是0的元素也显示出来
    {
        for (int i=0;i<100;++i)
        {
            for (int y=0;y<y_max;++y)
            {
                for (int x=0;x<x_max;++x)
                {
                    if(lei[y][x]==0&&lei_click[y][x]==1)
                    {
                        if (y-1>=0)
                            lei_click[y-1][x]=1;
                        if (y+1<y_max)
                            lei_click[y+1][x]=1;
                        if (x-1>=0)
                            lei_click[y][x-1]=1;
                        if (x+1<x_max)
                            lei_click[y][x+1]=1;
                    }
                }
            }
        }
    }
    void key(clock_t& t,int tt) //检测键盘输入
    {
        if(clock()-t>tt)
        {
            t=clock();
            if(GetAsyncKeyState(VK_ESCAPE)) exit(0);
			if(GetAsyncKeyState(VK_LEFT))c='a';
			if(GetAsyncKeyState(VK_RIGHT))c='d';
			if(GetAsyncKeyState(VK_UP))c='w';
			if(GetAsyncKeyState(VK_DOWN))c='s';
			if(GetAsyncKeyState(VK_RETURN)&0x8000)c='o';
			if(GetAsyncKeyState(VK_SHIFT))c='p';
        }
    }
    void up_fun()   //一旦确定是雷,就自动插上旗
    {
        int num_ge,count_kong,count_open;
        int x,y;
        for (int i=0;i<y_max;++i)
        {
            for (int j=0;j<x_max;++j)
            {
                num_ge=0;
                count_kong=0;
                count_open=0;
                for (y=i-1;y<=i+1;++y)
                {
                    for(x=j-1;x<=j+1;++x)
                    {
                        if (x>=0&&x<x_max&&y>=0&&y<y_max)
                        {
                            num_ge++;
                            if(lei_click[y][x]==1&&lei[y][x]!=9)
                                count_open++;
                        }
                    }
                }
                if (lei[i][j]+count_open==num_ge&&lei_click[i][j]==1&&lei[i][j]!=9)
                    for (y=i-1;y<=i+1;++y)
                    {
                        for(x=j-1;x<=j+1;++x)
                        {
                            if (x>=0&&x<x_max&&y>=0&&y<y_max&&lei_click[y][x]==0)
                            {
                                lei_click[y][x]=2;
                            }
                        }
                    }
            }
        }
    }
    void move_()    //相应键盘
    {
        switch(c)
        {
        case 'd':
            x_cursor+=1;
            if (x_cursor>=x_max)
                x_cursor=x_max-1;
            break;
        case 'a':
            x_cursor-=1;
            if(x_cursor<0)
                x_cursor=0;
            break;
        case 'w':
            y_cursor-=1;
            if (y_cursor<0)
                y_cursor=0;
            break;
        case 's':
            y_cursor+=1;
            if (y_cursor>=y_max)
                y_cursor=y_max-1;
            break;
        case 'o':
            if (lei_click[y_cursor][x_cursor]==0)
                lei_click[y_cursor][x_cursor]=1;
            open();                    //open函数在这里调用
            up_fun();                  //up_fun 函数在这里调用
            break;
        case 'p':
            if (lei_click[y_cursor][x_cursor]==0)
                lei_click[y_cursor][x_cursor]=2;
            else if (lei_click[y_cursor][x_cursor]==2)
                lei_click[y_cursor][x_cursor]=0;
            break;
        }
        c=0;
    }
    bool gameover()   //判断游戏是否结束,游戏结束则返回true
    {
        int flag=0,count_=0;
        for (int i=0;i<y_max;++i)
        {
            for (int j=0;j<x_max;++j)
            {
                if (lei[i][j]==9&&lei_click[i][j]==1)
                {
                    gotoxy(x_base+1+j,y_base+1+i);
                    cout<<"!";
                    gotoxy(0,4);
                    cout<<"矮油,踩到雷了!即将退出游戏";
                    return true;
                }
                if (lei_click[i][j]==0)
                    flag=1;
                if (lei_click[i][j]==2)
                    count_++;
            }
        }
        if (flag==0&&count_==num_lei)
        {
            gotoxy(0,4);
            cout<<"恭喜你获得游戏的胜利!即将退出游戏!";
            return true;
        }
        return false;
    }
    void running()    //最体现大局的一个函数,建议大家从这里看起
    {
        clock_t t1;
        t1=clock();
        lei_set();
        gotoxy(0,0);
        cout<<"---------扫雷小游戏----------"<<endl;
        cout<<"雷的个数是"<<num_lei<<"  "<<"为"<<x_max<<"*"<<y_max<<"的扫雷区域"<<endl;
        cout<<"游戏规则: 上下左右控制移动,按Enter键打开该格子,按Shift键插旗";
        while(true)
        {
            HideCursor();
            show_lei();
            key(t1,80);
            move_();
            show_left();
            if (gameover())
                break;
        }
        show_lei();
        gameover();
        delay_s(2);
    }
    void show_left()   /显示还剩下的雷的个数
    {
        int count__=0;
        for (int i=0;i<y_max;++i)
            for (int j=0;j<x_max;++j)
            {
                if (lei_click[i][j]==2)
                    count__++;
            }
        gotoxy(0,3);
        count__=num_lei-count__;
        if (count__<0)
            count__=0;
        cout<<"剩余雷的数量:"<<count__<<"   ";
    }
};

int main()
{
    Basic b;
    b.running();
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值