C語言寫的2048小遊戲
阿新 • • 發佈:2018-12-15
基於"基於C_語言的2048演算法設計_顏冠鵬.pdf" 這一篇文獻提供的思路 在中國知網上能找到 就不貼具體內容了 [摘 要] 針對2048的遊戲規則,分析了該遊戲的演算法特點,對其相關的功能需求和演算法設計進行了簡單介紹,提出了一種 新的設計方案。解決了該設計在方陣資料結構、運動演算法和遊戲結束判斷方面的問題,並闡述了以佇列方式進行座標運算和操 作擴充套件的關鍵技術。軟體測試表明,該設計的方塊數值最大值受方陣階數和操作次數的限制,四階方陣的理論最大值為 65 536, 智力極高的人可達 16 384,而一般人僅能達到 2 048 左右。 [關鍵詞] 2048 演算法設計 資料結構 座標運算 佇列 中圖分類號:TP301.6 文獻標識碼:A 文章編號:1008- 1739(2014)24- 62- 5
主要是幾個小的函式 用兩個for迴圈列印地圖和遍歷地圖 把一個4*4的二維陣列改成一個一維陣列來簡化處理思路
學到的知識
switch函式每一個case都需要加break來結束判斷 for在c99標準下 初始化的迴圈變數和外界所有變數毫無關係 c99標準才有了布林型變數 儘量不要大迴圈套小迴圈 巢狀四層迴圈之後就暈了 下斷點都不好除錯 如果陣列越界訪問會返回0 隨機數函式必須撒種子 不然每次都是同一個值
// // main.c // 2048 // 表示 為了練習C語言 在這先寫著一個小遊戲吧 // “聽說以後上課要用?” // 除錯程式碼已註釋 目前遊戲所有功能均實現 // 唯一不足的是在蘋果系統環境無getch函式 // 且不會自行實現 在其他系統直接include <conio.h> // 把getchar改為getch即可暢玩2048 // Created by licsber on 2018/10/11. // Copyright © 2018 licsber. All rights reserved. // #include <stdio.h>//emmmm #include <stdbool.h> //c裡沒有布林型變數 c99標準才加的 #include <time.h>//用於產生隨機數 #include <stdlib.h> //#include <ncurses.h>//圖形介面庫 等後來更新printMap函式再引用 void gameStart(void);//遊戲開始 void randomAdd(void);//在空格隨機加2和4 其中2為十分之九概率 void printMap(void);//用printf列印地圖 void getDirection(void);//讀取鍵盤輸入 void moveUp(void);//上 void moveDown(void);//下 void moveLeft(void);//左 void moveRight(void);//右 void moveForward(void);//推進 void moveMerge(void);//合併 bool checkIfGameOver(void);//檢測遊戲是否over 即無空位同時相鄰陣列元素各不相等 void restart(void);//重新開始 void loop(void);//循環遊戲 //int countZero(void);//還有幾個是0 //int returnZero(int line); int score = 0;//當前得分 int map[4][4]={ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} };//這是地圖 用二維陣列實現 int tmp[4] = {0,0,0,0}; void gameStart(void){ printf("Welcome to play 2048 game! by licsber\n"); randomAdd(); printMap(); printf("[w][s][a][d]move [r]restart [q]quit\n"); } void randomAdd(void){ srand((unsigned int)time(NULL));//撒隨機數種子 //printf("%d",rand()); int i,j,time = 0;//行 列 迴圈次數(debug用) do{ i = rand() % 4; j = rand() % 4; time++; }while (map[i][j] != 0); if (rand() % 10 == 0 ) { map[i][j]=4; } else{ map[i][j]=2; } //printf("%d",time); //上面的程式碼在格子快滿之後也有機率迴圈N次都不停 //todo改進方案:先找到所有空格子 //下面的程式碼是有問題的 有機率無限迴圈 /* bool finish = 0;//本輪是否已放置方塊 for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (!map[i][j]) { if (rand() % 16 == 0 && finish == 0) { // 十分之一的概率放4 if (rand() % 10 == 0 ) { map[i][j]=4; } else{ map[i][j]=2; } finish = 1; } } } } if (finish == 0) { randomAdd(); } else{ return; } */ } void printMap(void){ for (int i = 0; i < 4; i++) { printf(" "); for (int j = 0; j < 4; j++) { printf("%4d ",map[i][j]); } printf("\n"); } return; } void getDirection(void){ tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; char in = getchar(); switch (in) { case 'w': moveUp(); break; case 's': moveDown(); break; case 'a': moveLeft(); break; case 'd': moveRight(); break; case 'r': restart(); break; case 'q': exit(0); break; default: getDirection(); break; } } void moveUp(void){ for (int line = 0; line < 4; line++) { for (int i = 0; i < 4; i++) { tmp[i] = map[i][line]; } moveMerge(); for (int i = 0; i < 4; i++) { map[i][line] = tmp[i]; } } } void moveDown(void){ for (int line = 0; line < 4; line++) { for (int i = 0; i < 4; i++) { tmp[3 - i] = map[i][line]; } moveMerge(); for (int i = 0; i < 4; i++) { map[i][line] = tmp[3 - i]; } } } void moveLeft(void){ for (int line = 0; line < 4; line++) { for (int i = 0; i < 4; i++) { tmp[i] = map[line][i]; } moveMerge(); for (int i = 0; i < 4; i++) { map[line][i] = tmp[i]; } } } void moveRight(void){ for (int line = 0; line < 4; line++) { for (int i = 3; i >= 0; i--) { tmp[3 - i] = map[line][i]; } moveMerge(); for (int i = 3; i >= 0; i--) { map[line][i] = tmp[3 - i]; } } } bool checkIfGameOver(void){ //先檢查格子是不是都滿了 for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (!map[i][j]) { //只要有空的格子 遊戲就沒結束 return false; } } } //格子滿了之後 for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { if (map[i][j] == map[i+1][j] || map[i][j] == map[i][j+1]) { //如果一個格子和它右邊或下邊相等 遊戲也沒結束 //這裡陣列如果越界訪問會返回0 所以不影響結果 return false; } } } return true; } void moveForward(void){ //i為0的話就把最先一個非零的j挪到i的位置 int j = 0; for (int i = 0; i < 4; i++) { j++; if (tmp[i] == 0) { for (; j < 4; j++) { if (tmp[j] != 0) { tmp[i] = tmp[j]; tmp[j] = 0; break; } } } } } void moveMerge(void){ //處理合並 每合併一次就推進一次 moveForward(); for (int i = 0; i < 3; i++) { if (tmp[i] == tmp[i + 1]) { tmp[i] *=2; tmp[i + 1] = 0; moveForward(); } } } /* int countZero(void){ int zero = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (!map[i][j]) { zero++; } } } return zero; } */ void restart(void){ for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { map[i][j] = 0; } } gameStart(); loop(); } void loop(void){ for(;;) { getDirection(); printMap(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (!map[i][j]) { //只要有空的格子 就加 randomAdd(); goto go; } } } go: if (checkIfGameOver() == true){ printf("You are lose!"); exit(0); } } } int main() { gameStart(); loop(); return 0; }