C語言介面實現2048小遊戲
這是我在大一第二學期(兩年前)為了參加比賽,自學後寫的一個Dome,拿出來和大家分享一下,程式碼為兩年前的程式碼,未改動,優化以及各式可能很一般,請見諒。
#include "stdio.h" #include "stdlib.h" #include "time.h" #define N 4//方陣邊長 #define WIN 2048//遊戲獲勝目標 void output(int (*a)[N]){//輸出4*4表格, int i,j; printf("\n"); printf("┏━━━━┳━━━━┳━━━━┳━━━━┓");//頂邊框 printf("\n"); for(i=0;i<N;i++){printf("┃") ; for(j=0;j<N;j++){ if(a[i][j]==0) printf(" ┃");//如果數值為零則輸出空白 else printf("%4d┃",a[i][j]); } if(i!=3) printf("\n┣━━━━╋━━━━╋━━━━╋━━━━┫\n");//層邊框 else printf("\n┗━━━━┻━━━━┻━━━━┻━━━━┛\n");//底邊框 } } int sj24(){//獲取隨機數2或4 int s[8]={2,2,2,2,2,2,2,4},i,j;//以概率7:1建立2和4的隨機數種子 srand((unsigned)time(NULL)); i=(rand())%8;//以時間為種子得到0~7的隨機數 return s[i]; } int input(){//輸入上下左右指令控制遊戲 int m; if(getch()==0xE0){ //對鍵入的命令進行識別 switch(getch()){//十位1表示水平移動2表示豎直移動,各位1表示向小座標移動2表示向大座標移動 case 72: return 21;break;//輸入上 case 80: return 22;break;//輸入下 case 75: return 11;break;//輸入右 case 77: return 12;break;//輸入左 default:{//若命令不符合要求,運用遞迴重新得到命令 printf("請輸入正確的指令!(~ ̄(OO) ̄)ブ\n"); return input(); } } } else {//若命令不符合要求,運用遞迴重新得到命令 printf("請輸入正確的指令!(~ ̄(OO) ̄)ブ\n\n"); return input(); } } void move(int (*a)[N]){ //通過呼叫input函式得到正確的命令,根據命令移動資料 int x,i,j,k,s[N][N],t=0; x=input(); for(i=0;i<N;i++){ for(j=0;j<N;j++) s[i][j]=a[i][j];//拷貝移動前方陣方便以後檢查 } if(x/10==1){//水平移動 if(x%10==1){//向小座標移動 for(i=0;i<N;i++){for(k=0;k<3;k++){// 核心演算法介紹 for(j=N-1;j>0;j--){ //第一步,先將一排資料重後往前一個個向前推(除去前面和中間的0) if(a[i][j-1]==0) { //為確保移動完全經推理最多3次完成所有移動所有執行3次該演算法 a[i][j-1]=a[i][j]; //第二步,將相鄰兩兩相同的數相加賦值前者後者賦0 a[i][j]=0; // 第三部,重複第一步操作去除新產生的0,總操作完成 } //PS:所有方向演算法原理相同 } } for(j=0;j<N-1;j++){ if(a[i][j]==a[i][j+1]) { a[i][j]=a[i][j]+a[i][j+1]; a[i][j+1]=0; } } for(k=0;k<3;k++){ for(j=N-1;j>0;j--){ if(a[i][j-1]==0) { a[i][j-1]=a[i][j]; a[i][j]=0; } } } } } else{//向大座標移動 for(i=0;i<N;i++){for(k=0;k<3;k++){ for(j=0;j<N-1;j++){ if(a[i][j+1]==0) { a[i][j+1]=a[i][j]; a[i][j]=0; } } } for(j=N-1;j>0;j--){ if(a[i][j]==a[i][j-1]) { a[i][j]=a[i][j]+a[i][j-1]; a[i][j-1]=0; } } for(k=0;k<3;k++){ for(j=0;j<N-1;j++){ if(a[i][j+1]==0) { a[i][j+1]=a[i][j]; a[i][j]=0; } } } } } } else{//豎直移動 if(x%10==1){//向小座標移動 for(i=0;i<N;i++){for(k=0;k<3;k++){ for(j=N-1;j>0;j--){ if(a[j-1][i]==0) { a[j-1][i]=a[j][i]; a[j][i]=0; } } } for(j=0;j<N-1;j++){ if(a[j][i]==a[j+1][i]) { a[j][i]=a[j][i]+a[j+1][i]; a[j+1][i]=0; } } for(k=0;k<3;k++){ for(j=N-1;j>0;j--){ if(a[j-1][i]==0) { a[j-1][i]=a[j][i]; a[j][i]=0; } } } } } else{//向大座標移動 for(i=0;i<N;i++){for(k=0;k<3;k++){ for(j=0;j<N-1;j++){ if(a[j+1][i]==0) { a[j+1][i]=a[j][i]; a[j][i]=0; } } } for(j=N-1;j>0;j--){ if(a[j][i]==a[j-1][i]) { a[j][i]=a[j][i]+a[j-1][i]; a[j-1][i]=0; } } for(k=0;k<3;k++){ for(j=0;j<N-1;j++){ if(a[j+1][i]==0) { a[j+1][i]=a[j][i]; a[j][i]=0; } } } } } } for(i=0;i<N;i++){//檢查是否為有效移動 for(j=0;j<N;j++) { if (s[i][j]!=a[i][j]) t=1; } } if(t){ begin(a); Sleep(60);//為讓玩家知道移動後隨機數出現位置,讓其延遲出現 get(a); begin(a); } else printf("選擇其他方向試試(¬_¬)"); } void get(int (*a)[N]){//在4*4表格中空板位置隨機獲得數字 int i,j; srand((unsigned)time(NULL)); do{ i=(rand())%4; j=(rand())%4; } while(a[i][j]!=0); a[i][j]=sj24(); } void begin(int (*a)[N]){//清屏並列印開頭 system("cls"); printf(" 小遊戲2048\n\n "); printf(" 鍵入上下左右控制\n"); output(a); } int test(int (*a)[N]){//判斷是否遊戲完成 int i,j,k=0,m=0,n=0; printf("\n"); for(i=0;i<N;i++){ for(j=0;j<N;j++){ if(a[i][j]==0)m=1;//檢查方陣中是否有0 if(a[i][j]==WIN)k=1; //檢查方陣中是否有目標數字 } } if (k){//如果發現目標數字判定遊戲獲勝 printf("YOU WIN! \(^o^)/YES!"); return 0; } else{ if(!m){//如果方陣中無0且無相鄰數字相等則判定遊戲失敗,反之遊戲繼續 for(i=0;i<N;i++){ for(j=0;j<N-1;j++) if(a[i][j]==a[i][j+1]||a[j][i]==a[j+1][i]) n=1; } if(n) return 1; else{ printf("GAME OVER!〒▽〒"); return 0; } } else return 1; } } void main(){ int a[N][N]={0}; get(a);get(a);begin(a);//起始時方陣有兩個隨機數 while(test(a)) move(a); //只有通過tset函式檢查才能繼續遊戲 } //謝謝
原說明文件:
作品名:小遊戲2048
使用語言:C語言
使用編譯器:DEV-C++
遊戲說明:《2048》是一款比較流行的數字遊戲,最早於2014年3月20日發行。原版2048首先在GitHub上釋出,原作者是Gabriele Cirulli,後被移植到各個平臺。這款遊戲的玩法很簡單,每次可以選擇上下左右滑動,每滑動一次,所有的數字方塊都會往滑動的方向靠攏,系統也會在空白的地方亂數出現一個數字方塊(2或4),相同數字的方塊在靠攏、相撞時會相加。不斷的疊加最終拼湊出2048
程式設計思路:
在程式編寫之前我只知道遊戲的規則和對遊戲把玩的經驗。後來對遊戲原理進行思考,大體的得到了程式編寫的方向。
首先我需要一個4*4的表格來填放數字,可用二維陣列來表達,用一個4*4的二維陣列,初值設定為0。
開始在4*4的表格中隨機出現兩個2或4的隨機數,為保證遊戲難度正常出現2的概率應大於出現4的概率(P2:P4=7:1),然後鍵入一次方向鍵後進行相應移動、合併。完成移動後在表格中空白位置出現一個2或4的隨機數。
遊戲勝負判定:若數字“2048”出現則為獲勝並輸出“YOU WIM!”,若數字填滿方格且每個數字無相鄰相等(即不可移動)則為失敗並輸出“GAME OVER!”
核心演算法(移動合併):第一步,先將需要操作的一行資料的非零數字向需移動方向靠齊(去0)。第二步,將相鄰相等數字相加,靠近需移動的一個賦二者的和另一個賦0,若有連續三個數字相等,操作前兩個。若前兩個後兩個均可合併,可同時操作。第三步,重複第一步操作,去除第二步新產生的0。
演算法細節詳見原始檔程式碼及註釋。
程式完成截圖
: