zoukankan      html  css  js  c++  java
  • 基于C++控制台的一个的类似2048的小游戏

    本文为大大维原创,最早于博客园发表,转载请注明出处!!!

    承接上篇,这几日,笔者本来打算写一个2048的,但写着写着,突然有个想法,能不能搞一个将2048和消消乐结合起来的游戏,于是,笔者便写出了如下这个小游戏。

    值得一提的是,整个游戏完全由笔者独自写成,并没有参考任何网上的代码,这跟上次写贪吃蛇前学了老半天网上已有代码就显得独立了很多。看来贪食蛇的书写还是让笔者受益匪浅

    定义的游戏规则如下:

    1.采用类似2048的游戏规则合成数字

    2.加入消消乐的点选作用(类似于在PC端模拟了一下触摸屏)

    3.加入地图压缩规则

    4.由于游戏像2048,就叫他NEW2048吧

    虽然笔者将游戏按照所想做了出来,但笔者玩了一下,可玩性并不高。甚至十分枯燥!!!

    尽管如此,这个游戏还是笔者完全独立书写的第一个游戏,意义还是蛮大的,因此笔者还是在此记录一笔。日后再翻出来改改,说不定能更好玩些。

    大家可以试试这个游戏,并提提意见,可能有些bug,也请指正。

    以后还是接着计划写剩余的游戏,加油。

      1 #include<iostream>
      2 #include<string>
      3 #include<cmath>
      4 #include<ctime>
      5 #include<cstdlib>
      6 #include<conio.h>
      7 using namespace std;
      8 constexpr unsigned HIGH=4;
      9 constexpr unsigned LENG=4;
     10 ///当前地图状态:READY,即(),可以进行moveAndAddData()操作;WAIT,即[],可以进行chooseMapSpace()操作
     11 enum state {READY,WAIT};
     12 ///当前操作块的移动方向及操作:UP,上;DOWN,下;LEFT,左;RIGHT,右;CHANGE,改变状态;DEFAULT,其他
     13 enum dir {UP,DOWN,LEFT,RIGHT,CHANGE,DEFAULT};
     14 class MapNew2048
     15 {
     16 public:
     17     MapNew2048();///构造函数,初始化数据
     18     void printMap();///地图打印
     19     void chooseMapSpace();///操作块移动,选择想要处理的地图块
     20     void moveAndAddData();///移动和相加选中块的数据
     21     ///压缩地图,将有意义的数值向左(上)角靠拢
     22     void mapSortToUp();
     23     void mapSortToLeft();
     24     ///当一行(一列)完全为空时,随机生成一个数加入地图(这个数不能大于当前所合成的最大数的一半)
     25     void dataCreate();
     26     void stateChange();///状态切换函数
     27     bool isLive();///是否存活判断
     28     state getState();///获取当前地图状态
     29     dir setDir();///输入操作块的移动方向
     30     unsigned getMaxData();
     31     string dataToPrintData(int n);///data到printData的转换函数
     32 private:
     33     unsigned data[HIGH][LENG];///设要显示数据为x,data=log2(x),空白时,data=0
     34     string printData[HIGH][LENG];///存储规范化的输出数据
     35     int nowX;///记录当前操作块的位置
     36     int nowY;
     37     state sta;///记录当前地图状态,确定执行chooseMapSpace()还是moveAndAddData()
     38     bool flag;///记录上次moveAndAddData()操作是否成功
     39 };
     40 
     41 MapNew2048::MapNew2048()
     42 {
     43     for(int i=0; i<HIGH; i++)
     44         for(int j=0; j<LENG; j++)
     45         {
     46             data[i][j]=1;
     47             srand((unsigned)time(NULL)+(2*i+3*j));///确保每一次,地图的每一格生成的data都是随机的
     48             unsigned p=rand()%5;
     49             if(p!=0)
     50                 data[i][j]=p;
     51         }
     52     for(int i=0; i<HIGH; i++)
     53         for(int j=0; j<LENG; j++)
     54             printData[i][j]=dataToPrintData(data[i][j]);
     55     nowX=nowY=0;
     56     printData[nowX][nowY][0]='[';
     57     printData[nowX][nowY][7]=']';
     58     sta=WAIT;
     59 }
     60 
     61 state MapNew2048::getState()
     62 {
     63     return sta;
     64 }
     65 
     66 dir MapNew2048::setDir()
     67 {
     68     char keydown=getch();///读取按键
     69     switch(keydown)
     70     {
     71     case 'w':
     72         return UP;
     73         break;
     74     case 'W':
     75         return UP;
     76         break;
     77     case 's':
     78         return DOWN;
     79         break;
     80     case 'S':
     81         return DOWN;
     82         break;
     83     case 'a':
     84         return LEFT;
     85         break;
     86     case 'A':
     87         return LEFT;
     88         break;
     89     case 'd':
     90         return RIGHT;
     91         break;
     92     case 'D':
     93         return RIGHT;
     94         break;
     95     case ' ':
     96         return CHANGE;
     97         break;
     98     default:
     99         return DEFAULT;
    100         break;
    101     }
    102 }
    103 unsigned MapNew2048::getMaxData()
    104 {
    105     unsigned temp=data[0][0];
    106     for(int i=0; i<HIGH; i++)
    107         for(int j=0; j<LENG; j++)
    108         {
    109             temp=temp>data[i][j]?temp:data[i][j];
    110         }
    111     return temp;
    112 }
    113 void MapNew2048::printMap()
    114 {
    115     cout<<"            NEW   2    0    4    8"<<endl;
    116     cout<<"-----------------------------------------------------"<<endl;
    117     for(int i=0; i<HIGH; i++)
    118     {
    119         for(int j=0; j<LENG; j++)
    120         {
    121             if(data[i][j]!=0)
    122                 cout<<"|  "<<printData[i][j]<<"  ";
    123             else
    124                 cout<<"|  "<<printData[i][j][0]<<"      "<<printData[i][j][7]<<"  ";
    125         }
    126         cout<<"|"<<endl<<"-----------------------------------------------------"<<endl;
    127     }
    128 }
    129 
    130 string MapNew2048::dataToPrintData(int n)
    131 {
    132 
    133     int count=0;
    134     int m=pow(2,n);
    135     ///str的初始化基于如下数学关系:4*4的地图下,2048游戏能合成数,理论上最大值131072(2^17),即data最大为17
    136     string str {' ',m/100000+48,(m/10000)%10+48,(m/1000)%10+48,(m/100)%10+48,(m/10)%10+48,m%10+48,' '};
    137     ///对冗余0的处理
    138     for(int i=1; i<7; i++)
    139     {
    140         if(str[i]=='0')
    141         {
    142             count++;
    143             str[i]=' ';
    144         }
    145         else
    146             break;
    147     }
    148     switch(count)///格式调整
    149     {
    150     case 2:///不加break会在执行完第一条语句后自动执行break
    151     {
    152         str[2]=str[3];
    153         str[3]=str[4];
    154         str[4]=str[5];
    155         str[5]=str[6];
    156         str[6]=' ';
    157         break;
    158     }
    159     case 3:
    160     {
    161         str[3]=str[4];
    162         str[4]=str[5];
    163         str[5]=str[6];
    164         str[6]=' ';
    165         break;
    166     }
    167     case 4:
    168     {
    169         str[3]=str[5];
    170         str[4]=str[6];
    171         str[5]=' ';
    172         str[6]=' ';
    173         break;
    174     }
    175     case 5:
    176     {
    177         str[4]=str[6];
    178         str[6]=' ';
    179         break;
    180     }
    181     }
    182     return str;
    183 }
    184 void MapNew2048::chooseMapSpace()
    185 {
    186 
    187     if(sta==WAIT)
    188     {
    189         printData[nowX][nowY][0]=printData[nowX][nowY][7]=' ';
    190         dir DIR=setDir();
    191         switch(DIR)
    192         {
    193         case LEFT:
    194         {
    195             nowY--;
    196             if(nowY<0)
    197                 nowY=LENG-1;
    198             printData[nowX][nowY][0]='[';
    199             printData[nowX][nowY][7]=']';
    200             break;
    201         }
    202         case RIGHT:
    203         {
    204             nowY++;
    205             if(nowY>LENG-1)
    206                 nowY=0;
    207             printData[nowX][nowY][0]='[';
    208             printData[nowX][nowY][7]=']';
    209             break;
    210         }
    211         case UP:
    212         {
    213             nowX--;
    214             if(nowX<0)
    215                 nowX=HIGH-1;
    216             printData[nowX][nowY][0]='[';
    217             printData[nowX][nowY][7]=']';
    218             break;
    219         }
    220         case DOWN:
    221         {
    222             nowX++;
    223             if(nowX>HIGH-1)
    224                 nowX=0;
    225             printData[nowX][nowY][0]='[';
    226             printData[nowX][nowY][7]=']';
    227             break;
    228         }
    229         case CHANGE:
    230             stateChange();
    231             break;
    232         case DEFAULT:
    233         {
    234             printData[nowX][nowY][0]='[';
    235             printData[nowX][nowY][7]=']';
    236             break;
    237         }
    238         }
    239     }
    240 }
    241 void MapNew2048::moveAndAddData()
    242 {
    243     if(sta==READY)
    244     {
    245         printData[nowX][nowY][0]=printData[nowX][nowY][7]=' ';
    246         dir DIR=setDir();
    247         switch(DIR)
    248         {
    249         case LEFT:
    250         {
    251             if((data[nowX][nowY]==data[nowX][nowY-1])&&(nowY>0)&&(data[nowX][nowY-1]>0))
    252             {
    253                 data[nowX][nowY]=0;
    254                 nowY--;
    255                 data[nowX][nowY]++;
    256                 printData[nowX][nowY]=dataToPrintData(data[nowX][nowY]);
    257                 printData[nowX][nowY][0]='(';
    258                 printData[nowX][nowY][7]=')';
    259             }
    260             else
    261             {
    262                 printData[nowX][nowY][0]='(';
    263                 printData[nowX][nowY][7]=')';
    264             }
    265             mapSortToLeft();
    266             mapSortToUp();
    267             break;
    268         }
    269         case RIGHT:
    270         {
    271             if((data[nowX][nowY]==data[nowX][nowY+1])&&(nowY<LENG-1)&&(data[nowX][nowY+1]>0))
    272             {
    273                 data[nowX][nowY]=0;
    274                 nowY++;
    275                 data[nowX][nowY]++;
    276                 printData[nowX][nowY]=dataToPrintData(data[nowX][nowY]);
    277                 printData[nowX][nowY][0]='(';
    278                 printData[nowX][nowY][7]=')';
    279             }
    280             else
    281             {
    282                 printData[nowX][nowY][0]='(';
    283                 printData[nowX][nowY][7]=')';
    284             }
    285             mapSortToLeft();
    286             mapSortToUp();
    287             break;
    288         }
    289         case UP:
    290         {
    291             if((data[nowX][nowY]==data[nowX-1][nowY])&&(nowX>0)&&(data[nowX-1][nowY]>0))
    292             {
    293                 data[nowX][nowY]=0;
    294                 nowX--;
    295                 data[nowX][nowY]++;
    296                 printData[nowX][nowY]=dataToPrintData(data[nowX][nowY]);
    297                 printData[nowX][nowY][0]='(';
    298                 printData[nowX][nowY][7]=')';
    299             }
    300             else
    301             {
    302                 printData[nowX][nowY][0]='(';
    303                 printData[nowX][nowY][7]=')';
    304             }
    305             mapSortToUp();
    306             mapSortToLeft();
    307             break;
    308         }
    309         case DOWN:
    310         {
    311             if((data[nowX][nowY]==data[nowX+1][nowY])&&(nowX<HIGH-1)&&(data[nowX+1][nowY]>0))
    312             {
    313                 data[nowX][nowY]=0;
    314                 nowX++;
    315                 data[nowX][nowY]++;
    316                 printData[nowX][nowY]=dataToPrintData(data[nowX][nowY]);
    317                 printData[nowX][nowY][0]='(';
    318                 printData[nowX][nowY][7]=')';
    319             }
    320             else
    321             {
    322                 printData[nowX][nowY][0]='(';
    323                 printData[nowX][nowY][7]=')';
    324             }
    325             mapSortToUp();
    326             mapSortToLeft();
    327             break;
    328         }
    329         case CHANGE:
    330             stateChange();
    331             break;
    332         case DEFAULT:
    333         {
    334             printData[nowX][nowY][0]='(';
    335             printData[nowX][nowY][7]=')';
    336             break;
    337         }
    338         }
    339     }
    340 }
    341 
    342 void MapNew2048::stateChange()
    343 {
    344     if(sta==WAIT)
    345     {
    346         sta=READY;
    347         printData[nowX][nowY][0]='(';
    348         printData[nowX][nowY][7]=')';
    349     }
    350     else
    351     {
    352         sta=WAIT;
    353         printData[nowX][nowY][0]='[';
    354         printData[nowX][nowY][7]=']';
    355     }
    356 }
    357 
    358 void MapNew2048::mapSortToUp()///地图向上压缩
    359 {
    360     for(int n=0; n<LENG; n++)
    361     {
    362         for(int m=0; m<HIGH; m++)
    363         {
    364             if(data[m][n]==0&&m<HIGH-1)
    365             {
    366                 for(int k=m; k<HIGH-1; k++)
    367                 {
    368                     data[k][n]=data[k+1][n];
    369                     printData[k][n]=dataToPrintData(data[k][n]);
    370                 }
    371                 data[HIGH-1][n]=0;
    372             }
    373         }
    374     }
    375     ///调整时,会将printData[nowX][nowY]的标志冲掉,需要恢复一步
    376     printData[nowX][nowY][0]='(';
    377     printData[nowX][nowY][7]=')';
    378 }
    379 void MapNew2048::mapSortToLeft()///地图向左压缩
    380 {
    381     for(int m=0; m<HIGH; m++)
    382     {
    383         for(int n=0; n<LENG; n++)
    384         {
    385             if(data[m][n]==0&&n<LENG-1)
    386             {
    387                 for(int k=n; k<LENG-1; k++)
    388                 {
    389                     data[m][k]=data[m][k+1];
    390                     printData[m][k]=dataToPrintData(data[m][k]);
    391                 }
    392                 data[m][LENG-1]=0;
    393             }
    394         }
    395     }
    396     printData[nowX][nowY][0]='(';
    397     printData[nowX][nowY][7]=')';
    398 }
    399 
    400 //void MapNew2048::dataCreate()
    401 //{
    402 //    bool dataCreateFlag1=true;///列向生成newData标志
    403 //    bool dataCreateFlag2=true;///横向生成newData标志
    404 //    for(int i=0; i<HIGH; i++)
    405 //        if(data[i][LENG-1]!=0)
    406 //        {
    407 //            dataCreateFlag1=false;
    408 //            break;
    409 //        }
    410 //    for(int i=0; i<LENG; i++)
    411 //        if(data[HIGH-1][i]!=0)
    412 //        {
    413 //            dataCreateFlag2=false;
    414 //            break;
    415 //        }
    416 //    if(!dataCreateFlag1&&!dataCreateFlag2);///不用生成newData
    417 //    else
    418 //    {
    419 //        unsigned max=getMaxData();
    420 //        ///创建的数不大于当前地图显示的合成的最大数的一半,newData最大为max-1
    421 //        srand((unsigned int)time(NULL));
    422 //        unsigned newData=rand()%max;
    423 //        if(newData==0)
    424 //            newData++;
    425 //        /**经过上述的newData生成算法,P(newData=1)=2/(max-1),P(newData=other)=1/(max-1)**/
    426 //
    427 //        /**下面的几行语句用于确定newData在地图中的位置**/
    428 //        if(dataCreateFlag1&&!dataCreateFlag2)
    429 //        {
    430 //            srand((unsigned int)time(NULL));
    431 //            int a=rand()%HIGH;
    432 //            data[a][LENG-1]=newData;
    433 //            printData[a][LENG-1]=dataToPrintData(data[a][LENG-1]);
    434 //            mapSortToLeft();///地图压缩
    435 //        }
    436 //        else if(!dataCreateFlag1&&dataCreateFlag2)
    437 //        {
    438 //            srand((unsigned int)time(NULL));
    439 //            int b=rand()%LENG;
    440 //            data[HIGH-1][b]=newData;
    441 //            printData[HIGH-1][b]=dataToPrintData(data[HIGH-1][b]);
    442 //            mapSortToUp();///地图压缩
    443 //        }
    444 //        else if(dataCreateFlag1&&dataCreateFlag2)
    445 //        {
    446 //            srand((unsigned int)time(NULL));
    447 //            int a=rand()%HIGH;
    448 //            data[a][LENG-1]=newData;
    449 //            printData[a][LENG-1]=dataToPrintData(data[a][LENG-1]);
    450 //            if(a==HIGH-1)
    451 //            {
    452 //                mapSortToLeft();///地图压缩
    453 //                mapSortToUp();
    454 //            }
    455 //            else
    456 //                mapSortToLeft();
    457 //        }
    458 //    }
    459 //}
    460 
    461 
    462 bool MapNew2048::isLive()
    463 {
    464     ///isLive函数基于如下数学关系:反复使用向右,向下查询(最右行只向下),
    465     ///最底行只向右,可以将他的所有邻居遍历一次
    466     bool liveFlag=false;
    467     for(int i=0; i<HIGH; i++)
    468     {
    469         for(int j=0; j<LENG; j++)
    470         {
    471             if(i!=HIGH-1&&j!=LENG-1&&data[i][j]!=0)
    472             {
    473                 if(data[i][j]==data[i+1][j]||data[i][j]==data[i][j+1])
    474                 {
    475                     liveFlag=true;
    476                     return liveFlag;
    477                 }
    478             }
    479             else if(i==HIGH-1&&j!=LENG-1&&data[i][j]!=0)
    480             {
    481                 if(data[i][j]=data[i+1][j])
    482                 {
    483                     liveFlag=true;
    484                     return liveFlag;
    485                 }
    486             }
    487             else if(i!=HIGH-1&&j==LENG-1&&data[i][j]!=0)
    488             {
    489                 if(data[i][j]=data[i][j+1])
    490                 {
    491                     liveFlag=true;
    492                     return liveFlag;
    493                 }
    494             }
    495         }
    496     }
    497     return liveFlag;
    498 }
    499 
    500 int main()
    501 {
    502     bool gameOverFlag=false;
    503     MapNew2048 map;
    504     map.printMap();
    505     while(!gameOverFlag)
    506     {
    507         while(kbhit())
    508         {
    509             system("cls");
    510         if(map.getState()==WAIT)
    511             map.chooseMapSpace();
    512         else
    513         {
    514             map.moveAndAddData();
    515 //            map.dataCreate();
    516         }
    517         if(!map.isLive())
    518             gameOverFlag=true;
    519         map.printMap();
    520         }
    521 
    522     }
    523     cout<<endl<<"The Max is:  "<<pow(2,map.getMaxData())<<endl;
    524 }
    View Code

    付几张游戏截图:

  • 相关阅读:
    《Docker技术入门与实践》Docker入门4-使用Dockerfile创建镜像
    《Docker技术入门与实践》Docker入门3-网络基础配置
    《Docker技术入门与实践》Docker入门2-数据管理
    Git管理多个SSH密钥,Git多帐号配置
    《Docker技术入门与实践》Docker入门
    java获取汉字笔画数
    NSBundle、UIImageView、uibutton
    动画帧的使用
    结构体的转换
    IOS字符串的处理例子
  • 原文地址:https://www.cnblogs.com/liujw2114/p/6351735.html
Copyright © 2011-2022 走看看