You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为C语言实现的扫雷游戏添加游戏时长计时功能

给C语言扫雷游戏添加计时器功能

你手头有一款运行正常的C语言扫雷游戏,现在需要给它加上计时器功能,让游戏在结束(不管是胜利还是触雷失败)时显示玩家的游戏时长。下面是完整的修改方案和可运行代码:

实现思路

我们利用C标准库<time.h>里的工具来实现计时:

  • 用time_t类型变量记录游戏开始和结束的时间点
  • 在雷区生成完成、玩家开始猜坐标前启动计时
  • 游戏结束时计算时间差,转换成秒数并友好展示

修改后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define FLUSH fflush(stdin)

// 全局变量
int x, y;
int M, N;
float diff;
int total_mines = 0;
int mines = 0;
int minefield[30][30];       // 存储地雷、数字和空白的核心棋盘
int blank_minefield[30][30]; // 显示给玩家的初始棋盘(全为'-')
int final_minefield[30][30]; // 游戏结束后展示的完整棋盘
time_t start_time, end_time; // 计时用的时间点变量
double game_duration;        // 最终计算出的游戏时长(秒)

// 函数声明
void difficulty( void );
void beginner( void );
void intermediate( void );
void expert( void );
void custom( void );
void minefield_generator( void );
void print_minefield( void );
void guess( void );
void boom( void );
void print_final_minefield( void );
void win( void );
void play_again( void );
void game_over( void );

int main() {
    printf("\t\tWelcome to Minesweeper\n");
    difficulty();
    return 0;
}

void difficulty( void ) {
    diff = 0;
    while( (diff != 1) && (diff != 2) && (diff != 3) && (diff != 4)) {
        printf("\t\tChoose a difficulty level(1-3) or 4 for a custom game:");
        scanf("%f", &diff);
        FLUSH;
        if( (diff != 1) && (diff != 2) && (diff != 3) && (diff != 4)) {
            printf("\t\tPlease enter either 1, 2, 3 or 4\n");
        }
    }
    if( diff == 1 ) {
        beginner();
    } else if( diff == 2 ) {
        intermediate();
    } else if( diff == 3 ) {
        expert();
    } else if( diff == 4) {
        custom();
    }
}

void beginner( void ) {
    M = 9;
    N = 9;
    total_mines = 10;
    minefield_generator();
    start_time = time(NULL); // 生成雷区后启动计时
    guess();
}

void intermediate( void ) {
    M = 16;
    N = 16;
    total_mines = 40;
    minefield_generator();
    start_time = time(NULL); // 启动计时
    guess();
}

void expert( void ) {
    M = 16;
    N = 30;
    total_mines = 99;
    minefield_generator();
    start_time = time(NULL); // 启动计时
    guess();
}

void custom( void ) {
    M = 0;
    N = 0;
    total_mines = 0;
    printf("\t\tPlease enter the size of the dimensions you want\n");
    printf("\t\tFirst value:\n");
    scanf("%d", &M);
    printf("\t\tSecond value:\n");
    scanf("%d", &N);
    printf("\t\tNumber of mines you want to assign to the board:\n");
    scanf("%d", &total_mines);
    minefield_generator();
    start_time = time(NULL); // 启动计时
    guess();
}

void minefield_generator( void ) {
    int i = 0, j = 0;
    srand( time( NULL ) );

    // 初始化三个棋盘的初始状态
    while( j < N ) {
        while( i < M) {
            minefield[i][j] = '-';
            blank_minefield[i][j] = minefield[i][j];
            final_minefield[i][j] = minefield[i][j];
            i++;
        }
        i = 0;
        j++;
    }

    // 随机生成地雷
    mines = 0;
    while( mines < total_mines ) {
        i = rand()%(M);
        j = rand()%(N);
        if( minefield[i][j] != '*') {
            minefield[i][j] = '*';
            final_minefield[i][j] = minefield[i][j];
            mines++;
        }
    }

    // 计算每个非雷格子的相邻地雷数量
    i = 0;
    j = 0;
    while( j < N ) {
        while( i < M) {
            if( minefield[i][j] != '*') {
                minefield[i][j] = 0;
                // 检查8个相邻方向的地雷
                if(i > 0 && j > 0 && minefield[i-1][j-1] == '*') minefield[i][j]++;
                if(i > 0 && minefield[i-1][j] == '*') minefield[i][j]++;
                if(j > 0 && minefield[i][j-1] == '*') minefield[i][j]++;
                if(i > 0 && j < N-1 && minefield[i-1][j+1] == '*') minefield[i][j]++;
                if(i < M-1 && j > 0 && minefield[i+1][j-1] == '*') minefield[i][j]++;
                if(i < M-1 && minefield[i+1][j] == '*') minefield[i][j]++;
                if(j < N-1 && minefield[i][j+1] == '*') minefield[i][j]++;
                if(i < M-1 && j < N-1 && minefield[i+1][j+1] == '*') minefield[i][j]++;
            }
            i++;
        }
        i = 0;
        j++;
    }
}

void print_minefield(void) {
    int i = 0, j = 0, z = 0;
    // 打印X轴坐标
    printf("\t");
    while( z < M ) {
        printf("|%d|\t", z);
        z++;
    }
    printf("\n\n");
    // 打印棋盘内容和Y轴坐标
    while( j < N ) {
        printf("|%d|\t", j);
        while( i < M) {
            if( blank_minefield[i][j] == '-') {
                printf("|%c|\t", blank_minefield[i][j]);
            } else {
                printf("|%d|\t", blank_minefield[i][j]);
            }
            i++;
        }
        printf("\n\n");
        i = 0;
        j++;
    }
}

// 玩家猜坐标的核心逻辑
void guess( void ) {
    int revealed = 0;
    int total_safe = M*N - total_mines; // 非雷格子总数
    while(1) {
        print_minefield();
        printf("\t\tEnter coordinates (x y): ");
        scanf("%d %d", &x, &y);
        FLUSH;

        // 检查坐标是否合法
        if(x < 0 || x >= M || y < 0 || y >= N) {
            printf("\t\tInvalid coordinates! Try again.\n");
            continue;
        }

        // 触雷失败
        if(minefield[x][y] == '*') {
            boom();
            break;
        }

        // 揭开未探索的格子
        if(blank_minefield[x][y] == '-') {
            blank_minefield[x][y] = minefield[x][y];
            revealed++;
            // 检查是否清空所有非雷格子(胜利条件)
            if(revealed == total_safe) {
                win();
                break;
            }
        }
    }
}

// 触雷失败的处理函数
void boom( void ) {
    end_time = time(NULL);
    game_duration = difftime(end_time, start_time);
    printf("\n\t\tBOOM! You hit a mine!\n");
    printf("\t\tYour game lasted %.2f seconds.\n", game_duration);
    print_final_minefield();
    play_again();
}

// 游戏胜利的处理函数
void win( void ) {
    end_time = time(NULL);
    game_duration = difftime(end_time, start_time);
    printf("\n\t\tCongratulations! You Win!\n");
    printf("\t\tYour game took %.2f seconds.\n", game_duration);
    print_final_minefield();
    play_again();
}

// 显示最终完整棋盘
void print_final_minefield( void ) {
    int i = 0, j = 0, z = 0;
    printf("\t\tFinal Minefield:\n");
    printf("\t");
    while( z < M ) {
        printf("|%d|\t", z);
        z++;
    }
    printf("\n\n");
    while( j < N ) {
        printf("|%d|\t", j);
        while( i < M) {
            if(final_minefield[i][j] == '*') {
                printf("|%c|\t", final_minefield[i][j]);
            } else {
                printf("|%d|\t", final_minefield[i][j]);
            }
            i++;
        }
        printf("\n\n");
        i = 0;
        j++;
    }
}

// 询问是否再玩一局
void play_again( void ) {
    char choice;
    printf("\t\tPlay again? (Y/N): ");
    scanf(" %c", &choice);
    FLUSH;
    if(choice == 'Y' || choice == 'y') {
        difficulty();
    } else {
        game_over();
    }
}

// 退出游戏
void game_over( void ) {
    printf("\t\tThanks for playing Minesweeper!\n");
    exit(0);
}

修改要点说明

  1. 新增计时变量:添加了time_t类型的时间点变量和double类型的时长变量,用于存储和计算游戏时间
  2. 启动计时:在每个难度模式的雷区生成完成后,调用start_time = time(NULL);开始计时
  3. 结束计时并展示:在boom()(失败)和win()(胜利)函数中,获取结束时间,用difftime()计算时间差,格式化后显示给玩家
  4. 补全缺失代码:完善了原代码中未完成的print_minefield、guess等函数,确保代码可以完整编译运行

内容的提问来源于stack exchange,提问作者Jose Luis Mendoza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:44:51