亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

使用C++一步步實現俄羅斯方塊后續

2020-05-23 13:31:43
字體:
來源:轉載
供稿:網友

一、實驗簡介

1.1 實驗內容

本節實驗我們將實現俄羅斯方塊主要函數的設計,完成基本功能并運行。

1.2 實驗知識點

窗口的繪制
方塊類的設計
旋轉算法
移動、消除函數

1.3 實驗環境

xface 終端
g++ 編譯器
ncurses 庫

1.4 編譯程序

編譯命令要加上 -l 選項引入 ncurses 庫:

g++ main.c -l ncurses

1.5 運行程序

./a.out

1.6 運行結果

C++,俄羅斯方塊,C++俄羅斯方塊,C++制作俄羅斯方塊

二、實驗步驟

2.1 頭文件

首先包含頭文件以及定義一個交換函數和隨機數函數,后面用到(交換函數用來做方塊的旋轉,隨機數用來設置方塊的形狀)

#include <iostream>#include <sys/time.h>#include <sys/types.h>#include <stdlib.h>#include <ncurses.h>#include <unistd.h>/* 交換a和b */void swap(int &a, int &b){ int t=a; a = b; b = t;}/* 得到一個(min,max)區間的隨機整數int getrand(int min, int max){ return(min+rand()%(max-min+1));}

2.2 定義類

由于程序內容相對簡單,這里只定義了一個 Piece 類

class Piece { public:  int score;  //得分  int shape;  //表示當前方塊的形狀  int next_shape;  //表示下一個方塊的形狀  int head_x;  //當前方塊首個box的位置,標記位置  int head_y;  int size_h;  //當前方塊的size  int size_w;  int next_size_h;  //下一個方塊的size  int next_size_w;  int box_shape[4][4]; //當前方塊的shpe數組 4x4  int next_box_shape[4][4];  //下一個方塊的shpe數組 4x4  int box_map[30][45];  //用來標記游戲框內的每個box  bool game_over;  //游戲結束的標志 public:  void initial();  //初始化函數  void set_shape(int &cshape, int box_shape[][4],int &size_w, int & size_h);  //設置方塊形狀  void score_next();  //顯示下一個方塊的形狀以及分數  void judge();  //判斷是否層滿  void move(); //移動函數 通過 ← → ↓ 控制  void rotate(); //旋轉函數  bool isaggin(); //判斷下一次行動是否會越界或者重合  bool exsqr(int row); //判斷當前行是否空 };

2.3 設置方塊形狀

這里通過 case 語句定義了7種方塊的形狀,在每次下一個方塊掉落之前都要調用以設置好它的形狀以及初始位置

void Piece::set_shape(int &cshape, int shape[][4],int &size_w,int &size_h){ /*首先將用來表示的4x4數組初始化為0*/ int i,j; for(i=0;i<4;i++)  for(j=0;j<4;j++)   shape[i][j]=0; /*設置7種初始形狀并設置它們的size*/ switch(cshape) {  case 0:    size_h=1;   size_w=4;    shape[0][0]=1;   shape[0][1]=1;   shape[0][2]=1;   shape[0][3]=1;   break;  case 1:   size_h=2;   size_w=3;   shape[0][0]=1;   shape[1][0]=1;   shape[1][1]=1;   shape[1][2]=1;   break;  case 2:   size_h=2;   size_w=3;    shape[0][2]=1;   shape[1][0]=1;   shape[1][1]=1;   shape[1][2]=1;   break;  case 3:   size_h=2;   size_w=3;   shape[0][1]=1;   shape[0][2]=1;   shape[1][0]=1;   shape[1][1]=1;   break;  case 4:   size_h=2;   size_w=3;   shape[0][0]=1;   shape[0][1]=1;   shape[1][1]=1;   shape[1][2]=1;   break;  case 5:    size_h=2;   size_w=2;   shape[0][0]=1;   shape[0][1]=1;   shape[1][0]=1;   shape[1][1]=1;   break;  case 6:    size_h=2;   size_w=3;   shape[0][1]=1;   shape[1][0]=1;   shape[1][1]=1;   shape[1][2]=1;   break; } //設置完形狀以后初始化方塊的起始位置 head_x=game_win_width/2; head_y=1; //如果剛初始化就重合了,游戲結束~ if(isaggin()) /* GAME OVER ! */  game_over=true;}

2.4 旋轉函數

這里用了一個比較簡單的算法對方塊進行旋轉,類似于矩陣的旋轉,先將 shape 數組進行斜對角線對稱化,再進行左右對稱,便完成了旋轉,需要注意的是要判斷旋轉后方塊是否出界或重合,如果是,則取消本次旋轉。

void Piece::rotate() {  int temp[4][4]={0}; //臨時變量  int temp_piece[4][4]={0}; //備份用的數組  int i,j,tmp_size_h,tmp_size_w;  tmp_size_w=size_w;  tmp_size_h=size_h;  for(int i=0; i<4;i++)   for(int j=0;j<4;j++)    temp_piece[i][j]=box_shape[i][j]; //備份一下當前的方塊,如果旋轉失敗則返回到當前的形狀  for(i=0;i<4;i++)   for(j=0;j<4;j++)    temp[j][i]=box_shape[i][j]; //斜對角線對稱  i=size_h;  size_h=size_w;  size_w=i;  for(i=0;i<size_h;i++)   for(j=0;j<size_w;j++)    box_shape[i][size_w-1-j]=temp[i][j]; //左右對稱  /*如果旋轉以后重合,則返回到備份的數組形狀*/  if(isaggin()){   for(int i=0; i<4;i++)    for(int j=0;j<4;j++)     box_shape[i][j]=temp_piece[i][j];   size_w=tmp_size_w; //記得size也要變回原來的size   size_h=tmp_size_h;  }  /*如果旋轉成功,那么在屏幕上進行顯示*/  else{   for(int i=0; i<4;i++)    for(int j=0;j<4;j++){     if(temp_piece[i][j]==1){      mvwaddch(game_win,head_y+i,head_x+j,' '); //移動到game_win窗口的某個坐標處打印字符      wrefresh(game_win);     }    }   for(int i=0; i<size_h;i++)    for(int j=0;j<size_w;j++){     if(this->box_shape[i][j]==1){      mvwaddch(game_win,head_y+i,head_x+j,'#');      wrefresh(game_win);     }   }  }}

2.5 移動函數

如果玩家沒有按下任何按鍵,方塊需要慢速下落,所以我們不能夠因為等待按鍵輸入而阻塞在 getch() ,這里用到了 select() 來取消阻塞。

/* 這里只是截取了程序的一部分,具體實現請參考源碼 */struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec= 500000;if (select(1, &set, NULL, NULL, &timeout) == 0)

timeout 就是我們最多等待按鍵的時間,這里設置了 500000us,超過這個時間就不再等待 getch() 的輸入,直接進行下一步。

如果在 timeout 時間內檢測到按鍵,則下面的 if 語句為真,得到輸入的 key 值,通過判斷不同的 key 值進行向左、右、下、旋轉等操作。

if (FD_ISSET(0, &set))
    while ((key = getch()) == -1) ;
向左、右、下移動的函數處理方式基本相同,這里只拿向下移動的函數進行說明

/* 這里只是截取了程序的一部分,具體實現請參考源碼 *//* 如果輸入的按鍵是 ↓ */if(key==KEY_DOWN){  head_y++; //方塊的y坐標+1  if(isaggin()){ //如果重合或出界,則取消這次移動   head_y--;   /*既然停下來了,那么把地圖上對應的box設置為已被占用,用1表示,0表示未被占用   for(int i=0;i<size_h;i++)    for(int j=0;j<size_w;j++)     if(box_shape[i][j]==1)      box_map[head_y+i][head_x+j]=1;   score_next(); //顯示分數以及提示下一個方塊  }  /*如果能夠向下移動,那么取消當前方塊的顯示,向下移動一行進行顯示,這里注意for循環的行要從下往上  else{   for(int i=size_h-1; i>=0;i--)    for(int j=0;j<size_w;j++){     if(this->box_shape[i][j]==1){      mvwaddch(game_win,head_y-1+i,head_x+j,' ');      mvwaddch(game_win,head_y+i,head_x+j,'#');     }    }   wrefresh(game_win);}

2.6 重復函數

每次移動或旋轉之后要進行判斷的函數,函數返回真則不能行動,返回假則可以進行下一步。

bool Piece::isaggin(){ for(int i=0;i<size_h;i++)  for(int j=0;j<size_w;j++){   if(box_shape[i][j]==1){    if(head_y+i > game_win_height-2) //下面出界     return true;    if(head_x+j > game_win_width-2 || head_x+i-1<0) //左右出界     return true;    if(box_map[head_y+i][head_x+j]==1) //與已占用的box重合     return true ;   }  } return false;}

2.7 層滿函數

最后一個很重要的功能是對方塊已滿的行進行消除,每當一個方塊向下移動停止后都需要進行判斷。

void Piece::judge(){ int i,j; int line=0; //用來記錄層滿的行數 bool full; for(i=1;i<game_win_height-1;i++){ //除去邊界  full=true;  for(j=1;j<game_win_width-1;j++){   if(box_map[i][j]==0) //存在未被占用的box    full=false; //說明本層未滿  }  if(full){ //如果該層滿   line++; //行滿+1   score+=50; //加分~   for(j=1;j<game_win_width-1;j++)    box_map[i][j]=0; //把該層清空(標記為未被占用)  } } /*上面判斷完后 看line的值,如果非 0 說明有層已滿需要進行消除*/ if(line!=0){ for(i=game_win_height-2;i>=2;i--){  int s=i;  if(exsqr(i)==0){   while(s>1 && exsqr(--s)==0); //查找存在方塊的行,將其下移   for(j=1;j<game_win_width-1;j++){    box_map[i][j]=box_map[s][j]; //上層下移    box_map[s][j]=0; //上層清空   }  } } /*清空和移動標記完成以后就要屏幕刷新了,重新打印game_win*/ for(int i=1;i<game_win_height-1;i++)   for(int j=1;j<game_win_width-1;j++){    if(box_map[i][j]==1){     mvwaddch(game_win,i,j,'#');     wrefresh(game_win);    }    else{     mvwaddch(game_win,i,j,' ');     wrefresh(game_win);    }   } }}

三、實驗總結

到這里幾個關鍵函數的介紹也就完成了,搞明白這些函數的功能并實現,再參考源碼補全其他函數以及main函數就可以運行啦!當然俄羅斯方塊的實現方法還有很多,每個人的思路和方法可能會不一樣,或許你寫出來的俄羅斯方塊更簡潔、更流暢! Enjoy it ?。海?/p>

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美夫妻性生活视频| 日韩第一页在线| 亚洲激情视频在线播放| 精品国产一区二区三区久久狼黑人| 精品无人区乱码1区2区3区在线| 国产精品成人观看视频国产奇米| 亚洲丝袜在线视频| 精品久久久久久久大神国产| 国产精品亚洲综合天堂夜夜| 国语自产精品视频在线看一大j8| 日韩av影视综合网| 91av在线视频观看| 国产精品久久久久久久久影视| 中文字幕日韩av电影| 欧美www在线| 国产亚洲精品成人av久久ww| 亚洲国产精品字幕| 91精品久久久久久久久久入口| 日韩av资源在线播放| 欧美性生交大片免网| 日韩精品中文字幕在线观看| 亚洲综合视频1区| 日韩精品中文字幕在线播放| 国产精品成人一区二区三区吃奶| 成人精品视频久久久久| 欧美激情小视频| 久久99亚洲热视| 久久精品亚洲一区| 日韩有码在线播放| 欧美有码在线观看| 亚洲综合精品一区二区| 欧美成年人网站| 日韩成人av网| 精品国产乱码久久久久酒店| 精品国产欧美一区二区三区成人| 日韩在线欧美在线国产在线| 欧美又大又粗又长| 国产欧美日韩91| 中文字幕日韩高清| 久久久久久久色| 中文字幕欧美日韩在线| 欧美激情xxxx性bbbb| 亚洲天天在线日亚洲洲精| 亚洲人成伊人成综合网久久久| 欧美视频一区二区三区…| 欧美日韩国产丝袜美女| 久久视频在线看| 日韩视频中文字幕| 久久久久99精品久久久久| 日日噜噜噜夜夜爽亚洲精品| 国产视频精品一区二区三区| 国产精品青草久久久久福利99| 亚洲视频电影图片偷拍一区| 亚洲精品在线视频| 91国自产精品中文字幕亚洲| 国产精品久久久久久久9999| 亚洲精品国产成人| 精品女同一区二区三区在线播放| 欧美壮男野外gaytube| 亚洲xxxx视频| 亚洲欧美精品suv| 国产一区二区三区网站| 热99精品里视频精品| 国产欧美va欧美va香蕉在| 成人免费视频网| 中文字幕亚洲一区在线观看| 热99在线视频| 国内免费久久久久久久久久久| 高清亚洲成在人网站天堂| 亚洲精品福利在线| 久久精品电影网| 亚洲欧洲在线免费| 成人免费直播live| 成人国产精品一区二区| 久久人人97超碰精品888| 久久久久北条麻妃免费看| 亚洲国产91色在线| 91精品国产综合久久香蕉922| 91九色在线视频| 欧美男插女视频| 91沈先生作品| 欧美黑人巨大精品一区二区| 国产不卡精品视男人的天堂| 国内精品久久久久伊人av| 在线电影欧美日韩一区二区私密| 清纯唯美亚洲激情| 91中文精品字幕在线视频| 国产精品久久久久7777婷婷| 午夜欧美大片免费观看| 国产日韩欧美夫妻视频在线观看| 欧美日韩成人精品| 欧美激情a∨在线视频播放| 欧美夫妻性生活xx| 欧美激情18p| 欧美日韩国产一区二区| 亚洲情综合五月天| 97精品一区二区视频在线观看| 亚洲综合色av| 5566日本婷婷色中文字幕97| 日韩在线视频免费观看| 久久久噜噜噜久噜久久| 精品久久香蕉国产线看观看gif| 欧美日韩国产中字| 欧美精品videossex88| 国产精品亚洲激情| 91久久在线播放| 国产一区二区三区在线| 97久久精品国产| 色多多国产成人永久免费网站| 亚洲精品国产suv| 91麻豆国产精品| 国产亚洲视频在线| 久久视频国产精品免费视频在线| 日韩中文理论片| 亚洲综合中文字幕在线| 国外成人在线直播| 亚洲石原莉奈一区二区在线观看| 日韩高清电影免费观看完整版| 狠狠躁夜夜躁人人躁婷婷91| 欧美日韩免费一区| 91精品国产成人| 亚洲一区美女视频在线观看免费| 欧美精品18videosex性欧美| 超碰日本道色综合久久综合| 欧美日韩国产页| 国产精欧美一区二区三区| 欧洲永久精品大片ww免费漫画| 国产欧美日韩免费| 久久国产精品99国产精| 日韩一区视频在线| 国产视频丨精品|在线观看| 精品久久久久久久大神国产| 日韩中文字幕不卡视频| 亚洲第一av在线| 欧美成人中文字幕在线| 91精品啪aⅴ在线观看国产| 国产精品r级在线| 精品亚洲一区二区三区四区五区| 最近2019中文字幕大全第二页| 亚洲高清一区二| 亚洲一级片在线看| 亚洲欧美制服综合另类| 亚洲欧美日韩成人| 亚洲精品网站在线播放gif| 国产精品毛片a∨一区二区三区|国| 色综合天天综合网国产成人网| 欧美激情第6页| 欧美日韩电影在线观看| 国产精品视频公开费视频| 最新日韩中文字幕| 亚洲国产精品久久91精品| 成人性生交大片免费看小说| 最近2019年中文视频免费在线观看| 91美女福利视频高清| 国产免费一区二区三区在线能观看| 日韩精品在线观看视频| 亚洲欧美日韩网| 2019日本中文字幕| 国产精品夫妻激情| 亚洲精品免费在线视频| 久久精品在线视频| 久久久精品一区二区三区| 亚洲成色www8888| 亚洲综合中文字幕在线|