c++實現2048[牛客網、控制檯]
阿新 • • 發佈:2018-12-25
1.前言
剛學完c++基礎,找個專案練練手,於是上牛客網找了個2048練練手,文章最後給出原始碼
2.簡介
- 一次只能合併相鄰的兩個數字,例如 [2 2 2 2] ,向右合併以後是 [空 空 4 4] ,不是 [空 空 空 8]
- 每次合併的時候,合併方向優先順序高,例如 [空 2 2 2],向右合併以後是 [空 空 2 4],不是 [空 空 4 2]
- 判斷遊戲結束
- 每次合併以後隨機新出4的概率10%
3.專案思路
- 用一個4*4的int陣列來儲存資料,初始化為0
- 使用者上下左右移的操作可整體簡化為3個步驟
- 1)將非0元素緊湊
- 2)合併同類項
- 3)再將非0元素緊湊
4.示例
2 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
此時執行上移操作,步驟如下
1)緊湊
2 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
2)上移合併同類項
4 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
3)緊湊
4 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
5.bug
因為樓主在隨機位置生成隨機數的程式碼如下
//生成隨機數
int randomNum(){
int num=rand()%10;
return num>8?4:2;
}
//para num->使用者想生成[0,num]間隨機數
inline void random(int num){
srand((unsigned int)(time(NULL)));
a=rand()%num;
Sleep(100);
b=rand()%num;
}
//生成1個隨機位置並賦值
void randomAddress(){
//隨著4*4陣列中非0個數增加 可能出現卡頓 帶優化
while(map[a][b]!=0){
random(3);
}
int num=randomNum();
map[a][b]=num;
cout<<"row:"<<a<<" column"<<b<<" "<<map[a][b]<<endl;
}
當陣列中非0元素個數增多時,在隨機位置生成隨機數所耗費的時間也不斷增加
6.原始碼
#include <iostream>
#include <ctime>
#include<windows.h>
using namespace std;
void print();//列印當前狀態
int randomNum();//生成2個隨機數(其中一個必為2,另一個 2:4出現的比例=4:1)
void randomAddress();//生成2個隨機位置
inline void random(int);//生成隨機數[0,num),以便上述2個函式使用
void up();
void down();
void left();
void right();
bool isEnd();//判斷遊戲是否結束
int map[4][4]={0,};
int a=0,b=0;//兩個用來儲存隨機數的值
void print(){
cout << "************************************************" << endl;
cout << "* " << map[0][0] << " " << map[0][1] << " " << map[0][2] << " " << map[0][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "* " << map[1][0] << " " << map[1][1] << " " << map[1][2] << " " << map[1][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "* " << map[2][0] << " " << map[2][1] << " " << map[2][2] << " " << map[2][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "* " << map[3][0] << " " << map[3][1] << " " << map[3][2] << " " << map[3][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "操作詳情:(輸入後,按回車鍵結束)" << endl;
cout << "w : 向上移動 s : 向下移動" << endl;
cout << "a : 向左移動 r : 向右移動" << endl;
cout << "q : 退出" << endl;
}
//para num->使用者想生成[0,num]間隨機數
inline void random(int num){
srand((unsigned int)(time(NULL)));
a=rand()%num;
Sleep(100);
b=rand()%num;
}
//生成隨機數
int randomNum(){
int num=rand()%10;
return num>8?4:2;
}
//判斷遊戲是否結束 結束條件:1.4x4陣列中非0元素已滿 2.出現2048
bool isEnd(){
for(int a=0;a<4;a++){
for(int b=0;b<4;b++){
if(map[a][b]==2048)return true;
if(map[a][b]==0)return false;
}
}
return true;
}
//生成1個隨機位置並賦值
void randomAddress(){
//隨著4*4陣列中非0個數增加 可能出現卡頓 帶優化
while(map[a][b]!=0){
random(3);
}
int num=randomNum();
map[a][b]=num;
cout<<"row:"<<a<<" column"<<b<<" "<<map[a][b]<<endl;
}
//使用者點選上移操作
void up(){
int row,column;
//1.將非0元素上移
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(row!=0&&map[row][column]!=0&&map[row-1][column]==0){
map[row-1][column]=map[row][column];
map[row][column]=0;
row--;
}
}
}
//2.相同元素合併 迴圈遍歷每一個元素
for(row=1;row<4;row++){
for(column=0;column<4;column++){
if(map[row][column]==0)continue;
else if(map[row][column]!=map[row-1][column]){
continue;
}else{
map[row-1][column]*=2;
map[row][column]=0;
}
}
}
//3.將合併後非0元素上移
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(row!=0&&map[row][column]!=0&&map[row-1][column]==0){
map[row-1][column]=map[row][column];
map[row][column]=0;
row--;
}
}
}
randomAddress();
}
//使用者點選下移操作
void down(){
int row,column;
//1.將非0元素下移
for(row=3;row>=0;row--){
for(column=0;column<4;column++){
while(row!=3&&map[row][column]!=0&&map[row+1][column]==0){
map[row+1][column]=map[row][column];
map[row][column]=0;
row++;
}
}
}
//2.合併同類項
for(row=2;row>=0;row--){
for(column=0;column<4;column++){
if(map[row][column]==0)continue;
else if(map[row][column]!=map[row+1][column]){
continue;
}else{
map[row+1][column]*=2;
map[row][column]=0;
}
}
}
//3.合併後非0
for(row=3;row>=0;row--){
for(column=0;column<4;column++){
while(row!=3&&map[row][column]!=0&&map[row+1][column]==0){
map[row+1][column]=map[row][column];
map[row][column]=0;
row++;
}
}
}
randomAddress();
}
//使用者點選左移操作
void left(){
int row,column;
//1.將非0元素左移
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(column!=0&&map[row][column]!=0&&map[row][column-1]==0){
map[row][column-1]=map[row][column];
map[row][column]=0;
column--;
}
}
}
//2.合併元素
for(row=0;row<4;row++){
for(column=1;column<4;column++){
if(map[row][column]==0)continue;
else if(map[row][column]!=map[row][column-1])continue;
map[row][column]=0;
map[row][column-1]*=2;
}
}
//3.
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(column!=0&&map[row][column]!=0&&map[row][column-1]==0){
map[row][column-1]=map[row][column];
map[row][column]=0;
column--;
}
}
}
randomAddress();
}
void right(){
int row,column;
//1.
for(row=0;row<4;row++){
for(column=3;column>=0;column--){
while(column!=3&&map[row][column]!=0&&map[row][column+1]==0){
map[row][column+1]=map[row][column];
map[row][column]=0;
column++;
}
}
}
//2.右移合併同類項
for(row=0;row<4;row++){
for(column=2;column>=0;column--){
if(map[row][column]==0||map[row][column]!=map[row][column+1])continue;
else{
map[row][column+1]*=2;
map[row][column]=0;
}
}
}
//3.
for(row=0;row<4;row++){
for(column=3;column>=0;column--){
while(column!=3&&map[row][column]!=0&&map[row][column+1]==0){
map[row][column+1]=map[row][column];
map[row][column]=0;
column++;
}
}
}
randomAddress();
}
int main(){
char control;
//資料初始化
randomAddress();
randomAddress();
print();
while(cin>>control){
switch(control){
case 'w':up();break;
case 's':down();break;
case 'a':left();break;
case 'd':right();break;
case 'q':return 0;
}
print();//將移動後元素列印
if(isEnd()){
cout<<"遊戲已結束"<<endl;
return 0;
}
}
return 0;
}