C++控制台实现扫雷游戏

本文实例为大家分享了C++控制台实现扫雷游戏的具体代码,供大家参考,具体内容如下

花了一下午写出来的控制台扫雷,主要通过修改和打印数组来实现。

主要的问题点:

1.在显示地图的过程中,既要显示数字,又要显示雷和符号,所以的用string类型的二维向量,vector<vector<string.>>;中间要利用ASCII码将int型的数字转化为字符串。
2.生成地图的时候,雷是随机的,我这里采用的做法是取余生成雷,举个例子,如果雷数是格子数的十分之一,那我遍历整个二维数组,在rand()%8 == 0时放置一颗雷,当放置10颗之后停止,这样可能会导致我的雷都偏前面一点,哈哈。
3.对于没有雷的格子,需要做一个遍历,统计周边的雷数,为了方便,实际地图要大一圈,实际的边长+2,边不作为地图,只为统计雷数时方便存在。
4.当点开一颗雷之后,如果数字是0,那么四周为0的数字也要被点亮,因此在这里使用递归实现dfs。
5.在每次进行一个格子操作之后,使用一个count计数,所有格子操作完后,游戏结束统计游戏结果,在此之前,踩到雷也会导致游戏结束。

附上游戏截图和代码

主函数

#include<vector>
#include<algorithm>
#include<functional>
#include<iostream>
#include<windows.h>
#include"gameManager.h"
#include"map.h"
using namespace std;

int main() {
    GameManager* game = new GameManager();

    while (true) {
        int diff = game->difficultNumber();//玩家的难度选择参数
        
        Map* m = new Map(diff);

        m->initMap();

        while (true) {
            m->showMap();

            int swicth;

            cout << "1.踩雷" << endl;
            cout << "2.插旗子" << endl;
            cout << "3.取消插旗子" << endl;

            cin >> swicth;

            if (swicth == 1) {
                //踩雷;如果踩到雷了返回1,没踩到返回0
                if (game->stepOnMine(m)) break;
            }
            else if (swicth == 2) {
                //插旗子
                game->flagMine(m);
            }
            else if (swicth == 3) {
                //取消插旗子
                game->cancelFalgMine(m);
            }
            else {
                cout << "您的输入有误!" << endl;
            }

            //判断格子是否被开完,开完了则取胜
            if (m->gameOver()) {
                cout << "恭喜你获得胜利!" << endl;
                m->showMap();
                break;
            }

        }
        int over = 0;
        cout << "1.回到主菜单" << endl;
        cout << "other.退出游戏" << endl;
        cin >> over;
        if (over == 1) {
            system("cls");
            continue;
        }
        else break;
    }
    system("pause");
    return 0;
}

map类

头文件

```cpp
#pragma once
#include<ctime>
#include <vector>
#include<string>
#include <iostream>
using namespace std;

class Map {
public:
    Map(int);//根据难度构造地图
    void initMap();//根据难度初始化地图
    string aroudMineNum
    (const vector<vector<string>>&, const int&, const int&) const;//判断某个坐标桌边的雷数
    void showMap();//打印showMapArray数组    
    int dateUpMap(const int&, const int&);//如果返回值为1,继续,返回值为0表示结束,如果返回值为-1表示非法输入
    int flag(const int&, const int&);//插旗子修改显示数组
    int cancelFlag(const int&, const int&);//取消旗子时修改显示数组
    bool gameOver();

private:
    int mapCount;//格子用完的计数
    int difficult;//难度
    vector<vector<string>> map;//隐藏的雷表
    vector<vector<string>> showMapArray;//公开的显示数组
};

源文件

#include"map.h"

Map::Map(int difficult) :
    difficult(difficult),
    mapCount(difficult* difficult)
{

}

//初始化地图数组
void Map::initMap()
{
    //根据难度设置二维数组的大小以及雷的数量
    int mineNumber = difficult * difficult * 10;//雷的数量
    int size = 10 * difficult;//此处尺寸加2,四边都为零,这样方便统计没有雷的格子上的数据

    srand(time(0));
    //使用随机数设置雷的数量
    for (int i = 0; i < size + 2; ++i) {
        vector<string> temp;
        for (int j = 0; j < size + 2; ++j) {
            if (rand() % 8 == 0 && mineNumber != 0 && i != 0 && j != 0 && i != size - 1 && j != size - 1) {
                temp.push_back("*");
                --mineNumber;
            }
            else {
                temp.push_back("0");
            }
        }
        map.push_back(temp);
    }
    //此外还需要根据雷的位置和数量在其他位置上提示!
    for (int i = 1; i < size - 1; ++i) {

        for (int j = 1; j < size - 1; ++j) {
            if (map[i][j] != "*") {
                map[i][j] = aroudMineNum(map, i, j);
            }

        }

    }

    //初始化显示显示数组,注意!此数组要显示行列数,所以比上述数组多一行一列
    for (int i = 0; i < size + 1; ++i) {
        vector<string> temp;
        for (int j = 0; j < size + 1; ++j) {
            if (i == 0) {
                string t;
                if (j < 10) {
                    t.push_back(48);
                    t.push_back(j + 48);
                }
                else if (j < 20) {
                    t.push_back(49);
                    t.push_back(j + 38);
                }
                else if (j < 30) {
                    t.push_back(50);
                    t.push_back(j + 28);
                }
                else {
                    t.push_back('3');
                    t.push_back('0');
                }
                temp.push_back(t);
            }
            else if (j == 0) {
                string t;
                if (i < 10) {
                    t.push_back(48);
                    t.push_back(i + 48);
                }
                else if (i < 20) {
                    t.push_back(49);
                    t.push_back(i + 38);
                }
                else if (i < 30) {
                    t.push_back(50);
                    t.push_back(i + 28);
                }
                else {
                    t.push_back('3');
                    t.push_back('0');
                }
                temp.push_back(t);
            }
            else temp.push_back(" #");
        }
        showMapArray.push_back(temp);
    }
}

//判断自身格子上的数字为多少
string Map::aroudMineNum(const vector<vector<string>>& map, const int& i, const int& j) const
{
    int count = 0;
    string ans;
    for (int x = i - 1; x <= i + 1; ++x) {
        for (int y = j - 1; y <= j + 1; ++y) {
            if (map[x][y] == "*") {
                ++count;
            }
        }
    }
    ans.push_back(48);
    ans.push_back(count + 48);
    return ans;
}

//按照地图数组显示画面
void Map::showMap()
{
    int sideLength = showMapArray.size();
    for (int i = 0; i < sideLength; ++i) {
        for (int j = 0; j < sideLength; ++j) {
            cout << showMapArray[i][j] << " ";
        }
        cout << endl;
    }
}

int Map::dateUpMap(const int& x, const int& y)
{

    //判断xy的值只能在0-30之间difficult*10
    if (x < 1 || x >= (difficult * 10) || y < 0 || y >= (difficult * 10)) return -1;
    //判断坐标是否已经被翻开,若被翻开,则输入非法,返回-1
    if (showMapArray[x][y] != " #") return -1;
    //如果该点有雷,则把该点的雷翻出来,显示游戏失败
    if (map[x][y] == "*") {
        showMapArray[x][y] = " *";
        return 0;
    }
    //如果该点的数字大于0,则只把单一数字翻出来
    else if (map[x][y] != "00") {
        string temp;
        temp.append(map[x][y]);
        showMapArray[x][y] = temp;
        --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利!
    }
    //如果该点的数字为0,则把附近为0的点全部翻出来,直到翻出数字为止
    else {
        if (showMapArray[x][y] != " Q") {
            --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利!
            showMapArray[x][y] = "00";
        }
        if (showMapArray[x][y] == " Q" && map[x][y] == "*") {
            showMapArray[x][y] = " *";
            return -1;
        }
        for (int i = x - 1; i <= x + 1; ++i) {
            for (int j = y - 1; j <= y + 1; ++j) {
                if (!(i == x && j == y) && i > 0 && i < (difficult * 10) && j > 0 && j < (difficult * 10)) {
                    dateUpMap(i, j);
                }
            }
        }
        return 1;
    }
}

int Map::flag(const int& x, const int& y)
{
    if (showMapArray[x][y] != " #") return -1;
    else {
        --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利!
        showMapArray[x][y] = " Q";
    }
    return 0;
}

int Map::cancelFlag(const int& x, const int& y)
{
    if (showMapArray[x][y] != " Q") return -1;
    else {
        ++mapCount;//格子数增加统计,当格子数为0时判断游戏胜利!
        showMapArray[x][y] = " #";
    }
    return 0;
}

bool Map::gameOver()
{
    if (mapCount == 0) return true;
    return false;
}

gameManager类

头文件

#pragma once
#include<iostream>
#include<windows.h>
#include"map.h"
using namespace std;
class GameManager {
public:
    void showMenu();//显示主菜单
    int difficultNumber();//选择难度
    int stepOnMine(Map * m);//踩雷
    int flagMine(Map* m);//插旗子
    int cancelFalgMine(Map * m);//取消旗子
};

源文件

#include"gameManager.h"
#include"map.h"

void GameManager::showMenu()
{
    cout << "***************主菜单***************" << endl;
    cout << "************1.简单模式**************" << endl;
    cout << "************2.中等模式**************" << endl;
    cout << "************3.困难模式**************" << endl;
    cout << "**********请输入你的选择************" << endl;
}

int GameManager::difficultNumber()
{
    int diff = 0;
    while (diff != 1 && diff != 2 && diff != 3) {
        this->showMenu();
        cin >> diff;
    }
    return diff;
}

int GameManager::stepOnMine(Map* m)
{
    int x, y;
    cout << "请输入你想排雷的坐标:" << endl;
    cout << "x:" << endl;
    cin >> x;
    cout << "y:" << endl;
    cin >> y;
    int result = m->dateUpMap(x, y);
    system("cls");
    if (result == -1) {
        cout << "您的输入有误,请重新输入!" << endl;

    }
    else if (result == 0) {
        cout << "你踩到雷啦!" << endl;
        Sleep(300);
        cout << "游戏即将结束!" << endl;
        Sleep(300);
        cout << "5!" << endl;
        Sleep(300);
        cout << "4!" << endl;
        Sleep(300);
        cout << "3!" << endl;
        Sleep(300);
        cout << "2!" << endl;
        Sleep(300);
        cout << "1!" << endl;
        m->showMap();
        system("pause");
        return 1;
    }
    return 0;
}

int GameManager::flagMine(Map* m)
{
    //插旗子
    int x, y;
    cout << "请输入你想插旗子的坐标:" << endl;
    cout << "x:" << endl;
    cin >> x;
    cout << "y:" << endl;
    cin >> y;
    int result = m->flag(x, y);
    system("cls");
    if (result == -1) {
        cout << "此处不能插旗子!" << endl;
    }
    else
        cout << "插旗子成功!" << endl;
    return 0;
}

int GameManager::cancelFalgMine(Map* m)
{
    int x, y;
    cout << "请输入你想取消旗子的坐标:" << endl;
    cout << "x:" << endl;
    cin >> x;
    cout << "y:" << endl;
    cin >> y;
    int result = m->cancelFlag(x, y);
    system("cls");
    if (result == -1) {
        cout << "此处没有旗子可以取消!" << endl;
    }
    else {
        cout << "取消旗子成功!" << endl;
    }
        
    return 0;
}

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

(0)

相关推荐

  • C++实现一个扫雷小游戏

    本文实例为大家分享了C++实现扫雷小游戏的具体代码,供大家参考,具体内容如下 目前的版本是0.98版本,可以提出增加新功能意见哦 代码如下: #include<bits/stdc++.h> #include<windows.h> using namespace std; long long int c,dev,m,k,cnt,d,e,jie=10,z,abc,n,b[1000][1000],a[1000][1000],cc,cd,ce,def; //c是随机行,k是随机列 bool

  • C++扫雷游戏的简单制作

    本文实例为大家分享了C++实现扫雷游戏的具体代码,供大家参考,具体内容如下 #ifndef SAOLEI_H #define SAOLEI_H class Block { friend class Saoleigame; public: Block(); bool isShown(); void setnum(int); int getnum(); bool isbomb(); protected: int num; bool flag_show; int x; int y; }; class

  • 利用c++和easyx图形库做一个低配版扫雷游戏

    游戏界面 由于这个游戏是我抱着玩一玩的心态做出来的,所以没有过多的去设计界面,也没有去找游戏的资源(图片.游戏音效等).仅使用了不同颜色的方块来表示游戏中方块的状态和种类.(绿色为初始状态(未翻转的状态),黄色为翻转后的背景颜色,蓝色表示已插旗的方块,红色代表地雷) 图1 游戏主菜单界面 图二 模式一的游戏界面(20*20 40个雷) 图三 模式二的游戏界面(10*10 20个雷) 图四 游戏成功界面 图五 游戏失败界面 2.全部代码 #include<graphics.h> #include

  • C++实现简单的扫雷游戏(控制台版)

    C++新手的代码,请各位多包涵. 用C++写的一个简单的控制台版扫雷游戏.玩家通过输入方块的坐标来翻开方块. 只是一个雏形,能够让玩家执行翻开方块的操作并且判断输赢,还未添加标记方块.游戏菜单.记录游戏时间.重新开一局等等的功能. 玩家输入坐标的方式来翻开方块只适用于小型的"雷区",若"雷区"大了,用坐标会变得很不方便. 代码片段扫雷V1.1 #include<stdio.h> #include<Windows.h> #define YELL

  • C++学习心得之扫雷游戏

    本文实例为大家分享了C++实现扫雷游戏的具体代码,供大家参考,具体内容如下 一.序言 创建一个9*9有10个雷的扫雷游戏 文章的顺序是按照我当时的编程顺序写的,顺便写下我当初的一点思路,总的代码在文章最后,前面的都是分散的函数,有需要的朋友直接复制最后的 二.创建 创建一个头文件,一个放游戏的程序,一个放运行测试的程序 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdlib.h>//生成随机数 #include<stdio.h> #inc

  • C++实现扫雷经典小游戏

    用C++复现经典扫雷,供大家参考,具体内容如下 主要是dfs实现打开一片的操作,数字带有颜色,很真实. windows扫雷中鼠标左右键同时按也实现了,即试探. 先上图,详见下面代码: 代码中有详细注释,编译无任何错误警告. Ps.有bug请评论指出,谢谢啦~ 另外我觉得代码比较臃肿,有什么可以优化的也请提出~ #include<cstdio> #include<cstring> #include<algorithm> #include<conio.h> #i

  • C++实现扫雷小游戏(控制台版)

    本文为大家分享了C++实现扫雷小游戏的具体代码,供大家参考,具体内容如下 程序功能: 提供三种模式:初级.中级.高级 操作模式:wsad控制光标移动,空格键打开方块 提供扫雷地图的类 map.h #ifndef MAP_H_ #define MAP_H_ #define MAX_LENGTH 32 //可以提供的地图最大长度 #define MAX_WIDTH 18 //可以提供的地图最大宽度 #define UP_EDGE 1 //上边界 #define DOWN_EDGE _wid //下边

  • C++代码实现扫雷游戏

    前言 提示:本文是基于easyX图形库实现的,还有部分功能可以添加,仅适合新手参考. 提示:以下是本篇文章正文内容,下面案例可供参考 一.扫雷游戏模式 在确定大小的矩形雷区中随机布置一定数量的地雷,玩家需要尽快找出雷区中的所有不是地雷的方块,而不许踩到地雷. 游戏的基本操作包括左键单击和右键单击.其中左键用于打开安全的格子,推进游戏进度:右键用于标记地雷,以辅助判断. 左键单击:在判断出不是雷的方块上按下左键,可以打开该方块.如果方块上出现数字,则该数字表示其周围3×3区域中的地雷数(一般为8个

  • C++实现简单扫雷游戏

    扫雷是一个经典的电脑小游戏,用C++来编一下,效果自己试一下 #include<stdio.h> #include<Windows.h> #define YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY #define CYAN FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY #define ORANGE FOREGROUND_RED |

  • C++实现扫雷游戏(控制台不闪屏版)

    之前写了一个C++ 的控制台扫雷小游戏,但由于过度使用system("cls")刷屏,导致闪屏,因此重写了一个改善的不闪屏版本,并把逻辑重新捋了一遍. map.h #ifndef MAP_H_ #define MAP_H_ #define MAX_WID 18 #define MAX_LEN 32 #define UP_EDGE 1 //上边界 #define LEFT_EDGE 1 //左边界 #define RIGHT_EDGE _len //右边界 #define DOWN_ED

随机推荐