命令行版扫雷,方向键控制

以前写的一个命令行版扫雷,今天翻出来整理了下拿出来,写的有点乱=  =

Codeblocks、VC6.0编译通过,只能在windows下运行,Linux不支持。不嫌蛋疼的可以用curses库来实现下Linux版本。。。

截图2张,比较简陋:


程序还是比较简单的,那这里就直接丢代码了:

/**
 * 命令行版扫雷,方向键控制
 * 作者:evangwt
 */
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#define bool int
#define true 1
#define false 0
#define ROW             9
#define COLUMN          9
#define TOTAL_MINE     10
// ASCII码
#define MINE            42
#define ESC             27
#define ENTER           13
#define SPACE           32
#define UP              72
#define DOWN            80
#define LEFT            75
#define RIGHT           77
typedef struct cursorPos_st
{
    int x;
    int y;
} cursorPos_t;

typedef struct block_st
{
    bool bCover;
    int nMine;
} block_t;

cursorPos_t cursorPos[ROW][COLUMN]; // 光标位置数组

block_t mine[ROW][COLUMN];          // 扫雷地图数组

int nLeftBlock = ROW * COLUMN;      // 剩余的格数

int index_x = 0, index_y = 0;       // 光标在光标位置数组、地图数组中的下标

void setColor(unsigned short Color);

void welcome();

void init();

void count();                       // 计算附近雷数

void get();                         // 获取键盘输入

void gotoPos(int y, int x);

void move(int y, int x);            // 移动当前光标位置

bool check(int y, int x);           // 检测是否踩雷

void print();                       // 输出扫雷界面

void over(char *str);               // 游戏结束


int main()
{
    setColor(160);
    system("cls");
    welcome();
    init();
    count();
    print();
    /*颜色测试
    int i = 0;
    for(i = 0; i < 256; ++i){
        setColor(i);
        system("cls");
        print();
        gotoPos(0, 0);
        printf("%d", i);
        Sleep(100);
        getch();
    }
    */
    for (;;)
    {
        gotoPos(cursorPos[index_y][index_x].y, cursorPos[index_y][index_x].x);
        get();
    }
    return 0;
}

void setColor(unsigned short Color)
{
    HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hCon, Color);
};

void init()
{
    int i = 0, j = 0;
    int nMine = TOTAL_MINE;             // 初始化地雷总数
    srand((unsigned int)time(NULL));
    // 初始化地雷地图数组
    for (i = 0; i < ROW; ++i)
    {
        for (j = 0; j < COLUMN; ++j)
        {
            mine[i][j].bCover = true;
            mine[i][j].nMine = 0;
        }
    }
    // 放置地雷
    while (nMine)
    {
        //printf("%d\n", nMine);
        i = rand() % ROW;
        j = rand() % COLUMN;
        if (mine[i][j].nMine == 0)
        {
            mine[i][j].nMine = -1;    // -1为地雷
            --nMine;
        }
    }

    // 初始化光标位置数组
    for (i = 0; i < ROW; ++i)
    {
        for (j = 0; j < COLUMN; ++j)
        {
            cursorPos[i][j].x = j * 6 + 3;
            cursorPos[i][j].y = i * 2 + 1;
            //printf("%d,%d;", cursorPos[i][j].x, cursorPos[i][j].y);
        }
    }
}

void count()
{
    int i = 0, j = 0, m = 0, n = 0;
    int nMine = 0;                                 // 每个格子周围的雷数
    for (i = 0; i < ROW; ++i)
    {
        for (j = 0; j < COLUMN; ++j)
        {
            if (mine[i][j].nMine == -1)
                continue;
            // 8方向
            nMine = 0;
            for (m = -1; m <= 1; ++m)
            {
                if (i + m < 0 || i + m >= ROW)      // 行溢出
                {
                    continue;
                }
                for (n = -1; n <= 1; ++n)
                {
                    if (j + n < 0 || j + n >= COLUMN)// 列溢出
                    {
                        continue;
                    }
                    if (mine[i + m][j + n].nMine == -1)
                    {
                        ++nMine;
                    }
                }
            }
            mine[i][j].nMine = nMine;
        }
    }
}

void get() {
    bool lose;
    int key1 = getch();
    if (key1 == 224)                    // 方向键两个字节,第一个字节ASCII 224
    {
        int key2 = getch();
        switch (key2)
        {
        case UP:
            move(index_y - 1, index_x);
            break;
        case DOWN:
            move(index_y + 1, index_x);
            break;
        case LEFT:
            move(index_y, index_x - 1);
            break;
        case RIGHT:
            //printf("right\n");
            move(index_y, index_x + 1);
            break;
        default:
            break;
        }
    }
    else
    {
        switch (key1)
        {
        case ENTER:
        case SPACE:
            lose = check(index_y, index_x);
            system("cls");
            print();
            if (lose)
            {
                printf("|              诶哟我去,踩到一坨热翔! =。。=        |\n");
                printf("|                 按\"r\"重玩,其他键继续。             |\n");
                printf("[%c]-------------------------------------------------[%c]\n", MINE, MINE);
                Sleep(1000);
                char key3 = getch();
                if (key3 == 'r' || key3 == 'R')
                {
                    setColor(160);
                    init();
                    count();
                    print();
                }
            }
            else if (nLeftBlock > TOTAL_MINE)
            {
                printf("|                     哎哟,不错哦~ = v =             |\n");
                printf("[%c]-------------------------------------------------[%c]\n", MINE, MINE);
            }
            else
            {
                printf("|                    哟,居然赢了! =。。=            |\n");
                printf("|                  按\"r\"重玩,其他键继续。            |\n");
                printf("[%c]-------------------------------------------------[%c]\n", MINE, MINE);
                Sleep(1000);
                char key3 = getch();
                if (key3 == 'r' || key3 == 'R')
                {
                    setColor(160);
                    init();
                    count();
                    print();
                }
            }
            break;
        case ESC:
            system("cls");
            over("\t\t\t\t\t白白~\n\n\n\n\n\n\n\n");
        default:
            break;
        }
    }
}

void gotoPos(int y, int x)
{
    COORD c;
    c.X = x;
    c.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

void move(int y, int x)
{
    if ((x >= 0 && x < COLUMN) && (y >= 0 && y < ROW))
    {
        gotoPos(cursorPos[y][x].y, cursorPos[y][x].x);
        index_x = x;
        index_y = y;
    }
}

bool check(int y, int x)
{
    int i = 0, j = 0;
    // 下标溢出
    if (x < 0 || x >= COLUMN || y < 0 || y >= ROW)
    {
        return false;
    }
    // 翻开选中的格子
    mine[y][x].bCover = false;
    // 踩中地雷
    if (mine[y][x].nMine == -1)
    {
        mine[y][x].nMine = 9;
        return true;
    }

    // 展开连片空格
    if (mine[y][x].nMine > 0 && mine[y][x].nMine < 9)
    {
        return false;
    }
    for (i = -1; i <= 1; ++i)
    {
        if (y + i < 0 || y + i >= ROW)               // 行溢出
        {
            continue;
        }
        for (j = -1; j <= 1; ++j)
        {
            if (x + j < 0 || x + j >= COLUMN)        // 列溢出
            {
                continue;
            }
            if (mine[y + i][x + j].bCover)
            {
                mine[y + i][x + j].bCover = false;
                check(y + i, x + j);
            }
        }
    }
    return false;
}

void print()
{
    system("cls");
    char help0[] = "←↑↓→";
    char help1[] = "移动光标";
    char help2[] = "空格\\回车";
    char help3[] = "  挖雷";
    char help4[] = "Esc 退出";
    gotoPos(4, 62);
    printf("%s", help0);
    gotoPos(6, 62);
    printf("%s", help1);
    gotoPos(9, 62);
    printf("%s", help2);
    gotoPos(11, 62);
    printf("%s", help3);
    gotoPos(14, 62);
    printf("%s", help4);

    gotoPos(0, 0);
    int i = 0, j = 0, k = 0;
    nLeftBlock = 0;
    printf("[M]---");
    for (k = 1; k < COLUMN - 1; ++k)
    {
        printf("+-----");
    }
    printf("+---[I]\n");
    for (i = 0; i < ROW; ++i)
    {
        for (j = 0; j < COLUMN; ++j)
        {
            if (mine[i][j].bCover)
            {
                ++nLeftBlock;
                printf("|  %c  ", 1);
            }
            else if (mine[i][j].nMine == -1 || mine[i][j].nMine == 9)
            {
                printf("|  %c  ", MINE);
            }
            else if (mine[i][j].nMine == 0)
            {
                printf("|  %c  ", ' ');
            }
            else
            {
                printf("|  %d  ", mine[i][j].nMine);
            }
        }
        printf("|\n");
        if (i < ROW - 1)
        {
            for (k = 0; k < COLUMN; ++k)
            {
                printf("+-----");
            }
            printf("+\n");
        }
    }
    printf("[N]---");
    for (k = 1; k < COLUMN - 1; ++k)
    {
        printf("+-----");
    }
    printf("+---[E]\n");
}

void welcome() {
    int i = 0;
    char words0[] = "《屌丝扫雷》";
    char words1[] = "之";
    char words2[] = "命令行版本";
    char words3[] = "版权所有 evangwt,谢谢 (=v = )";

    for (i = 0; i <= 5; ++i)
    {
        system("cls");
        gotoPos(i, (80 - strlen(words0)) / 2);
        printf("%s", words0);
        Sleep(50);
    }
    for (i = 78; i >= 39; --i)
    {
        gotoPos(7, i);
        printf("%s", words1);
        gotoPos(7, 78 - i);
        printf("%s", words1);
        Sleep(40);
    }
    for (i = 0; i <= (80 - strlen(words2)) / 2; ++i)
    {
        gotoPos(9, i);
        printf("%s", words2);
        Sleep(50);
    }
    for (i = 24; i >= 14; --i)
    {
        system("cls");
        gotoPos(5, (80 - strlen(words0)) / 2);
        printf("%s", words0);
        gotoPos(7, 39);
        printf("%s", words1);
        gotoPos(9, (80 - strlen(words2)) / 2);
        printf("%s", words2);
        gotoPos(i, (80 - strlen(words3)) / 2);
        printf("%s", words3);
        Sleep(50);
    }
    char help0[] = "{←↑↓→ 移动光标,空格\\回车 翻牌,Esc 退出}";
    char help1[] = "{其他暂停界面按任意键继续}";
    gotoPos(18, (80 - strlen(help0)) / 2);
    printf("%s", help0);
    gotoPos(19, (80 - strlen(help1)) / 2);
    printf("%s", help1);

    getch();
}

void over(char *str) {
    setColor(110);
    system("cls");
    gotoPos(10, 0);
    int i = 0;
    do
    {
        printf("%c", str[i]);
        Sleep(100);
    } while(str[i++]);
    system("pause");
    exit(0);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值