用ncurses庫寫掃雷
文章目錄
前言
經過一整子的瞎折騰,我終於完成了ncurses版的掃雷。這讓我進一步認識到了ncurses庫的強大。這裡主要的新知識點是"滑鼠事件的獲取和處理",可以參考這篇文章,雖然排版湊合但還是挺實用的。相比寫情詩,掃雷的程式碼量還是比較大的,我的版本前後有100多行的樣子。我用思維導圖整理了我的思路,一個功能基本就一個函式。擴充套件功能我這裡完成了前兩個,但已經夠用了,掃雷的基本操作測試下來很流暢。
一、思路
二、程式碼實現
1.標頭檔案
#include <stdlib.h> //要用到srand()和rand()生成雷
#include <time.h> //要用到clock()生成隨機數種子
#include <ncurses.h> //主角不用解釋
2.全域性變數和巨集定義
#define MINENUM 10 //雷的總數
#define row 9 //雷區的行數
#define line 9 //雷區的列數
int a[row][line]; //0:周圍沒有雷 -1:此處有雷 1~8:周圍雷的數量
int f[row][line]; //0:未探索 1:已探索
int win; //用於記錄輸贏的資訊
3.main()
初始化
initscr(); //初始化螢幕
curs_set(0); //不顯示游標
noecho(); //禁止輸入的字元出現在螢幕上
keypad(stdscr, TRUE); //因為缺少這行一直出錯
mousemask(BUTTON1_RELEASED,0);//啟用滑鼠事件左鍵釋放,使得getch()能獲取滑鼠事件
MEVENT event; //建立事件變數
核心
while(1){ //這個迴圈使遊戲可以玩很多局
new_mine(MINENUM); //新建雷區
display(); //顯示雷區(剛開始全是不可見的)
while(1){ //這個迴圈使遊戲的操作可以持續
switch (getch()){ //獲取操作
case KEY_MOUSE: //如果是滑鼠事件,進行遊戲操作
win=operate(event);//如果踩雷operate()會返回-2
break;
case 'q': win=-2; //如果輸入的是字元'q'則退出本局遊戲
}
display();
if(win==-2){ //輸掉遊戲(包括中途退出)
printw("You lose!"); break;
}
if(check_win()){ //檢查是否贏得遊戲
printw("You win!"); break;
}
}
if(getch()=='q') break; //如果再次輸入字元'q'則退出遊戲
}
endwin(); //退出curses模式
4.功能函式
生成雷區new_mine()
int add_mine(int r,int l){ //用於累加雷區的數字
if(r>=0&&r<row&&l>=0&&l<line&&a[r][l]!=-1)//排除在界外的情況,而且雷上面不用進行處理
a[r][l]++;
}
int new_mine(int num){
int n=0,r=0,l=0;
win=0; //千萬不要忘記初始化,下一局開始時win要再次初始化為0
for(r=0;r<row;r++){
for(l=0;l<line;l++){
a[r][l]=0; //雷區的狀態也要初始化
f[r][l]=0; //雷區的探索情況也要初始化
}
} //生成雷
srand(clock()); //用clock()生成隨機種子
while(n<num){
r=rand()%row; //用隨機數獲取行數
l=rand()%line; //用隨機數獲取列數
if(a[r][l]==0){ //確保即使有重複位置的雷也能生成所需的數量的雷
a[r][l]=-1; //放置雷
n++;
}
}
for(r=0;r<row;r++) //佈置雷區數字
for(l=0;l<line;l++)
if(a[r][l]==-1){//在雷的周圍累加數字
add_mine(r-1,l-1);
add_mine(r-1,l);
add_mine(r-1,l+1);
add_mine(r,l-1);
add_mine(r,l+1);
add_mine(r+1,l-1);
add_mine(r+1,l);
add_mine(r+1,l+1);
}
}
遊戲主要操作operate()
int show_mine(int r,int l){ //用於顯示雷區的狀態
if(r>=0&&r<row&&l>=0&&l<line&&a[r][l]!=-1)//排除在界外的情況,而且雷不用顯示
f[r][l]=1;
}
int operate(MEVENT mouse){ //遊戲的主要操作
static int r=0,l=0;
getmouse(&mouse); //翻譯獲取的滑鼠事件
mouse_trafo(&mouse.y,&mouse.x,1); //將獲取的滑鼠的座標轉換為對應的螢幕座標
if (!wenclose(stdscr,mouse.y, mouse.x))
return -1; //如果座標不在螢幕內,直接返回
if(mouse.bstate==BUTTON1_RELEASED){ //當滑鼠事件為左鍵釋放時
l=mouse.x/3; //將滑鼠座標轉化為對應的雷區座標
r=mouse.y/2;
if(a[r][l]==-1){ //該座標上有雷,踩到雷了
for(int i=0;i<=row;i++)
for(int j=0;j<=line;j++)
f[i][j]=1; //全部雷區的狀態都設為可見
return -2; //返回-2
}
show_mine(r,l); //沒踩到雷,就設定該座標的雷區狀態為可見
if(a[r][l]==0){ //如果該座標周圍沒有雷,則設定周圍的雷區狀態為可見
show_mine(r-1,l-1);
show_mine(r-1,l);
show_mine(r-1,l+1);
show_mine(r,l-1);
show_mine(r,l+1);
show_mine(r+1,l-1);
show_mine(r+1,l);
show_mine(r+1,l+1);
}
}
}
顯示雷區影像display()
int display(){ //用於顯示雷區
int r=0,l=0;
clear(); //清屏
for(r=0;r<row;r++){ //遍歷整個雷區
for(l=0;l<line;l++){
if(f[r][l]==1) //如果該雷區座標狀態為可見
if(a[r][l]==-1) //如果該座標是雷,列印雷
mvaddch(r*2+1,l*3+1,'*');
else //不是雷就列印數字
mvaddch(r*2+1,l*3+1,'0'+a[r][l]);
}
}
//繪製網格,細節就不解釋了
for(r=0;r<row;r++){
for(l=0;l<line;l++){
mvaddch(r*2,l*3+1,'-');
mvaddch(r*2,l*3+2,'-');
mvaddch(r*2,l*3,'|');
mvaddch(r*2+1,l*3,'|');
mvaddch(row*2,l*3,'|');
mvaddch(row*2,l*3+1,'-');
mvaddch(row*2,l*3+2,'-');
}
mvaddch(r*2,line*3,'|');
mvaddch(r*2+1,line*3,'|');
}
mvaddch(row*2,line*3,'|');
refresh(); //將緩衝區的所有字元都列印到螢幕上
}
檢查贏check_win()
int check_win(void){ //看看遊戲有沒有贏
int count=0; //用於統計未探索的雷區的數量
for(int i=0;i<row;i++)
for(int j=0;j<line;j++)
count+=1-f[i][j]; //因為未探索是0,已探索是1,只有未探索才+1
return count==MINENUM; //剩下的雷區的數量就是雷的總數,說明雷全找出來了
}
三、效果展示
如果中途按q
退出,會判定為輸
我輸的時候
當然也有贏的時候
總結
通過這次用ncurses寫掃雷的嘗試,除了加深對c語言和ncurses庫的理解和熟練度,更讓我瞭解到思路的重要性。c語言和ncurses庫只是工具,如果思路不清晰明朗就很難完成目標,反之是總有辦法實現的。所以在敲程式碼之前,尤其是做複雜的任務的時候,一定要先做需求分析整理思路,將需要的資料和功能都剖析出來,這樣對程式碼的實現非常有利。養成這種良好的習慣對於提高效率和程式碼品質是十分有利的。
相關文章
- 無聊的週末用Java寫個掃雷小遊戲Java遊戲
- 初級掃雷
- JS實現掃雷JS
- 通過編寫掃雷遊戲提高你的 Bash 技巧遊戲
- 《魔窟掃雷》給掃雷遊戲指明瞭一個進化的方向遊戲
- win10有掃雷嗎?Win10系統掃雷遊戲在哪裡Win10遊戲
- 如何在Linux中安裝Ncurses庫Linux
- 掃雷--C語言實現C語言
- go語言實現掃雷Go
- 生成一個掃雷矩陣矩陣
- Python:遊戲:寫一個和 XP 上一模一樣的“掃雷”Python遊戲
- win10如何安裝掃雷遊戲_win10系統怎麼玩掃雷Win10遊戲
- C語言陣列應用例項2: 掃雷遊戲C語言陣列遊戲
- 掃雷小遊戲-網頁版遊戲網頁
- 經典掃雷遊戲Web版遊戲Web
- WPF 製作雷達掃描圖
- win10掃雷怎麼換主題 如何更換win10的掃雷主題Win10
- Android自定義View 雷達掃描效果AndroidView
- Linux核心配置 make menuconfig時出現缺失ncurses庫Linux
- 認識ncurses
- 編譯 ncurses編譯
- 安全測試之探索 windows 遊戲掃雷Windows遊戲
- python之掃雷小遊戲(附程式碼)Python遊戲
- win10沒有掃雷遊戲怎麼辦_win10自帶遊戲沒有掃雷如何解決Win10遊戲
- 當《掃雷》開始運用免費手遊的設計和運營思路
- 利用Python實現自動掃雷小指令碼Python指令碼
- 探秘掃雷遊戲的C語言實現遊戲C語言
- Python3+pygame實現Windows經典掃雷PythonGAMWindows
- (詳解)用C語言實現一個能夠連續展開的掃雷。C語言
- 體驗【應用交付掃雷大作戰】,得程式設計師專屬帆布袋程式設計師
- 厲害了,一個自動掃雷遊戲專案!遊戲
- 雷達氣象相關詞彙(一 掃描模式)模式
- 寫寫雷亞:誰說音遊講不好故事?
- 運用Npcap庫實現SYN半開放掃描PCA
- vb.net使用GDI+實現掃雷小遊戲遊戲
- 2019年了,這些年輕人還在玩掃雷
- Windows 95被做成了App,可玩掃雷和紙牌WindowsAPP
- Html5 Canvas 掃雷 (IE9測試透過)HTMLCanvasIE9