Advertisement

c++小项目:2048小游戏

阅读量:

使用c++语言,实现在控制界面进行的2048小游戏

练习使用ncurses库显示界面,vector模板作为容器存储数组

游戏效果图如下:

按键w,s,a,d作为操作,按q键结束比赛

失败情况提示

程序由一下几个函数构成,随机初始化函数,随机增加数字函数,屏幕刷新函数,执行操作函数,主函数

1.声明使用的库和定义函数

复制代码
 #include <ncurses.h>

    
 #include <iostream>
    
 #include <vector>
    
 #include <ctime>
    
 #include <cstdlib>
    
  
    
 using namespace std;
    
  
    
 enum key {kup, kdown, kleft, kright};
    
 void trans_coor(int i, int j, int& x, int& y, int& z, key k);
    
 bool add_item(vector< vector<int> >& v);
    
 void easy_display();
    
 void refresh_screen(const vector< vector<int> >& v);
    
 void perform(vector< vector<int> > & v, key k);
    
 vector< vector<int> > initial_checkerboard(void);
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/NyPfpMjVZaXQKiT7usA03IxelqCJ.png)

2.随机初始化函数

srand()设置随机数的种子;

rand()随机生成数字;

使用ncurses库中的函数:

mvprintw(x, y, string)

x,y是要显示的起始位置,string是要显示的字符串;

复制代码
 vector< vector<int> > initial_checkerboard(void)

    
 {
    
   //初始化vector,使用vector模板容器存储棋盘
    
   vector< vector <int> > arr(4, vector<int>(4));
    
   //随机初始化随机种子,time(0)根据时间作为种子
    
   srand(time(0));
    
   //随机初始化坐标
    
   int x1 = rand() % 4;
    
   int y1  = rand() % 4;
    
    
    
   int x2 = rand() % 4;
    
   int y2 = rand() % 4;
    
   //判断坐标是否重叠
    
   while(x1 == x2 && y1 == y2)
    
   {
    
     x2 = rand() %4;
    
     y2 = rand() %4;
    
   }
    
   arr[x1][y1] = 2;
    
   arr[x2][y2] = 2;
    
   return arr;
    
 }
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/iSQVaLBzChx2JeyGwIZ4XOR1oq5F.png)

3.随机增加棋盘中棋子(数字2)

复制代码
 bool add_item(vector< vector<int> >& v)

    
 {
    
   //判断游戏是否结束的变量,true为游戏继续,false为游戏结束
    
   bool keep = false;
    
   int i,j=0;
    
   //检查游戏是否结束
    
   for(i=0;i<4;i++)
    
     for(j=0;j<4;j++)
    
       if(v[i][j] ==0)
    
     keep=true;
    
   if(keep == false)
    
     return keep; 
    
   srand(time(0));
    
   
    
   int x = rand() % 4;
    
   int y = rand() % 4;
    
   //随机初始化增加数字的位置,直到此位置没有棋子为止
    
   while(v[x][y] != 0)
    
   {
    
     x = rand() %4;
    
     y = rand() %4;
    
   }
    
   v[x][y] = 2;
    
   return keep;
    
 }
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/gVvCnDpMEOmZPXwxzFaeBoqfUN8H.png)

4.刷新屏幕

要完整地显示数字的每一位

使用ncurses库中的函数:

refresh()刷新屏幕,只有使用这个函数后,之前的操作才能在屏幕上显示

复制代码
 void refresh_screen(const vector< vector<int> >& v)

    
 {
    
   int i,j,k,q=0;
    
   int int_n[4]={0,0,0,0};
    
   char n[]="0\0";
    
   clear();
    
   //分离数字的每一位,存入数组中
    
   for(i=0;i<4;i++)
    
   {
    
     for(j=0;j<4;j++)
    
     {
    
       for(q=0;q<4;q++)
    
     int_n[q]=0;
    
       k = v[i][j];
    
       if(k/1000!=0)
    
     int_n[0]=k/1000;
    
       if((k%1000)/100!=0)
    
     int_n[1]=(k%1000)/100;
    
       if((k%100)/10!=0)
    
     int_n[2]=(k%100)/10;
    
       if(k%10!=0)
    
     int_n[3]=k%10;
    
       mvprintw(i*2, j*5, "|");
    
       k=0;
    
       //正确显示数字(23显示23而不是0023)
    
       for(q=0;q<4;q++)
    
       {
    
     if(k==0)
    
     {
    
       if(int_n[q]==0)
    
         continue;
    
     }
    
     k=1;
    
     #显示每一位数字字符,0x30是asii码中'0'的位置
    
     n[0]=0x30+int_n[q];
    
     mvprintw(i*2, j*5+q+1, n);
    
       }
    
     }
    
     mvprintw(i*2,20, "|");
    
   }
    
   refresh();
    
 }
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/X21rCQNKFpvetS5qE7iTAymcdlGg.png)

5.执行操作

复制代码
 void perform(vector< vector<int> > & v, key k)

    
 {
    
   int i,j,q,p=0;
    
   int x,y,z=0;
    
     for(i=0;i<4;i++)
    
     {
    
       //清空空(0)的位置,把数字按执行要求移动一侧
    
       for(p=0;p<3;p++)
    
       {
    
       for(j=0;j<3;j++)
    
       {
    
     //根据不同操作命令,改变循环的次序
    
     trans_coor(i, j, x, y, z, k);
    
     if(v[x][y] == 0)
    
     {
    
       if(k==kup || k==kdown)
    
       {
    
         q = v[x+z][y];
    
         v[x+z][y]=0;
    
       }
    
       else
    
       {
    
         q = v[x][y+z];
    
         v[x][y+z]=0;
    
       }
    
       v[x][y] = q;
    
     }
    
       }
    
       }
    
       //进行相邻相同数字相加的操作
    
       for(j=0;j<3;j++)
    
       {
    
     trans_coor(i, j, x, y, z, k);
    
     if(k==kup || k==kdown)
    
     {
    
       q = v[x+z][y];
    
       if(v[x][y]==q)
    
       { 
    
         v[x+z][y]=0;
    
         v[x][y]=2*q;
    
       }
    
     }
    
     else
    
     { 
    
       q = v[x][y+z];
    
       if(v[x][y]==q)
    
       { 
    
         v[x][y+z]=0;
    
         v[x][y]=2*q;
    
       }
    
     }
    
       }
    
       //在执行一次去空位置操作
    
       for(j=0;j<3;j++)
    
       {
    
     trans_coor(i, j, x, y, z, k);
    
     if(v[x][y] == 0)
    
     {
    
       if(k==kup || k==kdown)
    
       {
    
         q = v[x+z][y];
    
         v[x+z][y]=0;
    
       }
    
       else
    
       {
    
         q = v[x][y+z];
    
         v[x][y+z]=0;
    
       }
    
       v[x][y] = q;
    
     }
    
       }
    
     }
    
 }
    
  
    
 //根据不同操作命令,改变循环的次序
    
 //当上操作,x=j,y=i;左操作反之
    
 //当下操作,x=3-j,y=i;右操作,x=i,y=3-j,即下和右都是逆序遍历vector需要改变的那一维数组
    
 //当上或右操作,k=1否则k=-1
    
 void trans_coor(int i, int j, int& x, int& y, int& z, key k)
    
 {
    
   if(k==kup)
    
   {
    
      x=j;
    
      y=i;
    
      z=1;
    
   }
    
   else if(k==kdown)
    
   {
    
      x=3-j;
    
      y=i;
    
      z=-1;
    
   }
    
   else if(k==kleft)
    
   {
    
      x=i;
    
      y=j;
    
      z=1;
    
   }
    
   else if(k==kright)
    
   {
    
      x=i;
    
      y=3-j;
    
      z=-1;
    
   }
    
 }
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/301HLGqnzVwBc5dEevJmWaboPfpQ.png)

6.主函数

复制代码
 int main()

    
 {
    
   char c;
    
   //初始化屏幕
    
   initscr();
    
   vector <vector <int> > arr(4, vector<int>(4));
    
   arr = initial_checkerboard();
    
   //关闭显示光标
    
   curs_set(FALSE);
    
   //清空屏幕
    
   clear();
    
   //显示初始棋盘
    
   refresh_screen(arr);
    
   bool keep = true;
    
   key k=kup;
    
   while(1)
    
   {
    
     //获取操作指令,w=向上,s=向下,a=向左,d=向右
    
     //q=退出
    
     c = getchar();
    
     if(c=='w')
    
       k=kup;
    
     else if(c=='s')
    
       k=kdown;
    
     else if(c=='a')
    
       k=kleft;
    
     else if(c=='d')
    
       k=kright;
    
     else if(c=='q')
    
       break;
    
     //当输入非正确按键时,提示操作方法,并不进行操作
    
     else
    
       {
    
     mvprintw(12, 12, "You must press 'w' or 's' or 'a' or 'd' or press 'q' to quit");
    
     refresh();
    
     continue;
    
       }
    
     //执行操作并刷新显示
    
     perform(arr, k);
    
     keep = add_item(arr);
    
     refresh_screen(arr);
    
     if(keep == false)
    
       break;
    
   }
    
   //游戏结束
    
   refresh_screen(arr);
    
   mvprintw(12, 12, "You are failure!");
    
   mvprintw(14, 14, "Please press 'q' to quit!");
    
   refresh();
    
   while(getchar() != 'q');
    
   //关闭显示界面
    
   endwin();
    
   return 0;
    
 }
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/YePrfXy1qNOCzBVSaLM9sioK27WQ.png)

全部评论 (0)

还没有任何评论哟~