前言:不少剛剛接觸編程的人都不知道怎麼下手編寫程序,特別是學習了新的知識點,不知道有什麼用,那麼本文將以簡單的存儲結構及簡單的運算,條件語句,分支語句,循環語句結合,帶來一個雙人對戰版五子棋,這是一個簡單的模型,實現了五子棋最最基本的功能,還有好多地方須要補全,如邊界問題,設計問題,遊戲邏輯問題,但願讀者閱讀後可以注意,經過本身的努力來完善它,還能擴展各類功能,如悔棋,網絡對戰等,有時候寫程序和小生命同樣,慢慢會成長,而咱們做爲「父母」的看到本身的小寶寶成爲有用之才,過程之欣喜特別棒!下面正題! ios
需求分析:經過C++語言來實現一個以windows控制檯爲展現平臺的簡單版五子棋程序,其中經過鍵盤輸入來控制遊戲中的行爲(光標移動、落子、確認)。規則要求某一方在橫豎斜方向連續存在五個或五個以上本人所執棋子得到爲獲勝。算法
遊戲流程分析: 編程
當咱們要扒一個已存在的程序時(有的是五子棋的程序,能夠在互聯網裏找到不少),咱們能夠從他的UI入手,經過咱們所觀察到的,所感覺到,所使用到的服務,來對軟件進行分析,從而得到以上流程,但咱們一旦須要將需求變爲代碼時,咱們的設計就要考慮的更多了。windows
這樣咱們就須要一種能力--抽象數組
1.首先,咱們須要一個棋盤,那麼我可使用C++裏的什麼來存儲和表示棋盤呢?經過抽象,由於棋盤是個二維圖形,我推薦使用二維數組,假設咱們構建一個19行*19列的棋盤。 實現: int qiPan[19][19]; //聲明一個19行19列的數組來存儲棋盤 for(int h=0;h<19;h++) //對數組進行遍歷,全部元素進行初始化(賦值),默認爲0值 { for(int l=0;l<19;l++) { qiPan[h][l]=0; //對當前元素進行初始化(賦值),默認爲0值 } } for(int h=0;h<19;h++) //打印 { for(int l=0;l<19;l++) { switch(qiPan[h][l]) { case 0: //若是棋盤存儲的元素爲0時,咱們打印 · 樣式的字符 cout<<"·"; break; } } cout<<endl; } 運行以上代碼,咱們能夠獲得一個棋盤。 2.那麼擁有棋盤後,咱們須要擁有一個光標,來對落子位置進行定點,那麼我如何進行表示呢。咱們能夠在棋盤上找一個點,也就是在數組對應位置找一個元素,更改他的值,咱們用8來表示光標,而找到這個元素咱們須要知道其橫縱座標值,咱們用兩個int變量表示。 int X=9; //2.聲明並初始化光標的橫縱座標 int Y=9; qiPan[9][9]=8; //更改棋盤中光標所在元素的值爲8 打印時,咱們只要在switch 語句中添加一個case 選項 8便可: case 8: //若是棋盤存儲的元素爲0時,咱們打印 · 樣式的字符 cout<<"╋"; break; 得到光標後咱們如何移動他呢?那麼咱們能夠經過接受鍵盤輸入的字符來控制光標的移動,本例中使用 W上,S下,A左,D右 來移動光標。 char xx=getch(); //控制檯從鍵盤得到一個字符的函數(方法) switch(xx) //控制 { case 'w': //上 Y=Y-1; //使光標縱座標-1 qiPan[Y][X]=8; //將光標寫入棋盤 qiPan[Y+1][X]=0; //使本來位置的值還原 break; case 's': //下 Y=Y+1; qiPan[Y][X]=8; qiPan[Y-1][X]=0; break; case 'a': //左 X=X-1; qiPan[Y][X]=8; qiPan[Y][X+1]=0; break; case 'd': //右 X=X+1; qiPan[Y][X]=8; qiPan[Y][X-1]=0; break; }
3.這時,咱們能夠控制光標的移動了,接下來要實現落子操做,棋子又怎麼表示呢?網絡
咱們可使用兩個int類型的值來表示:白子- 1,黑子- 2,那麼咱們只要在棋盤中更改光標所在位置元素的值爲1或2就能夠了,那麼咱們這麼作可行嗎?函數
咱們回顧一下光標移動的代碼,咱們會發現,光標的移動會影響元素的變化,那麼咱們若是在棋盤中進行落子後,咱們光標再次移動有可能會改變已記錄的落子信息,爲了使光標與棋子不衝突,咱們使用兩個圖層,表示兩個相同的棋盤。學習
那麼我就須要再聲明一個棋盤,方法和1中同樣:spa
int qiPanTwo[19][19]; //聲明一個19行19列的數組來存儲棋盤 for(int h=0;h<19;h++) //對數組進行遍歷,全部元素進行初始化(賦值),默認爲0值 { for(int l=0;l<19;l++) { qiPanTwo[h][l]=0; //對當前元素進行初始化(賦值),默認爲0值 } } 好,棋盤2已經創建好了,那麼咱們如何落子?咱們必定要選擇執棋方後,在光標位置經過接收鍵盤輸入的j落子,那麼咱們只須要在2.中switch語句中添加一個分支 case ’j’:便可,而且咱們須要使用一個變量來表示玩家,咱們能夠在程序一開始定義: int player=1;//設定玩家並進行初始化賦值 case 'j': //落子 if(player==1) //若是當前玩家爲白色方時 { qiPanTwo[Y][X]=1; //經過棋盤1中的光標位置更改棋盤2 //中對應元素的值爲1,也就是白棋落子 player=2; //白棋落子後更換玩家 } else if(player==2) { qiPanTwo[Y][X]=2; player=1; } break; 落子成功,接下來咱們能夠把它展現出來,因爲此時咱們要對兩個棋盤進行統一的打印,那麼咱們使用swicth就不能進行統一的分支選擇了,此時咱們須要將1.中的打印內容改成: if(qiPan[h][l]==8) //因爲光標所在圖層應該在棋子圖層之上,因此優先考慮。 { cout<<"╋"; } else if(qiPanTwo[h][l]==0) { cout<<"·"; } else if(qiPanTwo[h][l]==1) { cout<<"●"; } else if(qiPanTwo[h][l]==2) { cout<<"○"; } 4.遊戲規則,咱們落子以後要進行一個判斷,如何判斷是否勝利呢? 此時,咱們就要使用遊戲規則來進行算法的分析,當落子位橫、縱、斜5格內存在相互鏈接的五個同類棋子時,咱們可認爲執該棋者獲勝,因此咱們須要在各個方向進行判斷。 int shu=1,heng=1,pie=1,na=1;//橫豎撇捺計數器,累計到5則表示某方向出現五個相同的旗子 for(int i=1;i<=4;i++) //上 { if(qiPanTwo[Y+i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) shu++; else break; } for(int i=1;i<=4;i++) //下 { if(qiPanTwo[Y-i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) shu++; else break; } for(int i=1;i<=4;i++) //左 { if(qiPanTwo[Y][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) heng++; else break; } for(int i=1;i<=4;i++) //右 { if(qiPanTwo[Y][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) heng++; else break; } for(int i=1;i<=4;i++) //左下 { if(qiPanTwo[Y+i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) pie++; else break; } for(int i=1;i<=4;i++) //右上 { if(qiPanTwo[Y-i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) pie++; else break; } for(int i=1;i<=4;i++) //右下 { if(qiPanTwo[Y+i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) na++; else break; } for(int i=1;i<=4;i++) //左上 { if(qiPanTwo[Y-i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) na++; else break; } if(shu==5||heng==5||pie==5||na==5) { if(qiPanTwo[Y][X]==1) { cout<<"白子獲勝!"; system("pause"); break; } else { cout<<"黑子獲勝!"; system("pause"); break; } } shu=1,heng=1,pie=1,na=1; 好 當完成這一步時,咱們的程序基本就搞定了,剩下就是按照一開始的流程進行拼接了,其中咱們在打印屏幕以前,要對上一次打印的結果進行擦除,使用函數 system(「cls」);//擦除控制檯中全部已顯示的字符 就能夠完成了。
完整代碼(可運行):設計
#include<iostream> #include<string> #include<windows.h> #include<conio.h> using namespace std; int main() { int player=1; //定義一個玩家,當1時爲白方,2時爲黑方 //................................棋盤1.............................................. int qiPan[19][19]; //1.聲明一個19行19列的數組來存儲棋盤 1 for(int h=0;h<19;h++) //對數組進行遍歷,全部元素進行初始化(賦值),默認爲0值 { for(int l=0;l<19;l++) { qiPan[h][l]=0; //對當前元素進行初始化(賦值),默認爲0值 } } //...............................棋盤2................................................ int qiPanTwo[19][19]; //聲明一個19行19列的數組來存儲棋盤 2 for(int h=0;h<19;h++) //對數組進行遍歷,全部元素進行初始化(賦值),默認爲0值 { for(int l=0;l<19;l++) { qiPanTwo[h][l]=0; //對當前元素進行初始化(賦值),默認爲0值 } } //...............................光標聲明............................................. int X=9; //2.聲明並初始化光標的橫縱座標 int Y=9; qiPan[9][9]=8; //..............................顯示................................................... for(int h=0;h<19;h++) { for(int l=0;l<19;l++) { if(qiPan[h][l]==8) { cout<<"╋"; } else if(qiPanTwo[h][l]==0) { cout<<"·"; } else if(qiPanTwo[h][l]==1) { cout<<"●"; } else if(qiPanTwo[h][l]==2) { cout<<"○"; } } cout<<endl; } //..............................輸入控制............................................... while(true) { char xx=getch(); //控制檯從鍵盤得到一個字符 switch(xx) //控制 { case 'w': //上 Y=Y-1; //使光標縱座標-1 qiPan[Y][X]=8; //講光標寫入棋盤 qiPan[Y+1][X]=0; //使本來位置的值還原 break; case 's': //下 Y=Y+1; qiPan[Y][X]=8; qiPan[Y-1][X]=0; break; case 'a': //左 X=X-1; qiPan[Y][X]=8; qiPan[Y][X+1]=0; break; case 'd': //右 X=X+1; qiPan[Y][X]=8; qiPan[Y][X-1]=0; break; case 'j': //落子 if(player==1) //若是當前玩家爲白色方時 { qiPanTwo[Y][X]=1; //經過棋盤1中的光標位置更改棋盤2中對應元素的值爲1,也就是白棋落子 player=2; //白棋落子後更換玩家 } else if(player==2) { qiPanTwo[Y][X]=2; player=1; } break; } //................................清屏操做................................................ system("cls"); //...............................打印..................................................... for(int h=0;h<19;h++) { for(int l=0;l<19;l++) { if(qiPan[h][l]==8) { cout<<"╋"; } else if(qiPanTwo[h][l]==0) { cout<<"·"; } else if(qiPanTwo[h][l]==1) { cout<<"●"; } else if(qiPanTwo[h][l]==2) { cout<<"○"; } } cout<<endl; } //.........................遊戲規則.............................................. int shu=1,heng=1,pie=1,na=1;//橫豎撇捺 for(int i=1;i<=4;i++) //上 { if(qiPanTwo[Y+i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) shu++; else break; } for(int i=1;i<=4;i++) //下 { if(qiPanTwo[Y-i][X]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) shu++; else break; } for(int i=1;i<=4;i++) //左 { if(qiPanTwo[Y][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) heng++; else break; } for(int i=1;i<=4;i++) //右 { if(qiPanTwo[Y][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) heng++; else break; } for(int i=1;i<=4;i++) //左下 { if(qiPanTwo[Y+i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) pie++; else break; } for(int i=1;i<=4;i++) //右上 { if(qiPanTwo[Y-i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) pie++; else break; } for(int i=1;i<=4;i++) //右下 { if(qiPanTwo[Y+i][X+i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) na++; else break; } for(int i=1;i<=4;i++) //左上 { if(qiPanTwo[Y-i][X-i]==qiPanTwo[Y][X]&&qiPanTwo[Y][X]!=0) na++; else break; } if(shu==5||heng==5||pie==5||na==5) { if(qiPanTwo[Y][X]==1) { cout<<"白子獲勝!"; system("pause"); break; } else { cout<<"黑子獲勝!"; system("pause"); break; } } } return 0; }
2017-02-01 20:13:59