c/c++语言开发共享C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

/***************************项目 2048**********************c语言编写 图形库制作时间:2019.04.03 准备工具: vs2013 图形库 ico素材(作为exe的图标) 背景图(jpg格式)知识点: 循环 数组 函数 随机数 项目步骤分析: …

 /***************************项目 2048**********************
c语言编写 图形库制作
时间:2019.04.03

准备工具: vs2013 图形库 ico素材(作为exe的图标) 背景图(jpg格式)
知识点: 循环 数组 函数 随机数

项目步骤分析:
2048 通过方向键 wasd控制方向合并相同数字直到生成2048 游戏结束
1、4×4的棋盘 存放数字 —->数组 游戏操作 —->键盘操作 界面 —->需要操作结果

2、步骤
a、准备数组 生成两个隋杰的位置和随机的数字(2或4) //初始化操作
b、等待用户输入 根据上下左右处理数组
//添加一个判断输赢e
c、生成新的随机位置 和新的数字(2或4)
d、打印界面 当前输出结果 等待下一轮输入
e、输赢条件 输–>数组满,不能移动 赢–>出现2048,游戏就赢了

3、拆分函数 如果同一个功能或者相似的功能可以写成一个函数,减少代码量和难点
a 初始化

函数声明:

void init(int map[][4]); 

函数定义:

void init(int map[][4])
{

rand();
int x, y;
for (int i = 0; i < 2;)
{
x = rand() % 4; 
y = rand() % 4;
if (map[x][y] == 0) 
{
map[x][y] = rand()%2*2+2; 
}
}
}

在主函数中测试效果:

int main()
{
int map[4][4];
init(map); 
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf(“%dt”, map[i][j]);
}
printf(“%n”);
}

getchar();
return 0;
}

效果如图所示:

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

b 等待用户输入操作 随机位置

用switch进行键盘消息判断

各方向键的代码比对如下:

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏) C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏) C++学习(三十九)(C语言部分)之 游戏项目(2048游戏) 

 

也可以用枚举法定义方向键并对其进行消息的判断

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

 

对比如下:

 C++学习(三十九)(C语言部分)之 游戏项目(2048游戏) C++学习(三十九)(C语言部分)之 游戏项目(2048游戏) 

 C++学习(三十九)(C语言部分)之 游戏项目(2048游戏) C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

 

c 判断输赢

d 打印结果 显示地图

打印地图的函数:

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

 

暂时测试结果如下:

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

 

目的:
复习 总结 综合运用
***************************项目 2048**********************/

 

测试代码笔记如下:

  1 //**************************头文件部分*********************    2 //头文件 宏定义 类型定义 全局变量    3     4 //头文件    5 #include<stdio.h>    6 #include<memory.h>  //memset的头文件 或者string.h    7 #include<stdlib.h>  //srand函数  rand函数    8 #include<time.h>  //time函数    9 #include<conio.h>  //getch函数   10 #include<graphics.h>  //图形库   11 //#define color1 rgb(238,106,80)   12 //#define color2 rgb(238,169,184)   13 //#define color3 rgb(131,139,131)   14 //#define color4 rgb(193,205,205)   15    16 //类型定义 枚举   17 enum dir   18 {   19     up = 72, down = 80, left = 75, right = 77   20 };  //定义方向键   21    22 image img;//存放图片变量   23    24 //**************************函数声明***********************   25 //写个函数的声明   26 void init(int map[][4]);  //用函数给数组赋值初始化   27    28 void play(int map[][4]);  //处理用户输入   29    30 void drawmap(int map[][4]);  //打印 画图   31    32 void newnum(int map[][4]);  //随机一个新元素   33    34 int isgameover(int map[][4]);//判断游戏是否结束的一个函数   35    36 //**************************主函数*************************   37 //main函数   38 int main()   39 {   40     int map[4][4];  //准备数组 大小4x4的地图   41     init(map);  //传参(实参) 传的是数组名   42        43     while (1)  //死循环   44     {   45         drawmap(map);   46         play(map);   47         //system("cls");  //清屏函数 用于控制台   48         //newnum(map);   49         if (isgameover(map) != 0)  break;//结束循环   50     }   51    52     if (isgameover(map) == 1)   53     {   54         //赢得游戏   55         drawmap(map);   56         //printf("赢得游戏n");   57         messagebox(gethwnd(), l"ok", l"win", mb_ok);   58         //第一个 是窗口句柄  表示显示在这个窗口前面   可以写null 或者0   59         //第二个参数 是文本框内容   60         //第三次参数 窗口标题   61         //最后一个参数是按钮形式   62            63     }   64     else   65     {   66         //输了游戏   67         drawmap(map);   68         //printf("输了游戏n");   69         messagebox(gethwnd(), l"oops", l"lose", mb_ok);   70     }   71    72     //getchar();   73     closegraph();//关闭窗口   74     return 0;   75 }   76    77 //**************************函数定义************************   78 //上述函数的定义放在这里   79    80 //给数组赋值 初始化   81 void init(int map[][4])  //int (*map[4])(形参)  是数组指针 两种形式都可以   82 {   83     //给数组赋值 第一种方式用循环   84     //for (int i = 0; i < 4; ++i)  //数组用 下标进行循环   85     //{   86     //    for (int j = 0; j < 4; ++j)   87     //    {   88     //        map[i][j] = 0;  //刚开始全部赋值为0   89     //    }   90     //}   91    92     //第二种方式用函数 memset 初始化一块内存  头文件是stdlib,h   93     memset(map, 0, sizeof(int)* 4 * 4); //三个参数 内存首地址 初值 字节大小   94     //随机两个2和4  null用于指针 随机数 借用两个函数srand  rand --->头文件stlib.h  还需要一个函数 time(时间函数)--->头文件time.h   95     srand((unsigned)time(null));  //设置随机数种子  不要写在循环里面 设置一次就够了   96     //得到某个范围内的随机数 用求余控制范围  0-->100之间 int x=rand()%101; 66-->100之间 -->66+(0-->43)  rand()%35+66   97     //得到随机位置   98     int x, y;   99     for (int i = 0; i < 2;)  100     {  101         x = rand() % 4;  //下标3至3  所以对4求余  102         y = rand() % 4;  103         if (map[x][y] == 0)  //这个位置没有元素  104         {  105             map[x][y] = rand()%2*2+2; //2或4 2=1*2   4=2*2  106             i++;  //赋值之后才算一次  107         }  108         //++i放上面 只能确保循环两次 不能确保赋值两次 所以放下面  109     }  110 }  111   112 //处理用户输入  113 void play(int map[][4])  114 {  115     //方式 键盘操作  116     //getch  读取键盘中的一个字符 conio.h  117     //kbhit  conio.h  检测当前是否有键盘消息  118     //dir di;  //枚举变量  119     switch (getch())  //判断键盘消息  120     {  121     case 'w':  122     case 'w'://往上  123         for (int j = 0; j < 4; ++j)  //四列  124         {  125             for (int i = 0; i < 3; ++i)  //判断前三个能否和后面的合并  126             {  127                 if (map[i][j] == 0) //判断是否为0  128                 {  129                     //到后面找一个不是0的元素 换过来  130                     int k = i + 1;  131                     for (; k < 4; ++k)  132                     {  133                         if (map[k][j] != 0)  134                         {  135                             map[i][j] = map[k][j];  136                             map[k][j] = 0;  137                             break;  138                         }  139                     }  140                     if (k == 4)break;  //表明这一行全是0  141                 }  142                 //判断map[i][j]和后面的元素是否可以合并  143                 for (int k = i + 1; k < 4; ++k)  //判断后面的元素  144                 {  145                     if (map[k][j] == 0) continue;  146                     else if (map[i][j] == map[k][j])  147                     {  148                         //相同 合并  149                         map[i][j] *= 2;  //合并  150                         map[k][j] = 0;  151                         break;  152                     }  153                     else break;  //不相等 往后找 退出  154                 }  155             }  156         }  157         newnum(map);  158         break;  159     case 's':  160     case 's'://往下  161         for (int j = 0; j < 4; ++j)//四列  162         {  163             //每一行进行合并  164             for (int i = 3; i >0; --i)//判断前三个能否和后面的进行合并  165             {  166                 if (map[i][j] == 0)//判断map[i][j]是否为0  167                 {  168                     //到后面找一个不是0的元素 换到这个位置  169                     int k = i - 1;  170                     for (; k >= 0; --k)  171                     {  172                         if (map[k][j] != 0)  173                         {  174                             map[i][j] = map[k][j];  175                             map[k][j] = 0;  176                             break;  177                         }  178                     }  179                     if (k == 0)break;//表明这一行全是0  直接找下一行  180                 }  181                 //判断map[i][j] 和后面的元素能否合并  182                 for (int k = i - 1; k >= 0; --k)//判断后面的几个元素  183                 {  184                     if (map[k][j] == 0) continue;  185                     else if (map[i][j] == map[k][j])  186                     {  187                         map[i][j] *= 2;//合并  188                         map[k][j] = 0;  189                         break;  190                     }  191                     else  break;//不相等 往后找 退出  192                 }  193             }  194         }  195         newnum(map);  196         break;  197     case 'a':    198     case 'a'://往左  199         for (int i = 0; i < 4; ++i)  //四行  200         {  201             //每一行进行合并 从左往右 1、判断第一个元素是不是0,如果是0,就到右边找到第一个不是0的元素,放到为0的位置上 不是0,就进行下一步,(没有找到 说明全是0,那么就直接下一行)  202             //2、找到剩下的位置中不是0的元素 如果和这个位置的相同的话合并到下一个位置  203             for (int j = 0; j < 3; ++j)  //判断前三个能否和后面的合并  204             {  205                 if (map[i][j] == 0) //判断是否为0  206                 {  207                     //到后面找一个不是0的元素 换过来  208                     int k = j + 1;  209                     for (; k < 4; ++k)  210                     {  211                         if (map[i][k] != 0)  212                         {  213                             map[i][j] = map[i][k];  214                             map[i][k] = 0;  215                             break;  216                         }  217                     }  218                     if (k == 4)break;  //表明这一行全是0  219                 }  220                 //判断map[i][j]和后面的元素是否可以合并  221                 for (int k = j + 1; k < 4; ++k)  //判断后面的元素  222                 {  223                     if (map[i][k] == 0) continue;    224                     else if (map[i][j] == map[i][k])  225                     {  226                         //相同 合并  227                         map[i][j] *= 2;  //合并  228                         map[i][k] = 0;  229                         break;  230                     }  231                     else break;  //不相等 往后找 退出  232                 }  233             }  234         }  235         newnum(map);  236         break;  237     case 'd':    238     case 'd'://往右  239         for (int i = 0; i < 4; ++i) //四行  240         {  241             for (int j = 3; j >0; --j)  //判断前三个能否和后面的合并  242             {  243                 if (map[i][j] == 0) //判断是否为0  244                 {  245                     //到后面找一个不是0的元素 换过来  246                     int k = j - 1;  247                     for (; k >=0; --k)  248                     {  249                         if (map[i][k] != 0)  250                         {  251                             map[i][j] = map[i][k];  252                             map[i][k] = 0;  253                             break;  254                         }  255                     }  256                     if (k == -1)break;  //表明这一行全是0  257                 }  258                 //判断map[i][j]和后面的元素是否可以合并  259                 for (int k = j - 1; k >=0; --k)  //判断后面的元素  260                 {  261                     if (map[i][k] == 0) continue;  262                     else if (map[i][j] == map[i][k])  263                     {  264                         //相同 合并  265                         map[i][j] *= 2;  //合并  266                         map[i][k] = 0;  267                         break;  268                     }  269                     else break;  //不相等 往后找 退出  270                 }  271             }  272         }  273         newnum(map);  274         break;  275     case 224:  //表示使用方向键  方向键是组合件 用getch视为两个部分  276         switch (getch())  277         {  278         case up:  279             for (int j = 0; j < 4; ++j)//四列  280             {  281                 //每一行进行合并  282                 for (int i = 0; i < 3; ++i)//判断前三个能否和后面的进行合并  283                 {  284                     if (map[i][j] == 0)//判断map[i][j]是否为0  285                     {  286                         //到后面找一个不是0的元素 换到这个位置  287                         int k = i + 1;  288                         for (; k<4; ++k)  289                         {  290                             if (map[k][j] != 0)  291                             {  292                                 map[i][j] = map[k][j];  293                                 map[k][j] = 0;  294                                 break;  295                             }  296                         }  297                         if (k == 4)break;//表明这一行全是0  直接找下一行  298                     }  299                     //判断map[i][j] 和后面的元素能否合并  300                     for (int k = i + 1; k < 4; ++k)//判断后面的几个元素  301                     {  302                         if (map[k][j] == 0) continue;  303                         else if (map[i][j] == map[k][j])  304                         {  305                             map[i][j] *= 2;//合并  306                             map[k][j] = 0;  307                             break;  308                         }  309                         else  break;//不相等 往后找 退出  310                     }  311                 }  312             }  313             newnum(map);  314             break;  315         case down:  316             for (int j = 0; j < 4; ++j)//四列  317             {  318                 //每一行进行合并  319                 for (int i = 3; i >0; --i)//判断前三个能否和后面的进行合并  320                 {  321                     if (map[i][j] == 0)//判断map[i][j]是否为0  322                     {  323                         //到后面找一个不是0的元素 换到这个位置  324                         int k = i - 1;  325                         for (; k >= 0; --k)  326                         {  327                             if (map[k][j] != 0)  328                             {  329                                 map[i][j] = map[k][j];  330                                 map[k][j] = 0;  331                                 break;  332                             }  333                         }  334                         if (k == 0)break;//表明这一行全是0  直接找下一行  335                     }  336                     //判断map[i][j] 和后面的元素能否合并  337                     for (int k = i - 1; k >= 0; --k)//判断后面的几个元素  338                     {  339                         if (map[k][j] == 0) continue;  340                         else if (map[i][j] == map[k][j])  341                         {  342                             map[i][j] *= 2;//合并  343                             map[k][j] = 0;  344                             break;  345                         }  346                         else  break;//不相等 往后找 退出  347                     }  348                 }  349             }  350             newnum(map);  351             break;  352         case left:  353             for (int i = 0; i < 4; ++i)//四行  354             {  355                 //每一行进行合并  356                 for (int j = 0; j < 3; ++j)//判断前三个能否和后面的进行合并  357                 {  358                     if (map[i][j] == 0)//判断map[i][j]是否为0  359                     {  360                         //到后面找一个不是0的元素 换到这个位置  361                         int k = j + 1;  362                         for (; k<4; ++k)  363                         {  364                             if (map[i][k] != 0)  365                             {  366                                 map[i][j] = map[i][k];  367                                 map[i][k] = 0;  368                                 break;  369                             }  370                         }  371                         if (k == 4)break;//表明这一行全是0  直接找下一行  372                     }  373                     //判断map[i][j] 和后面的元素能否合并  374                     for (int k = j + 1; k < 4; ++k)//判断后面的几个元素  375                     {  376                         if (map[i][k] == 0) continue;  377                         else if (map[i][j] == map[i][k])  378                         {  379                             map[i][j] *= 2;//合并  380                             map[i][k] = 0;  381                             break;  382                         }  383                         else  break;//不相等 往后找 退出  384                     }  385                 }  386             }  387             newnum(map);  388             break;  389         case right:  390             for (int i = 0; i < 4; ++i)//四行  391             {  392                 //每一行进行合并  393                 for (int j = 3; j >0; --j)//判断前三个能否和后面的进行合并  394                 {  395                     if (map[i][j] == 0)//判断map[i][j]是否为0  396                     {  397                         //到后面找一个不是0的元素 换到这个位置  398                         int k = j - 1;  399                         for (; k >= 0; --k)  400                         {  401                             if (map[i][k] != 0)  402                             {  403                                 map[i][j] = map[i][k];  404                                 map[i][k] = 0;  405                                 break;  406                             }  407                         }  408                         if (k == -1)break;//表明这一行全是0  直接找下一行  409                     }  410                     //判断map[i][j] 和后面的元素能否合并  411                     for (int k = j - 1; k >= 0; --k)//判断后面的几个元素  412                     {  413                         if (map[i][k] == 0) continue;  414                         else if (map[i][j] == map[i][k])  415                         {  416                             map[i][j] *= 2;//合并  417                             map[i][k] = 0;  418                             break;  419                         }  420                         else  break;//不相等 往后找 退出  421                     }  422                 }  423             }  424             newnum(map);  425             break;  426         default:  427             break;  428         }  429         break;  430     default:  431         break;  432     }  433   434 }  435   436 //打印  贴图  437 void drawmap(int map[][4])  438 {  439     /*for (int i = 0; i < 4; ++i)  440     {  441         for (int j = 0; j < 4; ++j)  442         {  443             printf("%dt", map[i][j]);  444         }  445         printf("n");  446     }  447     printf("nn");*/  448   449     //cleardevice();//图形库清除屏幕内容  //如果加上 有闪屏的问题  450     putimage(0, 0, &img);//贴背景图  451     char arr[10];//准备字符串  452     for (int i = 0; i < 4; ++i)  453     {  454         for (int j = 0; j < 4; ++j)  455         {  456             //加数字进来  457             //outtextxy根据坐标输出字符串  458             //itoa 将int转换成字符串  459             /*if (map[i][j] != 0)  460             {  461             sprintf(arr,"%d",map[i][j]);  462             outtextxy(160 * j+20, 160 * i+20, arr);  463             }*/  464   465             //有素材  switch 根据不同数字进行贴图  466             //通过数字确定背景  467             //238 106 80  468             //238 169 184  469             //131 139 131  470             //193 205 205  471   472             /*switch (map[i][j])  473             {  474             case 0:  475             case 32:  476             setfillcolor(color1);  477             fillrectangle(160 * j, 160 * i, 160 * j + 160, 160 * i + 160);  478             break;  479             case 2:  480             case 64:  481             setfillcolor(color2);  482             fillrectangle(160 * j, 160 * i, 160 * j + 160, 160 * i + 160);  483             break;  484             case 4:  485             case 128:  486             setfillcolor(color3);  487             fillrectangle(160 * j, 160 * i, 160 * j + 160, 160 * i + 160);  488             break;  489             case 8:  490             case 256:  491             setfillcolor(color4);  492             fillrectangle(160 * j, 160 * i, 160 * j + 160, 160 * i + 160);  493             break;  494             }*/  495   496             sprintf(arr, "%d", map[i][j]);  497             outtextxy(160 * j + 20, 160 * i + 20, arr[10]);  498             //根据数字 确定不同的背景图  然后在背景图上 写数字  499             //if ()  500             //2^1  2^2  2^3 2^4  501             //2^5  2^6  502   503             //debug 调试版本  比较慢  504             //release 发行版本   -->主要发给别人用的  505         }  506     }  507 }  508   509 //随机一个新元素  510 void newnum(int map[][4])  511 {  512     //判断是不是满  513     int empty = 0;  514     for (int i = 0; i < 4; ++i)  515     {  516         for (int j = 0; j < 4; ++j)  517         {  518             if (map[i][j] == 0) empty = 1;  519         }  520         if (empty == 1) break;//如果找到这个空的位置  不需要继续循环  521     }  522     if (empty == 0) return;  523   524     int x, y;  525     do  526     {  527         x = rand() % 4;  528         y = rand() % 4;  529     } while (map[x][y] != 0);  530     map[x][y] = rand() % 2 * 2 + 2;  //随机2和4  531     //如果地图满的话 我们不能随机元素 所以最后 加上一个判断地图满的函数  532 }  533   534 //判断游戏是否结束  535 int isgameover(int map[][4])  536 {  537     //赢  返回1    输 -1  还没赢 还没输 返回0  538     //游戏输赢条件  539     //出现2048  游戏赢  540     //如果游戏不能走动  游戏输掉  541     int empty = 0;//如果判断的时候 map[i][j]==0  empty置为1    542     //如果有相邻元素 并且相同的话  也将empty置为1  543     for (int i = 0; i < 4; ++i)  544     {  545         for (int j = 0; j < 4; ++j)  546         {  547             if (map[i][j] >= 2048)//赢的条件  548             {  549                 //赢得游戏  550                 return 1;  551             }  552         }  553     }  554     //条件1  数字全满 并且 相邻没有同样的数字  555     for (int i = 0; i < 4; ++i)  556     {  557         for (int j = 0; j < 4; ++j)  558         {  559             if (map[i][j] == 0)  empty = 1;  560             if (i + 1<4 && map[i][j] == map[i + 1][j]) empty = 1;  561             if (j + 1<4 && map[i][j] == map[i][j + 1]) empty = 1;  562         }  563     }  564     if (empty == 1)  565     {  566         //游戏还没有结束  567         return 0;  568     }  569     else  570     {  571         //游戏结束 //输  572         return -1;  573     }  574 }

结果展示:

C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

 

注:代码部分仅供学习参考,完全复制下来不一定能够实现

 

 

2019-04-03  12:04:42

 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/604413.html

(0)
上一篇 2021年5月12日
下一篇 2021年5月12日

精彩推荐