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

时间:2022-12-15 14:22:08

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

前几天由于忙着过年串门,游戏机的计划搁置了几天。这两天终于空出了一块时间,抽空写了2048。

由于笔者前面自制了一个类似2048的游戏,所以写起来也算是轻车熟路,花了两个晚上也就差不多了。

废话少说,先将代码copy一份过来!

后续这几天,笔者想先写一个拼图小游戏,然后想办法将这几个游戏*同存在的全屏刷新闪屏的问题给解决了。

另外,整个程序代码均为笔者原创,引用或转载请注明出处!

 /**--------------------------------------------------------------**/
/**名称:大大维的2048v1 日期:2017/2/1**/
/**描述:简单地实现了2048的基本功能 **/
/**存在的问题:由于使用了全局刷新,游戏运行中会出现闪屏现象;
不能够存储玩家的游戏记录;由于不是图形化界面,用户界面较丑;
不能改变游戏的地图大小 **/
/**笔者会在后续版本逐步完善这些问题!!! **/
/**-------------------------------------------------------------**/
/**申明: 1.本程序由大大维独自编写,转载、引用请注明出处
2.本程序注释掉的部分,笔者认为理论上可以替代后续的代码,
但存在错误。笔者未发现错误原因,如有高手发现,请联系笔者
3.程序中若存在BUG请联系笔者
4.笔者联系方式 1329423134@qq.com **/
/**-------------------------------------------------------------**/
#include<iostream>
#include<string>
#include<vector>
#include<ctime>
#include<cstdlib>
#include<conio.h>
using namespace std;
constexpr unsigned HIGH=;
constexpr unsigned LENG=;
///当前地图状态:READY,即(),可以进行moveAndAddData()操作;WAIT,即[],可以进行chooseMapSpace()操作
enum state {READY,WAIT};
///当前操作块的移动方向:UP,上;DOWN,下;LEFT,左;RIGHT,右;DEFAULT,其他
enum dir {UP,DOWN,LEFT,RIGHT,DEFAULT};
class Map2048
{
public:
Map2048();///构造函数,初始化数据
void moveAndAddData();///移动和相加选中块的数据
///地图压缩
void mapSortToUp();
void mapSortToDown();
void mapSortToLeft();
void mapSortToRight();
void dataCreate(unsigned persentOf2);///生成新data
bool isLive();///是否存活判断
void printMap();///地图打印
dir setDir();///输入操作块的移动方向
string dataToPrintData(int n);///data到printData的转换函数
unsigned getScore();
private:
unsigned data[HIGH][LENG];///设要显示数据为x,data=log2(x),空白时,data=0
string printData[HIGH][LENG];///存储规范化的输出数据
unsigned score;
}; Map2048::Map2048()
{
for(int i=; i<HIGH; i++)
for(int j=; j<LENG; j++)
{
data[i][j]=;
}
for(int i=; i<HIGH; i++)
for(int j=; j<LENG; j++)
printData[i][j]=dataToPrintData(data[i][j]);
bool initFlag=true;
while(initFlag)
{
srand((unsigned)time(NULL));
int x1=rand()%HIGH,y1=rand()%LENG,x2=rand()%HIGH,y2=rand()%LENG;
if(x1!=x2&&y1!=y2)
{
initFlag=false;
data[x1][y1]=data[x2][y2]=;
printData[x1][y1]=dataToPrintData(data[x1][y1]);
printData[x2][y2]=dataToPrintData(data[x2][y2]);
}
}
score=;
} void Map2048::moveAndAddData()
{
dir DIR=setDir();
switch(DIR)
{
case UP:
{
mapSortToUp();
for(int n=; n<LENG; n++)
for(int m=; m<HIGH; m++)
if(data[m][n]==data[m-][n])
{
data[m-][n]*=;
data[m][n]=;
printData[m-][n]=dataToPrintData(data[m-][n]);
printData[m][n]=dataToPrintData(data[m][n]);
score+=data[m-][n];
}
mapSortToUp();
break;
}
case DOWN:
{
mapSortToDown();
for(int n=; n<LENG; n++)
for(int m=HIGH-; m>=; m--)
if(data[m][n]==data[m+][n])
{
data[m+][n]*=;
data[m][n]=;
printData[m+][n]=dataToPrintData(data[m+][n]);
printData[m][n]=dataToPrintData(data[m][n]);
score+=data[m+][n];
}
mapSortToDown();
break;
}
case LEFT:
{
mapSortToLeft();
for(int m=; m<HIGH; m++)
for(int n=; n<LENG; n++)
if(data[m][n]==data[m][n-])
{
data[m][n-]*=;
data[m][n]=;
printData[m][n-]=dataToPrintData(data[m][n-]);
printData[m][n]=dataToPrintData(data[m][n]);
score+=data[m][n-];
}
mapSortToLeft();
break;
}
case RIGHT:
{
mapSortToRight();
for(int m=; m<HIGH; m++)
for(int n=LENG-; n>=; n--)
if(data[m][n]==data[m][n+])
{
data[m][n+]*=;
data[m][n]=;
printData[m][n+]=dataToPrintData(data[m][n+]);
printData[m][n]=dataToPrintData(data[m][n]);
score+=data[m][n+];
}
mapSortToRight();
break;
}
case DEFAULT:
break;
}
} void Map2048::mapSortToUp()///地图向上压缩
{
for(int n=; n<LENG; n++)
for(int m=; m<HIGH; m++)
if(data[m][n]==)
for(int k=m; k<HIGH; k++)
if(data[k][n]!=)
{
data[m][n]=data[k][n];
data[k][n]=;
printData[m][n]=dataToPrintData(data[m][n]);
printData[k][n]=dataToPrintData(data[k][n]);
break;
}
} void Map2048::mapSortToDown()///地图向下压缩
{
for(int n=LENG-; n>=; n--)
for(int m=HIGH-; m>=; m--)
if(data[m][n]==)
for(int k=m; k>=; k--)
if(data[k][n]!=)
{
data[m][n]=data[k][n];
data[k][n]=;
printData[m][n]=dataToPrintData(data[m][n]);
printData[k][n]=dataToPrintData(data[k][n]);
break;
}
} void Map2048::mapSortToLeft()///地图向左压缩
{
for(int m=; m<HIGH; m++)
for(int n=; n<LENG; n++)
if(data[m][n]==)
for(int k=n; k<LENG; k++)
if(data[m][k]!=)
{
data[m][n]=data[m][k];
data[m][k]=;
printData[m][n]=dataToPrintData(data[m][n]);
printData[m][k]=dataToPrintData(data[m][k]);
break;
}
} void Map2048::mapSortToRight()///地图向右压缩
{
for(int m=HIGH-; m>=; m--)
for(int n=LENG-; n>=; n--)
if(data[m][n]==)
for(int k=n; k>=; k--)
if(data[m][k]!=)
{
data[m][n]=data[m][k];
data[m][k]=;
printData[m][n]=dataToPrintData(data[m][n]);
printData[m][k]=dataToPrintData(data[m][k]);
break;
}
} void Map2048::dataCreate(unsigned persentOf2)
{
vector<int> dataVecX;///加入一个矢量,记录空位置的x坐标
vector<int> dataVecY;///加入一个矢量,记录空位置的y坐标
for(int i=; i<HIGH; i++)
for(int j=; j<LENG; j++)
{
if(data[i][j]==)
{
dataVecX.push_back(i);
dataVecY.push_back(j);
}
}
if(!dataVecX.empty())
{
srand((unsigned)time(NULL));
auto k=rand()%dataVecX.size();///在空位中随机选择一个位置
if(rand()%<persentOf2)///根据2,4生成的比例随机生成新数据
data[dataVecX[k]][dataVecY[k]]=;
else
data[dataVecX[k]][dataVecY[k]]=;
printData[dataVecX[k]][dataVecY[k]]=dataToPrintData(data[dataVecX[k]][dataVecY[k]]);
}
} bool Map2048::isLive()
{
bool liveFlag=false;
for(int m=; m<HIGH; m++) ///确保没有空位置
for(int n=; n<LENG; n++)
if(data[m][n]==)
{
liveFlag=true;
return liveFlag;
}
// ///以下代码基于如下数学关系:反复使用向右,向下查询
// ///(最右行只向下,最底行只向右),可以遍历检查一遍元素自身是否与邻居相等
// for(int i=0; i<HIGH; i++)
// {
// for(int j=0; j<LENG; j++)
// {
// if(i!=HIGH-1&&j!=LENG-1)///非最右且非最下节点
// {
// if(data[i][j]==data[i][j+1]||data[i][j]==data[i+1][j])///向右,向下比较
// {
// liveFlag=true;
// return liveFlag;
// }
// }
// else if(i==HIGH-1&&j!=LENG-1)///非最右但是最下节点
// {
// if(data[i][j]=data[i][j+1])///向右比较
// {
// liveFlag=true;
// return liveFlag;
// }
// }
// else if(i!=HIGH-1&&j==LENG-1)///非最下但是最右节点
// {
// if(data[i][j]=data[i+1][j])///向下比较
// {
// liveFlag=true;
// return liveFlag;
// }
// }
// else///末尾节点,即最下且最右节点,无须比较,直接返回标志
// return liveFlag;
// }
// }
for(int m=; m<HIGH; m++) ///确保没有空位置
for(int n=; n<LENG; n++)
{
if((m==)&&(n==))
{
if(data[m][n]==data[m+][n]||data[m][n]==data[m][n+])
{
liveFlag=true;
return liveFlag;
}
}
else if((m==HIGH-)&&(n==LENG-))
{
if(data[m][n]==data[m-][n]||data[m][n]==data[m][n-])
{
liveFlag=true;
return liveFlag;
}
}
else if((m==)&&(n==LENG-))
{
if(data[m][n]==data[m+][n]||data[m][n]==data[m][n-])
{
liveFlag=true;
return liveFlag;
}
}
else if((m==HIGH-)&&(n==))
{
if(data[m][n]==data[m-][n]||data[m][n]==data[m][n+])
{
liveFlag=true;
return liveFlag;
}
}
else if((m==)&&(n!=)&&(n!=LENG-))
{
if(data[m][n]==data[m+][n]||data[m][n]==data[m][n-]||data[m][n]==data[m][n+])
{
liveFlag=true;
return liveFlag;
}
}
else if((m=HIGH-)&&(n!=)&&(n!=LENG-))
{
if(data[m][n]==data[m-][n]||data[m][n]==data[m][n-]||data[m][n]==data[m][n+])
{
liveFlag=true;
return liveFlag;
}
}
else if((n==)&&(m!=)&&(m!=HIGH-))
{
if(data[m][n]==data[m+][n]||data[m][n]==data[m-][n]||data[m][n]==data[m][n+])
{
liveFlag=true;
return liveFlag;
}
}
else if((n==LENG-)&&(m!=)&&(m!=HIGH-))
{
if(data[m][n]==data[m+][n]||data[m][n]==data[m-][n]||data[m][n]==data[m][n-])
{
liveFlag=true;
return liveFlag;
}
}
else
{
if(data[m][n]==data[m+][n]||data[m][n]==data[m-][n]||data[m][n]==data[m][n-]||data[m][n]==data[m][n+])
{
liveFlag=true;
return liveFlag;
}
}
}
} void Map2048::printMap()
{
cout<<" 2 0 4 8"<<endl;
cout<<"---------------------------------------------"<<endl;
for(int i=; i<HIGH; i++)
{
for(int j=; j<LENG; j++)
{
if(data[i][j]!=)
cout<<"| "<<printData[i][j]<<" ";
else
cout<<"| "<<" "<<" ";
}
cout<<"|"<<endl;
cout<<"---------------------------------------------"<<endl;
}
cout<<"SCORE= "<<score;
} dir Map2048::setDir()
{
char keydown=getch();///读取按键
switch(keydown)
{
case 'w':
return UP;
break;
case 'W':
return UP;
break;
case 's':
return DOWN;
break;
case 'S':
return DOWN;
break;
case 'a':
return LEFT;
break;
case 'A':
return LEFT;
break;
case 'd':
return RIGHT;
break;
case 'D':
return RIGHT;
break;
default:
return DEFAULT;
break;
}
} string Map2048::dataToPrintData(int m)
{ int count=;
///str的初始化基于如下数学关系:4*4的地图下,2048游戏能合成数,理论上最大值131072(2^17),即data最大为17
string str {m/+,(m/)%+,(m/)%+,(m/)%+,(m/)%+,m%+};
///对冗余0的处理
for(int i=; i<; i++)
{
if(str[i]=='')
{
count++;
str[i]=' ';
}
else
break;
}
switch(count)///格式调整
{
case :///不加break会在执行完第一条语句后自动执行break
{
str[]=str[];
str[]=str[];
str[]=str[];
str[]=str[];
str[]=' ';
break;
}
case :
{
str[]=str[];
str[]=str[];
str[]=str[];
str[]=' ';
break;
}
case :
{
str[]=str[];
str[]=str[];
str[]=' ';
str[]=' ';
break;
}
case :
{
str[]=str[];
str[]=' ';
break;
}
}
return str;
} unsigned Map2048::getScore()
{
return score;
} int main()
{
Map2048 map;
bool gameOverFlag=false;
map.printMap();
while(!gameOverFlag)
{
while(kbhit())
{
system("cls");
map.moveAndAddData();
map.dataCreate();///以50%为2,50%为4的规则生成新数据
map.printMap();
if(!map.isLive())
gameOverFlag=true;
}
}
cout<<endl<<"GAME OVER"<<endl;
cout<<"The Final Score Is: "<<map.getScore()<<endl;
getch();
}

老规矩,上几张游戏截图:(在codeblocks下编译)

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

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

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

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

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