大大维的游戏机计划2--一个自制的类似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 }

付几张游戏截图:

时间: 2024-10-08 17:47:29

大大维的游戏机计划2--一个自制的类似2048的小游戏的相关文章

大大维的游戏机计划3--2048v1

前几天由于忙着过年串门,游戏机的计划搁置了几天.这两天终于空出了一块时间,抽空写了2048. 由于笔者前面自制了一个类似2048的游戏,所以写起来也算是轻车熟路,花了两个晚上也就差不多了. 废话少说,先将代码copy一份过来! 后续这几天,笔者想先写一个拼图小游戏,然后想办法将这几个游戏中共同存在的全屏刷新闪屏的问题给解决了. 另外,整个程序代码均为笔者原创,引用或转载请注明出处! 1 /**----------------------------------------------------

使用Python开发一个超级简单的接水果小游戏,零基础也可以学会

Pylash项目地址 创建项目 这样的话我们的项目就创建好了,然后只用往Main.py里填写代码运行即可. 编写Hello World小程序 编写游戏 有以上对pylash的小小了解,我们接下来可以开始编写游戏了.首先我们把第四行以后所有代码删除. 引入所需 全局变量 游戏里面要用到一些全局变量,大家先浏览一遍,不同知道它们是干什么的,之后会用到: 加载资源 创建开始界面 在main函数中我们调用了gameInit函数,所以添加这个函数: 开始游戏 舞台层鼠标点击事件的监听器是startGame

做了一个小游戏,结项目,数数坑

这是一个微信端的,投篮小游戏. 游戏规则如下: 点击开始,进入游戏,按住右下角红色按钮控制投篮力度,3次进球以后游戏难度将会升级.45秒内您的进球数将会计入排行榜,最终排行榜上的名次可以获得相应奖励,快来投篮冲榜领福利吧. 一.动画效果 做微信项目,相信大家和我一样,已经习惯了放弃使用jQuery,转而使用zepto.但是zepto并没有集成animate()方法.因此若想使用动画,用不想做兼容处理,最高效的方法是重拾jQuery. $(selector).animate(styles,spee

axure 实现的一个简易的找茬小游戏

好吧,今天早上用了一早的时间,就是实现一个看图找不同的小游戏.到下课,才把基本情况弄好! 首页不用多说,大家都会,只需要一个简单的链接. 在关卡中,各个关卡都大致相同,我就以第一关为例简要说明一下: 1.时间 限定时间为120秒,就需要一个计时器,用动态面板实现它.新建动态面板,设置两个状态,载入页面时,默认为状态1,转换为状态2.在“动态面板状态改变时”一栏中,设置一下三个用例:     判断语句中的状态切换达到计时器效果,而元件文字框的判断是为了在时间到了的时候,给出如上图2的提示.“时间到

[Unity3D入门]分享一个自制的入门级游戏项目&quot;坦克狙击手&quot;

[Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手" 我在学Unity3D,TankSniper(坦克狙击手)这个项目是用来练手的.游戏玩法来自这里(http://www.4399.com/flash/127672_3.htm),虽然抄袭了人家的创意,不过我只用来练习(目前还很不成熟,离人家的境界相差很大),坦克.导弹.建筑模型来自网络,应该不会有版权问题吧. 由于模型和代码总共10M以上了,需要源代码和发布的Windows版.网页版程序的同学麻烦点个赞并留下你的邮箱~ 到

二维数组与指针的一个例子

刚在网上看到的一个题目,觉得有点意思就做了一下:输入m,n,返回一个m*n的零矩阵. 方案一:用一维指针解决,比较简单 #include<stdio.h> #include<malloc.h> int main() {  int m,n,i,j,*p;  printf("input m,n\n");  scanf("%d%d",&m,&n);  p = (int *)malloc(m*n*sizeof(int));   //m

周期性计划(一个cron守护进程):

周期性计划(一个cron守护进程): [email protected]:/etc# ps -ef | grep cron root 903 1 0 16:25 ? 00:00:00 /usr/sbin/cron -f root 16162 6459 0 22:08 pts/1 00:00:00 grep --color=auto cron cron是一个可以根据时间,日期,月份,星期的组合的周期性执行的守护进程. (可以停掉和重启) [email protected]:/etc# servic

自制Unity小游戏TankHero-2D(3)开始玩起来

自制Unity小游戏TankHero-2D(3)开始玩起来 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的.仅为学习Unity之用.图片大部分是自己画的,少数是从网上搜来的.您可以到我的github页面(https://github.com/bitzhuwei/TankHero-2D)上得到工程源码. 本篇主要记录金币.按钮.坦克工厂.小地图等小部件,让整个场景初步成为一个可玩的游戏. 在本篇在制作过程中,

小游戏●贪吃蛇1(利用二维数组制作)

利用二维数组编写简单贪吃蛇小游戏,由于是初学C#,用的是单线程,所以蛇不会自动前进 代码及简要分析如下: 1 //定义地图,0为空,1为墙,2为蛇,3为食物 2 int[,] map = new int[15, 15]{ 3 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 4 {1,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, 5 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 6 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},