C语言频闪问题与时间显示

C语言迷宫游戏设计如何解决屏幕严重刷屏问题同时实现运行时间的显示?


/* 迷宫游戏.exe 3.0 */ 
#include<stdio.h> //标准输入输出头文件 
#include<stdlib.h> //函数system():发出一个DOS命令 
#include<conio.h> //函数kbhit():检测键盘是否按下; 函数getch():获取用户输入(无需回车) 
#include<windows.h> //函数Sleep():将程序挂起一段时间 
#include<time.h> //计算游戏时间 
#define N 50
#define M 50
void Show(int maze[][M],int n,int m);
void MazeUpdate(int maze[][M],int n,int m,double start); 
int maze[N][M] =
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1},
 {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1},
 {1,0,1,0,1,0,1,1,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,0,1},
 {1,0,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,1,1,1},
 {1,0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1},
 {1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1},
 {1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1},
 {1,0,1,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,1},
 {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3},
 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
double times;
int main(void)
{
    clock_t start; //首先用clock_t定义两个变量储存开始与结束值 
    printf("游戏加载中...\n");
    Sleep(500);
    system("PAUSE");
    start = clock(); //记录开始时间
    int n = 12,m = 25;  // n行m列 
    Show(maze,n,m);  
    MazeUpdate(maze,n,m,start);
    
    return 0;
}


//函数功能:显示迷宫地图 
void Show(int maze[][M],int n,int m) 
{
    int i,j;
    for (i=0;i<n;i++) //显示n行m列迷宫地图数据 
    {
        for (j=0;j<m;j++)
        {
            if (maze[i][j]==0)
            {
                printf("  "); //显示路径 
            }
            else if (maze[i][j]==1)
            {
                printf("▓ "); //显示障碍物 
            }
            else if (maze[i][j]==2)
            {
                printf("☆"); //显示电子鼠    
            }
            else if (maze[i][j]==3)
            {
                printf("★");
            }
        }
        printf("\n"); 
    }
}

//函数功能:完成与用户输入有关的迷宫更新
void MazeUpdate(int maze[][M],int n,int m,double start)
{
    int x = 1,y = 23; //初始位置
    int exitX = 10, exitY = 24; //迷宫出口
    char input;
    clock_t end; 
    while (x!=exitX || y!=exitY) //判断是否达到迷宫出口 
    {
        if (kbhit()) //检查是否有键盘输入,没有就继续循环
        {
            input = getch(); //从键盘获取输入(不会在屏幕显示) 
            if (input=='a' && maze[x][y-1]!=1) //左移
            {
                maze[x][y] = 0;
                y--;
                maze[x][y] = 2;    
            }
            if (input=='d' && maze[x][y+1]!=1) //右移
            {
                maze[x][y] = 0;
                y++;
                maze[x][y] = 2;    
            }
            if (input=='w' && maze[x-1][y]!=1) //上移
            {
                maze[x][y] = 0;
                x--;
                maze[x][y] = 2;
            }
            if (input=='s' && maze[x+1][y]!=1) //下移 
            {
                maze[x][y] = 0;
                x++;
                maze[x][y] = 2; 
            }
        } 
        system("cls"); //清屏
        printf("    \t\t迷宫游戏3.0.exe\n"); 
        if (x!=exitX || y!=exitY) //副标题提示进行和结束 
        {
            printf("    \t\t    进行中\n");
        } 
        else
        {
            printf("    \t\t    已结束\n");
        }
        Show(maze,n,m); //显示更新后的迷宫
        Sleep(100); //延时100ms
        
        end = clock(); //记录结束时间 
        times = ((double)(end-start))/CLK_TCK;
        printf("总用时间%.1fs",times); 
        
          
    }
    printf("You win!\n");
    system("PAUSE"); //Windows系统下暂停程序运行 
} 


img

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7693362
  • 你也可以参考下这篇文章:C语言 详解如何编写闪烁显示字符串的函数
  • 你还可以看下c语言参考手册中的 c语言-成员访问与间接
  • 除此之外, 这篇博客: C语言双向链表实现对字符串的存储中的 构造展示双向链表元素的函数 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    // 展示字符串内容的函数 
    void displayLink(link *head){
    	while(head != NULL){
    		for(int i = 0; i < linkNum; i++){
    			printf("%c", head->a[i]);
    		}
    		head = head->next;
    	}
    	printf("\n"); 
    }
    
  • 您还可以看一下 贺利坚老师的C语言及程序设计初步课程中的 数值数据类型及表示小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    针对迷宫游戏频繁刷屏导致用户体验下降的问题,一个解决方案是使用ncurses库,在控制台中使用其提供的函数进行控制台输出的刷新,避免频繁刷屏。具体步骤如下:

    1. 安装ncurses库:在Linux中使用命令sudo apt-get install libncurses5-dev安装ncurses库。

    2. 在程序中包含ncurses.h头文件。

    3. 在需要输出的位置,使用ncurses库提供的函数进行输出,例如使用move()函数移动光标到指定的位置,使用printw()函数进行输出。

    4. 使用refresh()函数刷新输出。

    相关代码示例:

    #include <ncurses.h> 
    int main() 
    { 
        initscr(); //初始化
        printw("Hello, World!"); //输出
        refresh(); //刷新
        getch(); //等待输入
        endwin(); //结束
        return 0; 
    }
    

    针对时间的显示,一个解决方案是使用time.h头文件中的函数获取当前时间,并使用ncurses库输出时间信息。具体步骤如下:

    1. 包含time.h头文件。

    2. 使用time()函数获取当前时间。

    3. 使用localtime()函数将时间转换为本地时间结构体tm类型。

    4. 使用strftime()函数将tm类型的时间格式化为字符串。

    5. 使用ncurses库输出时间字符串。

    相关代码示例:

    #include <time.h>
    #include <ncurses.h>
    
    int main() 
    {
        time_t current_time;
        struct tm * time_info;
        char time_string[9]; //存储时间字符串
        initscr();
        time(&current_time); //获取当前时间
        time_info = localtime(&current_time); //转换为本地时间
        strftime(time_string, sizeof(time_string), "%H:%M:%S", time_info); //格式化为字符串
        printw("Current Time: %s", time_string); //输出
        refresh();
        getch();
        endwin();
        return 0;
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

屏幕严重刷屏问题可以通过在更新迷宫前先清屏的方式来解决,例如使用system("cls")函数可以清除屏幕内容。实现运行时间显示可以通过记录游戏的开始和结束时间,然后计算时间差来获取游戏的运行时间,最后将其以秒为单位显示出来即可。在代码中已经使用了clock()函数记录了开始时间,并在MazeUpdate()函数中使用clock()函数记录结束时间,然后用end-start得到时间差,并将其转换为秒数。最后调用printf()函数将其显示出来即可。
修改后的代码可以参考下面的示例:

/* 迷宫游戏.exe 3.1 */ 
#include<stdio.h> //标准输入输出头文件 
#include<stdlib.h> //函数system():发出一个DOS命令 
#include<conio.h> //函数kbhit():检测键盘是否按下; 函数getch():获取用户输入(无需回车) 
#include<windows.h> //函数Sleep():将程序挂起一段时间 
#include<time.h> //计算游戏时间 
#define N 50
#define M 50

void Show(int maze[][M],int n,int m);
void MazeUpdate(int maze[][M],int n,int m,double start); 
int maze[N][M] =
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1},
 {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1},
 {1,0,1,0,1,0,1,1,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,0,1},
 {1,0,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,1,1,1},
 {1,0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1},
 {1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1},
 {1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1},
 {1,0,1,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,1},
 {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3},
 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};

int main(void)
{
    double start_t = clock(); //记录开始时间
    int n = 12,m = 25;  // n行m列 
    printf("游戏加载中...\n");
    Sleep(500);
    system("PAUSE");
    Show(maze,n,m);  
    MazeUpdate(maze,n,m,start_t);
    
    return 0;
}

//函数功能:显示迷宫地图 
void Show(int maze[][M],int n,int m) 
{
    int i,j;
    for (i=0;i<n;i++) //显示n行m列迷宫地图数据 
    {
        for (j=0;j<m;j++)
        {
            if (maze[i][j]==0)
            {
                printf("  "); //显示路径 
            }
            else if (maze[i][j]==1)
            {
                printf("▓ "); //显示障碍物 
            }
            else if (maze[i][j]==2)
            {
                printf("☆"); //显示电子鼠    
            }
            else if (maze[i][j]==3)
            {
                printf("★");
            }
        }
        printf("\n"); 
    }
}

//函数功能:完成与用户输入有关的迷宫更新
void MazeUpdate(int maze[][M],int n,int m,double start_t)
{
    int x = 1,y = 23; //初始位置
    int exitX = 10, exitY = 24; //迷宫出口
    char input;
    double end_t; 
    while (x!=exitX || y!=exitY) //判断是否达到迷宫出口 
    {
        if (kbhit()) //检查是否有键盘输入,没有就继续循环
        {
            input = getch(); //从键盘获取输入(不会在屏幕显示) 
            if (input=='a' && maze[x][y-1]!=1) //左移
            {
                maze[x][y] = 0;
                y--;
                maze[x][y] = 2;    
            }
            if (input=='d' && maze[x][y+1]!=1) //右移
            {
                maze[x][y] = 0;
                y++;
                maze[x][y] = 2;    
            }
            if (input=='w' && maze[x-1][y]!=1) //上移
            {
                maze[x][y] = 0;
                x--;
                maze[x][y] = 2;
            }
            if (input=='s' && maze[x+1][y]!=1) //下移 
            {
                maze[x][y] = 0;
                x++;
                maze[x][y] = 2; 
            }
        } 
        system("cls"); //清屏
        printf("\t\t迷宫游戏3.1.exe\n"); 
        if (x!=exitX || y!=exitY) //副标题提示进行和结束 
        {
            printf("\t\t\t进行中\n");
        } 
        else
        {
            printf("\t\t\t已结束\n");
        }
        Show(maze,n,m); //显示更新后的迷宫
        Sleep(100); //延时100ms

        end_t = clock(); //记录结束时间 
        double used_time = (end_t - start_t) / CLOCKS_PER_SEC; //计算游戏时间
        printf("总用时间%.1f s\n", used_time);
    }
    printf("You win!\n");
    system("PAUSE"); //Windows系统下暂停程序运行 
}

在代码中,我们使用了start_t记录开始时间,使用了end_t记录结束时间,并且计算游戏所用时间时也针对性地修改了相关代码,这样就能够清晰地显示出游戏所用的时间了。

字符界面本来刷新率不高,所以频繁刷新肯定会闪烁.
对于你这个迷宫游戏,按键后才会更新画面,所以不用一直更新画面,可以在有按键后再更新

/* 迷宫游戏.exe 3.0 */ 
#include<stdio.h> //标准输入输出头文件 
#include<stdlib.h> //函数system():发出一个DOS命令 
#include<conio.h> //函数kbhit():检测键盘是否按下; 函数getch():获取用户输入(无需回车) 
#include<windows.h> //函数Sleep():将程序挂起一段时间 
#include<time.h> //计算游戏时间 
#define N 50
#define M 50
void Show(int maze[][M],int n,int m);
void MazeUpdate(int maze[][M],int n,int m,double start); 
int maze[N][M] =
{{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1},
 {1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
 {1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1},
 {1,0,1,0,1,0,1,1,1,0,1,1,0,0,1,0,1,0,0,1,0,1,1,0,1},
 {1,0,1,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,0,1,1,0,1,1,1},
 {1,0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,1},
 {1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1},
 {1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1},
 {1,0,1,0,1,0,1,0,1,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,1},
 {1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3},
 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
double times;
int main(void)
{
    clock_t start; //首先用clock_t定义两个变量储存开始与结束值 
    printf("游戏加载中...\n");
    Sleep(500);
    system("PAUSE");
    start = clock(); //记录开始时间
    int n = 12,m = 25;  // n行m列 
    Show(maze,n,m);  
    MazeUpdate(maze,n,m,start);
    
    return 0;
}


//函数功能:显示迷宫地图 
void Show(int maze[][M],int n,int m) 
{
    int i,j;
    for (i=0;i<n;i++) //显示n行m列迷宫地图数据 
    {
        for (j=0;j<m;j++)
        {
            if (maze[i][j]==0)
            {
                printf("  "); //显示路径 
            }
            else if (maze[i][j]==1)
            {
                printf("▓ "); //显示障碍物 
            }
            else if (maze[i][j]==2)
            {
                printf("☆"); //显示电子鼠    
            }
            else if (maze[i][j]==3)
            {
                printf("★");
            }
        }
        printf("\n"); 
    }
}

//函数功能:完成与用户输入有关的迷宫更新
void MazeUpdate(int maze[][M],int n,int m,double start)
{
    int x = 1,y = 23; //初始位置
    int exitX = 10, exitY = 24; //迷宫出口
    char input;
    clock_t end; 
    while (x!=exitX || y!=exitY) //判断是否达到迷宫出口 
    {
        if (kbhit()) //检查是否有键盘输入,没有就继续循环
        {
            input = getch(); //从键盘获取输入(不会在屏幕显示) 
            if (input=='a' && maze[x][y-1]!=1) //左移
            {
                maze[x][y] = 0;
                y--;
                maze[x][y] = 2;    
            }
            if (input=='d' && maze[x][y+1]!=1) //右移
            {
                maze[x][y] = 0;
                y++;
                maze[x][y] = 2;    
            }
            if (input=='w' && maze[x-1][y]!=1) //上移
            {
                maze[x][y] = 0;
                x--;
                maze[x][y] = 2;
            }
            if (input=='s' && maze[x+1][y]!=1) //下移 
            {
                maze[x][y] = 0;
                x++;
                maze[x][y] = 2; 
            }
            system("cls"); //清屏
            printf("    \t\t迷宫游戏3.0.exe\n"); 
            if (x!=exitX || y!=exitY) //副标题提示进行和结束 
            {
                printf("    \t\t    进行中\n");
            } 
            else
            {
                printf("    \t\t    已结束\n");
            }
            Show(maze,n,m); //显示更新后的迷宫
            Sleep(100); //延时100ms
        
            end = clock(); //记录结束时间 
            times = ((double)(end-start))/CLK_TCK;
            printf("总用时间%.1fs",times); 
        } 
        
          
    }
    printf("You win!\n");
    system("PAUSE"); //Windows系统下暂停程序运行 
} 



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

int main(int argc,const char* argv[])
{
    char maze[10][10]={
        {1,1,1,1,1,1,1,1,1,1},
        {1,1,1,1,1,1,1,1,1,1},
        {1,1,1,1,1,0,0,0,1,1},
        {1,0,1,1,1,0,1,0,1,1},
        {1,2,1,0,0,0,1,0,1,1},
        {1,0,1,0,1,1,1,0,1,1},
        {1,0,1,0,1,1,1,0,1,1},
        {1,0,0,0,1,1,1,0,1,1},
        {1,1,1,1,1,1,1,0,0,0},
        {1,1,1,1,1,1,1,1,1,1}
        };
    //设置老鼠初始坐标
    int m_x=4,m_y=1;
    
    //h获取开始时间
    time_t start_time = time(NULL);
    
    for(;;) //死循环
    {
        system("clear");
        //打印地图
        for(int i=0;i<10;i++)
        {
            for(int j=0;j<10;j++)
            {
                switch(maze[i][j])
                {
                    case 0:printf("  ");break;
                    case 1:printf("# ");break;
                    case 2:printf("@ ");break;
                }
            }
            printf("\n");
        }
        
        //判断是否到达终点
        if(8==m_x && 9==m_y)
        {
            time_t end_time=time(NULL);
            printf("游戏结束!用时%ds\n",end_time-start_time);
            break;
        }
        
        switch(getch())
        {
            case 183://上
                if(0==maze[m_x-1][m_y])
                {
                    maze[m_x-1][m_y]=2;
                    maze[m_x][m_y]=0;
                    m_x=m_x-1;
                }
                break;
            case 184://下
                if(0==maze[m_x+1][m_y])
                {
                    maze[m_x+1][m_y]=2;
                    maze[m_x][m_y]=0;
                    m_x=m_x+1;
                }
                break;
            case 185://右
                if(0==maze[m_x][m_y+1])
                {
                    maze[m_x][m_y+1]=2;
                    maze[m_x][m_y]=0;
                    m_y=m_y+1;
                }
                break;
            case 186://左
                if(0==maze[m_x][m_y-1])
                {
                    maze[m_x][m_y-1]=2;
                    maze[m_x][m_y]=0;
                    m_y=m_y-1;
                }
                break;
        }
    }
}