2048原始碼~~小遊戲。C++實現
阿新 • • 發佈:2019-01-02
每一個學習軟體工程的人,都很想自己寫出遊戲的程式碼,我也不例外,但是,能寫出一些小遊戲的程式碼,並不能說明你很厲害,而只能說明你對於這門語言你比較熟悉了。
2048這個遊戲,是一兩年前很火的遊戲,不過現在也沒什麼人在玩了,閒來沒事,就寫了一下這個遊戲,控制檯上實現的,目前我還不會寫視窗,所以很多東西都只能在控制檯上來實現了。
2048這個小遊戲,主要的是上下左右移動後,相同的數合併,不相同的數原樣輸出,而你就是要判斷每一行或每一列有沒有相同的,還有一點就是,數字有移動,就產生新的數,沒有,什麼都不用做。
下面是標頭檔案的:
class New2048 { public: New2048() //建構函式,初始話資料。 { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) a[i][j] = 0; num = 0; } void make_frame(); //列印框架函式。 void display_num(); //列印數字函式。 void creat_num(); //隨機產生數函式 void RightMove(); //右移函式 void LeftMove(); //左移函式 void UpMove(); //上移函式 void DownMove(); //下移函式 int cheak(); //檢查遊戲是否結束函式 void clean(); //清理顯示出來的數字 ~New2048(){} private: int a[4][4]; int num; };
下面是各個函式的cpp檔案:
# include <iostream> # include <Windows.h> # include <time.h> # include <conio.h> # include "2048.h" using namespace std; HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //獲取控制代碼 void gotoxy(HANDLE hOut, int x, int y) //輸出位置的函式 { COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(hOut, pos); } void New2048::make_frame() //列印框架 { gotoxy(hOut, 0, 0); cout << " 得分" << endl; cout << "┏━━┳━━┳━━┳━━┓" << endl; cout << "┃ ┃ ┃ ┃ ┃" << endl; cout << "┣━━╋━━╋━━╋━━┫" << endl; cout << "┃ ┃ ┃ ┃ ┃" << endl; cout << "┣━━╋━━╋━━╋━━┫" << endl; cout << "┃ ┃ ┃ ┃ ┃" << endl; cout << "┣━━╋━━╋━━╋━━┫" << endl; cout << "┃ ┃ ┃ ┃ ┃" << endl; cout << "┗━━┻━━┻━━┻━━┛" << endl; } void New2048::clean() { int k = 0, l = 0; for (int i = 2; i < 21, k < 4; i = i + 6) //找到對應的框,輸入空格 { l = 0; for (int j = 2; j < 9; j = j + 2) { gotoxy(hOut, i, j); printf(" "); l++; } k++; } } void New2048::display_num() //列印數字 { int k = 0, l = 0; for (int i = 2; i < 21, k < 4; i = i + 6) //找到對應的框,輸入數字,這個嘗試了好久,才搞定了。 { l = 0; for (int j = 2; j < 9; j = j + 2) { gotoxy(hOut, i, j); //找到各個位置並輸出數字 a[l][k] == 0 ? printf(" ") : printf("%d", a[l][k]); l++; } k++; } gotoxy(hOut, 13, 0); cout << num * 100; gotoxy(hOut, 0, 10); } void New2048::creat_num() //隨機產生座標位置和該位置的數 2 或 4 { int i, j, num; srand((unsigned)time(NULL)); //隨機數產生初始化,不然產生的數一直相同 i = (rand() % (4)) + 0; j = (rand() % (4)) + 0; while (a[i][j]) //該位置上的數不是0,重新產生 { i = (rand() % (4)) + 0; j = (rand() % (4)) + 0; } num = (rand() % (4)) + 1; //產生的是1就自增,是3便自減或自增,都可以的 if (num == 1) ++num; if (num == 3) --num; a[i][j] = num; } int New2048::cheak() { int i, j, flag = 0, tag = 0; for (i = 0; i < 4; i++) //檢查是否還有位置,有,tag = 1。 { for (j = 0; j < 4; j++) { if (a[i][j] == 0) { tag = 1; break; } } if (tag == 1) break; } if (tag) //有,返回1。 return 1; for (i = 0; i < 4; i++) //檢查左右的相鄰是否有相等,是,flag = 1,退出迴圈 { for (j = 0; j < 3; j++) { if (a[i][j] == a[i][j + 1]) { flag = 1; break; } } if (flag == 1) break; } for (j = 0; j < 4; j++) //檢查上下的相鄰是否有想等,是,flag = 1,退出迴圈 { for (i = 0; i < 3; i++) { if (a[i][j] == a[i + 1][j]) { flag = 1; break; } } if (flag == 1) break; } if (tag == 0 && flag == 0) //flag = 0 和 tag = 0,遊戲結束。 return 0; else //否則,繼續遊戲 return 1; } void New2048::DownMove() //下移的情況 { int k, tag = 0; for (int i = 0; i < 4; i++) //從每一列開始 { int b[4] = { 0 }; //定義一個臨時陣列來儲存相加之後的情況 k = 3; for (int j = 3; j > 0; j--) { if (a[j][i] != 0) { int flag = 0; for (int l = j - 1; l >= 0; l--) //找是否有相同的數 { if (a[l][i] != 0) { flag = 1; if (a[l][i] == a[j][i]) { b[k--] = 2 * a[j][i]; num++; a[l][i] = a[j][i] = 0; break; } else { b[k--] = a[j][i]; break; } } } if (flag == 0) b[k--] = a[j][i]; } } b[k] = a[0][i]; //最後一個沒有檢查,賦值過去,不管是否為0,都無所謂的 for (int j = 0; j < 4; j++) //檢查是否有移動 { if (a[j][i] != b[j]) { tag = 1; break; } } for (int j = 0; j < 4; j++) //將結果覆蓋回去 a[j][i] = b[j]; } if (tag) //存在移動,產生新的數 creat_num(); } void New2048::LeftMove() //同上 { int k, tag = 0; for (int i = 0; i < 4; i++) { int b[4] = { 0 }; k = 0; for (int j = 0; j < 3; j++) { if (a[i][j] != 0) { int flag = 0; for (int l = j + 1; l < 4; l++) { if (a[i][l] != 0) { flag = 1; if (a[i][l] == a[i][j]) { b[k++] = 2 * a[i][j]; num++; a[i][j] = a[i][l] = 0; break; } else { b[k++] = a[i][j]; break; } } } if (flag == 0) b[k++] = a[i][j]; } } b[k] = a[i][3]; for (int j = 0; j < 4; j++) { if (a[i][j] != b[j]) { tag = 1; break; } } for (int j = 0; j < 4; j++) a[i][j] = b[j]; } if (tag) creat_num(); } void New2048::RightMove() //同上 { int k, tag = 0; for (int i = 0; i < 4; i++) { int b[4] = { 0 }; k = 3; for (int j = 3; j > 0; j--) { if (a[i][j] != 0) { int flag = 0; for (int l = j - 1; l >= 0; l--) { if (a[i][l] != 0) { flag = 1; if (a[i][l] == a[i][j]) { b[k--] = 2 * a[i][j]; num++; a[i][j] = a[i][l] = 0; break; } else { b[k--] = a[i][j]; break; } } } if (flag == 0) b[k--] = a[i][j]; } } b[k] = a[i][0]; for (int j = 0; j < 4; j++) { if (a[i][j] != b[j]) { tag = 1; break; } } for (int j = 0; j < 4; j++) a[i][j] = b[j]; } if (tag) creat_num(); } void New2048::UpMove() { int k, tag = 0; for (int i = 0; i < 4; i++) { int b[4] = { 0 }; //定義一個臨時陣列來儲存相加之後的情況 k = 0; for (int j = 0; j < 3; j++) { if (a[j][i] != 0) { int flag = 0; for (int l = j + 1; l < 4; l++) //找是否有相同的數 { if (a[l][i] != 0) { flag = 1; if (a[l][i] == a[j][i]) { b[k++] = 2 * a[j][i]; num++; a[l][i] = a[j][i] = 0; break; } else { b[k++] = a[j][i]; break; } } } if (flag == 0) b[k++] = a[j][i]; } } b[k] = a[3][i]; for (int j = 0; j < 4; j++) { if (a[j][i] != b[j]) { tag = 1; break; } } for (int j = 0; j < 4; j++) //將結果覆蓋回去 a[j][i] = b[j]; } if (tag) creat_num(); }
主函式的cpp檔案:
# include <iostream> # include <conio.h> # include "2048.h" using namespace std; int main() { while (1) { char ch; system("cls"); //清屏 system("color 3B"); //改變背景和字型顏色 New2048 s; s.make_frame(); //列印框架 s.creat_num(); s.creat_num(); //產生兩個隨機數 s.display_num(); //顯示數字 while (1) { ch = _getch(); //如果不是VS的,_getch應該改成getch if (ch == 'a' || ch == 's' || ch == 'd' || ch == 'w' || ch == ' ' || ch == 'A' || ch == 'S' || ch == 'D' || ch == 'W') break; } p: switch (ch) { case 's': case 'S': { while (s.cheak()) { s.DownMove(); //下移 s.clean(); //清理 s.display_num(); //顯示數字 while (1) { ch = _getch(); if (ch == 'a' || ch == 's' || ch == 'd' || ch == 'w' || ch == ' ' || ch == 'A' || ch == 'S' || ch == 'D' || ch == 'W') break; } goto p; } }break; case 'd': case 'D': { while (s.cheak()) { s.RightMove(); //右移 s.clean(); //清理 s.display_num(); //顯示數字 while (1) { ch = _getch(); if (ch == 'a' || ch == 's' || ch == 'd' || ch == 'w' || ch == ' ' || ch == 'A' || ch == 'S' || ch == 'D' || ch == 'W') break; } goto p; } }break; case 'a': case 'A': { while (s.cheak()) { s.LeftMove(); //左移 s.clean(); //清理 s.display_num(); //顯示數字 while (1) { ch = _getch(); if (ch == 'a' || ch == 's' || ch == 'd' || ch == 'w' || ch == ' ' || ch == 'A' || ch == 'S' || ch == 'D' || ch == 'W') break; } goto p; } }break; case 'w': case 'W': { while (s.cheak()) { s.UpMove(); //上移 s.clean(); //清理 s.display_num(); //顯示數字 while (1) { ch = _getch(); if (ch == 'a' || ch == 's' || ch == 'd' || ch == 'w' || ch == ' ' || ch == 'A' || ch == 'S' || ch == 'D' || ch == 'W') break; } goto p; } }break; default: break; } //退出switch,遊戲結束 system("cls"); //清屏 cout << " PLAY AGAIN ? YES(Y) : NO(N)" << endl; while (1) { ch = _getch(); if (ch == 'y' || ch == 'n' || ch == 'Y' || ch == 'N') break; } if (ch == 'y' || ch == 'Y') //Y繼續 continue; else //否則退出 break; } return 0; }
遊戲開始圖片:
遊戲過程中的圖片:
遊戲結束圖片:
這個或多或少的存在bug,如果發現了,歡迎來告訴我,好讓我改正!~~