史上最牛C语言控制台游戏!C语言控制台音游——Rhythm Slasher! 附上源代码供交流学习

这个游戏是我大一上学期弄出来,刚学C语言,学了循环和选择结构。那时候数据结构都不太会,但是按捺不住自己的想法,总想用现有的东西做点什么。

就连窗体程序都不会,没有任何的图片,全是ASCII字符的一个游戏,我为什么敢说是史上最牛?我感觉牛不在算法上,牛不在精美的界面,而是你仅仅用这样的条件,能创造出什么?

C语言和控制台,大概是程序员最熟悉,最早接触的东西了吧。说到C语言控制台游戏,你可能想到的是,贪吃蛇?RPG游戏?俄罗斯方块?我之前见过的比较牛的,也就一个打飞机游戏了。有人会说,毕竟是C语言控制台,做出来的东西也就只能是这样了吧,黑白的界面(也有彩色的,不过很少呐),光标一闪一闪,然后输入个数字按回车执行……我总觉得不甘心,我感觉还能做得更好。想了挺久,不如做个音游吧。于是三天之后,有了这个Rhythm Slasher!(我命名为节奏斩击者,不要吐槽我英语渣,中二什么的,哈哈)。下面先附上界面图:


光标呢?序号呢?我只想说,按上下选择,回车确定。还会变颜色,有没有很炫酷的感觉~


这游戏主要就是按你的喜好,录制出任意曲目的节奏,保存起来。之后就可以像节奏大师那样玩了。简而言之,就是可以用任何你喜欢的音乐,DIY你自己喜欢的任意节奏谱的简易版节奏大师。

介绍一下游戏方法:

1. 首先将任意一首音乐,放入到游戏本体目录所在的文件夹中。

2. 第一步先选择Record。选择你喜欢的音乐,然后听着音乐,录入节奏。就是根据节奏,按你的喜好敲击askl四个按键,录制你喜欢的节奏谱。

3. 之后,你就可以选择Slash,演奏你录制过节奏谱的音乐。游戏会按照你录制节奏谱时候的节奏,生成音符。你根据音符,配合节奏,在适当的时机敲击相应音符的按键,就可以演奏该乐曲,最后会统计你的分数。

ps:四个按键是可以设置的,Record只需要一次,之后你可以任意次Slash,即使关掉游戏,也不会丢失数据。音乐仅支持wav文件,因为使用的是C语言自带的播放音乐函数。


下面附上源代码,代码的注释还是比较详细的:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#pragma comment(lib, "winmm.lib")  //播放音乐所用头文件
#include <windows.h>

//函数声明
void Print_rhythm(char p,int v);//输出节奏音符
void Hide_cursor();//隐藏光标
int Choice_menus();//选择菜单,返回选项的编号(0,1,2,3)
void Cursor_goto_xy(int x,int y);//定位光标位置到指定坐标
void Selection(int n);//进入对应选项
void Record();//记录节奏
void Slash();//斩击节奏
void Setting();//设置按键
void Operate();//游戏说明

//全局变量定义
int n,i,start_music,good,miss,end,Select,SM;
char p,q,w,key1='a',key2='s',key3='k',key4='l';
char name[20][1000];

//主函数
int main()
{
    Hide_cursor();//隐藏光标
    system("mode con cols=66 lines=40 ");//控制台大小
    system("color 19");//前景色,后景色
    system("title Rhythm Slasher!");//窗口标题
    end=1;
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\tRhythm Slasher!\n\n\n\t\tPress any key to continue...");
    getch();
    while(end)
    {
        n=Choice_menus();//选择菜单,返回选项的编号(0,1,2,3)
        system("cls");
        Selection(n);//进入对应选项
    }
    return 0;
}


int Choice_menus()//选择菜单,返回选项的编号(0,1,2,3,4)
{
    char number,select;
    number=0;
    system("cls");
    printf("\n\n\n\n\n\n\n\n\n\t\t\t   Record!\n\n\n\n\t\t\t   Slash!\n\n\n\n\t\t\t   Setting!\n\n\n\n\t\t\t   Operate!\n\n\n\n\t\t\t   Exit!");
    while(1)
    {
        switch(number)
        {
        case 0:
            Cursor_goto_xy(21,9);//定位光标位置到指定坐标
            system("color 6e");//前景色,后景色
            break;
        case 1:
            Cursor_goto_xy(21,13);//定位光标位置到指定坐标
            system("color 5d");//前景色,后景色
            break;
        case 2:
            Cursor_goto_xy(21,17);//定位光标位置到指定坐标
            system("color 4c");//前景色,后景色
            break;
        case 3:
            Cursor_goto_xy(21,21);//定位光标位置到指定坐标
            system("color 2a");//前景色,后景色
            break;
        case 4:
            Cursor_goto_xy(21,25);//定位光标位置到指定坐标
            system("color 3b");//前景色,后景色
            break;
        }
        printf(">>>>");
        select=getch();
        if(select==72)//方向键,上
        {
            number--;
        }
        else if(select==80)//方向键,下
        {
            number++;
        }
        else if(select==13)//回车
        {
            return number;
        }
        number=(number+5)%5;
        printf("\b\b\b\b    ");
    }
}

void Selection(int n)//进入对应选项
{
    if(n==0)
    {
        Record();//记录节奏
    }
    else if(n==1)
    {
        Slash();//斩击节奏
    }
    else if(n==2)
    {
        Setting();//设置
    }
    else if(n==3)
    {
        Operate();//说明
    }
    else
    {
        end=0;//退出
    }
}

void Operate()//游戏说明
{
    printf("\n\n\n\n\n\t制作人 :   Lulu\n\n\n\t操作说明  :\n\n\tRecord! :\n");
    printf("\t根据音乐节奏按下按键,由左到右依次按键为a,s,k,l。\n");
    printf("\t系统将记录下你的按键,作为歌曲的节奏谱。\n");
    printf("\t按键可以在设置中调整。\n");
    printf("\n\tSlash! :\n");
    printf("\t使用上一次Record!制成的节奏谱,生成节奏音符。\n");
    printf("\t由左往右依次按键为a,s,k,l。随音乐节奏击破!\n");
    printf("\t按键可以在设置中调整。\n");
    printf("\n\tSetting! :\n");
    printf("\t设置游戏按键。\n");
    printf("\n\tOperate! :\n");
    printf("\t游戏说明。\n");
    printf("\n\tExit! :\n");
    printf("\t退出。\n");
    printf("\n\t\t\t按任意键返回。\n");
    getch();
}

void Setting()//设置按键
{
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\tkey1 :    ");
    key1=getch();
    printf("%c",key1);
    Sleep(1000);
    system("cls");
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\tkey2 :    ");
    key2=getch();
    printf("%c",key2);
    Sleep(1000);
    system("cls");
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\tkey3 :    ");
    key3=getch();
    printf("%c",key3);
    Sleep(1000);
    system("cls");
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\tkey4 :    ");
    key4=getch();
    printf("%c",key4);
    Sleep(1000);
    system("cls");
    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\tSetting succeeded!");
    printf("\n\n\t\t   Press any key to continue...");
    getch();
}
int Select_music()//选择音乐
{
    int i,n;
    FILE *fp = NULL;

    system("dir /b *.wav>> buf.Ock");//将目录导出到buf.Ock

    fp = fopen("buf.Ock","rb");
    i=0;
    while (!feof(fp))
    {
        fgets(name[i],1000,fp);
        name[i][strlen(name[i])-6]='\0';
        i++;
    }
    n=i;
    fclose(fp);
    system("del /Q buf.Ock");  //删除D:目录下buf.Ock文件
    char number=0,select;
    Select=0;
    system("cls");
    for(i=0; i<n-1; i++)
    {
        printf("\n\t%d. %s\n",i+1,name[i]);
    }
    while(1)
    {
        Cursor_goto_xy(2,2*number+1);//定位光标位置到指定坐标
        if(number%2==0)
            system("color 6e");//前景色,后景色
        else
            system("color 5d");//前景色,后景色
        printf(">>>>");
        select=getch();
        if(select==72)//方向键,上
        {
            number--;
        }
        else if(select==80)//方向键,下
        {
            number++;
        }
        else if(select==13)//回车
        {
            return number;
        }
        number=(number+n-1)%(n-1);
        printf("\b\b\b\b    ");
    }
}
void Record()//记录节奏
{
    char musicNamer[100],musicNamew[100],musicName[100],musicNamev[100];
    int v;
    SM=Select_music();//选择音乐
    system("cls");
    FILE *fp1;//定义文件指针
    FILE *fp2;//定义文件指针
    FILE *fp3;//定义文件指针
    strcpy(musicNamer,name[SM]);
    strcpy(musicNamew,name[SM]);
    strcpy(musicName,name[SM]);
    strcpy(musicNamev,name[SM]);
    strcat(musicNamer,"r.txt");
    strcat(musicNamew,"w.txt");
    strcat(musicNamev,"v.txt");
    strcat(musicName,".wav");
    fp1=fopen(musicNamer,"w");//以写入模式(w)打开文件
    fp2=fopen(musicNamew,"w");
    fp3=fopen(musicNamev,"w");
    printf("Set the velocity of this song(20 to 70):");
    scanf("%d",&v);
    fprintf(fp3,"%d",v);
    fclose(fp3);
    printf("\n\tReady?");
    for(i=39; i>0; i--)
    {
        printf("\n  !      !      !      !  ");
    }
    fprintf(fp2,"00000000");
    getch();
    PlaySound(musicName,NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);//播放音乐
    while(1)
    {
        if(kbhit())//kbhit(),监测当前是否有按键按下,有返回非零值,无,返回零
        {
            p=getch();
            while(kbhit()) //实际上,亲测发现,只要缓冲区有数据存在,都视为有按键按下。故可以用它清空缓冲区
            {
                getch();//当缓冲区有数据时,用getch()提取数据,直至缓冲区空
            }
            if(p==key1)
            {
                p='1';
            }
            else if(p==key2)
            {
                p='2';
            }
            else if(p==key3)
            {
                p='3';
            }
            else if(p==key4)
            {
                p='4';
            }
            else
            {
                fprintf(fp1,"00000000");
                PlaySound(NULL, NULL, SND_PURGE) ;//停止播放音乐
                fprintf(fp1,"5");//写入到文件函数
                fprintf(fp2,"5");
                fclose(fp1);//关闭文件
                fclose(fp2);
                break;
            }
        }
        else
        {
            p='0';
        }
        fprintf(fp1,"%c",p);
        fprintf(fp2,"%c",p);
        Print_rhythm(p,v);//生成节奏音符
    }
    printf("\n\tComplete!\n");
    printf("Press any key to continue...");
    getch();
    system("cls");
}

void Slash()//斩击节奏
{
    char musicNamer[100],musicNamew[100],musicName[100],musicNamev[100];
    int v;
    good=0;
    miss=0;
    FILE *fin1;
    FILE *fin2;
    FILE *fin3;
    SM=Select_music();//选择音乐
    system("cls");
    strcpy(musicNamer,name[SM]);
    strcpy(musicNamew,name[SM]);
    strcpy(musicName,name[SM]);
    strcpy(musicNamev,name[SM]);
    strcat(musicNamer,"r.txt");
    strcat(musicNamew,"w.txt");
    strcat(musicNamev,"v.txt");
    strcat(musicName,".wav");
    fin1=fopen(musicNamer,"r");//以读取模式(r)打开文件
    fin2=fopen(musicNamew,"r");
    fin3=fopen(musicNamev,"r");
    fscanf(fin3,"%d",&v);
    fclose(fin3);
    printf("The velocity of this music is %d\n",v);
    printf("\tReady?");
    for(i=39; i>0; i--)
    {
        printf("\n  !      !      !      !  ");
    }
    start_music=0;
    getch();
    while(1)
    {
        if(start_music==10)//延迟播放音乐
        {
            PlaySound(musicName,NULL,SND_FILENAME|SND_ASYNC|SND_LOOP);//播放音乐
        }
        start_music++;
        fscanf(fin1,"%c",&p);//读取文件函数
        fscanf(fin2,"%c",&w);
        if(p=='5')
        {
            PlaySound(NULL, NULL, SND_PURGE) ;
            fclose(fin1);
            fclose(fin2);
            break;
        }
        Print_rhythm(p,v);//生成节奏音符
        if(kbhit())
        {
            q=getch();
            while(kbhit())
            {
                getch();
            }
            if(q==key1)
            {
                q='1';
            }
            else if(q==key2)
            {
                q='2';
            }
            else if(q==key3)
            {
                q='3';
            }
            else if(q==key4)
            {
                q='4';
            }
        }
        else
        {
            q='0';
        }
        if(q==w)
        {
            //system("color 20");
            printf("Good!");//正确提示
            good++;
        }
        else
        {
            //system("color 40");
            printf("Miss!!!!!!!!!!!!!!!!!!!!!!");//错误提示
            miss++;
        }
    }
    printf("\n\tFinish play!\n");
    printf("Total:%d   Good:%d   Miss:%d\n",good+miss,good,miss);
    printf("Press any key to continue...");
    getch();
    system("cls");
}

void Cursor_goto_xy(int x,int y)//定位光标位置到指定坐标
{
    HANDLE hOut;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD pos= {x,y};
    SetConsoleCursorPosition(hOut,pos);
}

void Hide_cursor()//隐藏光标
{
    CONSOLE_CURSOR_INFO cursor_info = {1, 0};
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}


void Print_rhythm(char p,int v)//生成节奏音符
{
    if(p=='0')
    {
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
    }
    else if(p=='1')
    {
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n 888     !      !      !  ");
        Sleep(v);
        printf("\n 888     !      !      !  ");
        Sleep(v);
        printf("\n 888     !      !      !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
    }
    else if(p=='2')
    {
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !     888     !      !  ");
        Sleep(v);
        printf("\n  !     888     !      !  ");
        Sleep(v);
        printf("\n  !     888     !      !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
    }
    else if(p=='3')
    {
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !      !     888     !  ");
        Sleep(v);
        printf("\n  !      !     888     !  ");
        Sleep(v);
        printf("\n  !      !     888     !  ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
    }
    else if(p=='4')
    {
        printf("\n  !      !      !      !  ");
        Sleep(v);
        printf("\n  !      !      !     888 ");
        Sleep(v);
        printf("\n  !      !      !     888 ");
        Sleep(v);
        printf("\n  !      !      !     888 ");
        Sleep(v);
        printf("\n  !      !      !      !  ");
        Sleep(v);
    }
}

代码只用了循环和判断,还有文件读写,理解起来应该不难。

本渣渣能力有限,代码可能显得累赘而且程序功能不全,有bug。欢迎各位大佬指出更正。

代码和游戏本体,我一并上传到百度云:

我是链接君,点我下载游戏源码和本体


我是后记:

即使现在学了很多算法,学了很多语言,很多东西,也再没做出来什么有趣的东西了。最近决定重拾心情做点什么,哈哈~不管结果如何也算是一个尝试,一番经历~

最后,欢迎各位大佬来扰~


  • 22
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值