1. 程式人生 > >史上最牛C語言控制檯遊戲!C語言控制檯音遊——Rhythm Slasher! 附上原始碼供交流學習

史上最牛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。歡迎各位大佬指出更正。

程式碼和遊戲本體,我一併上傳到百度雲:

我是後記:

即使現在學了很多演算法,學了很多語言,很多東西,也再沒做出來什麼有趣的東西了。最近決定重拾心情做點什麼,哈哈~不管結果如何也算是一個嘗試,一番經歷~

最後,歡迎各位大佬來擾~

相關推薦

C語言控制檯遊戲C語言控制檯——Rhythm Slasher! 附上原始碼交流學習

這個遊戲是我大一上學期弄出來,剛學C語言,學了迴圈和選擇結構。那時候資料結構都不太會,但是按捺不住自己的想法,總想用現有的東西做點什麼。 就連窗體程式都不會,沒有任何的圖片,全是ASCII字元的一個遊戲,我為什麼敢說是史上最牛?我感覺牛不在演算法上,牛不在精美的介面,而是你

的Java架構師進階路線

驀然回首自己做開發已經十年了,這十年中我獲得了很多,技術能力、培訓、出國、大公司的經歷,還有很多很好的朋友。但再仔細一想,這十年中我至少浪費了五年時間,這五年可以足夠讓自己成長為一個優秀的程式設計師,可惜我錯過了,我用這五年時間和很多程式設計師一樣在困惑和迷茫中找不到出路! 路其實一直都在那裡,

Java架構師進階路線

1.工程化專題 (團隊大於3個人之後,你需要去考慮團隊合作,科學管理)   2. 原始碼分析專題 (好的程式設計師,一行程式碼一個設計就能看出來,原始碼分析帶你品味程式碼,感受架構)   3.高效能及分散式專題 (跟上技術節奏,擴寬技術視野

JAVA思維導圖學習筆記從初級到架構

我做過有道雲筆記、印象筆記,也寫過部落格,幾十篇文章之後,發現對筆記分類整理很麻煩,查詢不容易,往往自己寫的內容都不願意看一眼,後來用了思維導圖,很好用,結構清晰,一目瞭然,又靈機一動把導圖做成chm格式,你知道的API文件都是chm,離線狀態下就以查看了。在開發過程中,遇到

逼的純CSS實現tab選項卡,閃瞎你的狗眼

                     html檔案<!DOCTYPE html><html>    <head>        <meta charset="UTF-8">        <title>CSS3外觀漂亮淡入淡出Tab選單演示<

號稱X的程式設計師簡歷,萬千辛酸匯聚於此

網上流行著這麼一段程式設計師的自我評價:本人學識淵博、經驗豐富,程式碼風騷、效率恐怖,C/C++、java、php無不精通,熟練掌握各種框架,深山苦練20餘年,一天只睡4個小時,千里之外定位問題,瞬息之間修復上線。身體強壯、健步如飛,可連續程式設計100小時不休息,討論技術方

的Java思維學習導圖

我做過有道雲筆記、印象筆記,也寫過部落格,幾十篇文章之後,發現對筆記分類整理很麻煩,查詢不容易,往往自己寫的內容都不願意看一眼,後來用了思維導圖,很好用,結構清晰,一目瞭然,又靈機一動把導圖做成chm格式,你知道的API文件都是chm,離線狀態下就以查看了。在開發過程中,

的Linux視訊教程—兄弟連 學習筆記2

7月25日 4.2.2Linux常用命令-許可權管理命令-其他許可權管理命令(chown chgrp umask) 1. chown(改變檔案或者目錄的所有者) 原意:change file ownership 格式:chown [使用者] [檔案或目錄] 備註:只

女祕書 郵件內容

如果你今天還不知道“史上最牛女祕書”是誰,或者你還沒收到那封在網路上引起軒然大波的郵件,只能說明你不是那些著名外企中的一員。最近一週,從北京、上海到成都、廣州、南京……全國所有知名外企都在瘋狂轉發一封來自EMC(全球最大的網路資訊儲存商,總部在美國)北京總部的電子郵件:EMC

收益爆表,BEAM挖礦指南

  BEAM 是基於 MimbleWimble 協議開發的加密貨幣,採用 PoW 共識,致力於解決比特幣在擴充套件性和私密性上的不足,在國內外都備受關注。2019年1月3日晚上10點,各大礦池開始上線開挖。BEAM雖然目前還沒上線交易平臺,但是目前截止發稿時場外收購價已經達到18元一個。按照目前的挖

全的LINUX命令集

Linux # ethtool eth0 # Show the ethernet status (replaces mii-diag) # ethtool -s eth0 speed 100 duplex full # Force 100Mbit Full dup

的Linux視訊教程—兄弟連 學習筆記1

7月24日 3.1給初學者的建議——注意事項 1.Linux嚴格區分大小寫 2.硬碟檔案是/dev/sd[a-p]    光碟檔案/dev/sr0等 3.Linux沒有副檔名 4.Linux所有儲存裝置都必須掛載之後才能用(手工分配) 3.2給初學者的建議—

5次的黑客攻擊

好萊塢認為,黑客就像是使用計算機的黑魔導士。在電影中,計算機可以炸燬房屋,關閉公路,釋放瘟疫還有引發女權運動。也許有人認為,好萊塢的想象力很豐滿,但現實是骨感的。他們錯了,因為在現實中,確實也有如電影所描述的黑客行動,而且刺激程度絕對不亞於電影。 1、邏輯炸彈引爆西伯利亞 在1982年,在里根gov的CI

JAVA思維導圖學習筆記

我做過有道雲筆記、印象筆記,也寫過部落格,幾十篇文章之後,發現對筆記分類整理很麻煩,查詢不容易,往往自己寫的內容都不願意看一眼,後來用了思維導圖,很好用,結構清晰,一目瞭然,又靈機一動把導圖做成chm格式,你知道的API文件都是chm,離線狀態下就以查看了。在開發過程中,遇到某個點有些印象模糊了就開啟看一

逼的音樂播放器—仿網易雲音樂(已開源)

前言:音樂播放器倒見過不少,做到幾乎和官方網易雲音樂安卓版差不多的,還是頭第一回見。aa112901 的這款仿網易雲音樂安卓版客戶端,很多地方值得我們學習。無論是下載模組,還是換膚模組,還是炫麗的UI介面。等。用心在每一個細節。aa112901 本專案的github為:

號稱X的程序員簡歷,萬千辛酸匯聚於此

工作 效率 支持 不支持 拆遷 大牛 自己 前端 上線 網上流行著這麽一段程序員的自我評價: 本人學識淵博、經驗豐富,代碼風騷、效率恐怖,C/C++、java、php無不精通,熟練掌握各種框架,深山苦練20余年,一天只睡4個小時,千裏之外定位問題,瞬息之間修復上線。身體強壯

的5次黑客攻擊比電影更刺激

好萊塢認為,黑客就像是使用計算機的黑魔導士。在電影中,計算機可以炸燬房屋,關閉公路,釋放瘟疫還有

全socket模組詳解沒有學不會的模組只有學不學的模組

    import socket sk= socket.socket()#建立物件 sk.bind(('127.0.0.1',9999,))#繫結IP和埠,以一個元組的方式傳進去 sk.listen(5)#在前面連結已經建立的情況下,後面最多讓五

全Python基礎合集集合用法、檔案操作字元轉換、函式

    list = {1, 3, 6, 5, 7, 9, 11, 3, 7} # 定義集合方式一 list1 = set([1, 3, 6, 5, 7, 9, 11, 3, 7]) # 定義集合方式二 list2 = set() # 定義一個空集合 p

高新技術企業認定,詳細的申請攻略(深度好文)

相關 str 直接 方式 項目 微信 組織 名片 數據 在市場廣闊的今天,基本每個省和市地×××府都會建立產業園區或高新技術企業優化孵化帶,提供各種政策支持、稅收優惠以及財政補助。同時,高新技術企業資質對企業來說是一張閃亮的名片,相當於中國的品牌馳名商標,不僅能夠為企業帶來