1.前言
刚学完c++基础,找个项目练练手,于是上牛客网找了个2048练练手,文章最后给出源码
2.简介
- 一次只能合并相邻的两个数字,例如 [2 2 2 2] ,向右合并以后是 [空 空 4 4] ,不是 [空 空 空 8]
- 每次合并的时候,合并方向优先级高,例如 [空 2 2 2],向右合并以后是 [空 空 2 4],不是 [空 空 4 2]
- 判断游戏结束
- 每次合并以后随机新出4的概率10%
3.项目思路
- 用一个4*4的int数组来储存数据,初始化为0
- 用户上下左右移的操作可整体简化为3个步骤
- 1)将非0元素紧凑
- 2)合并同类项
- 3)再将非0元素紧凑
4.示例
2 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
此时执行上移操作,步骤如下
1)紧凑
2 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
2)上移合并同类项
4 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
3)紧凑
4 | 0 | 0 | 0 |
8 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
5.bug
因为楼主在随机位置生成随机数的代码如下
//生成随机数
int randomNum(){
int num=rand()%10;
return num>8?4:2;
}
//para num->用户想生成[0,num]间随机数
inline void random(int num){
srand((unsigned int)(time(NULL)));
a=rand()%num;
Sleep(100);
b=rand()%num;
}
//生成1个随机位置并赋值
void randomAddress(){
//随着4*4数组中非0个数增加 可能出现卡顿 带优化
while(map[a][b]!=0){
random(3);
}
int num=randomNum();
map[a][b]=num;
cout<<"row:"<<a<<" column"<<b<<" "<<map[a][b]<<endl;
}
当数组中非0元素个数增多时,在随机位置生成随机数所耗费的时间也不断增加
6.源码
#include <iostream>
#include <ctime>
#include<windows.h>
using namespace std;
void print();//打印当前状态
int randomNum();//生成2个随机数(其中一个必为2,另一个 2:4出现的比例=4:1)
void randomAddress();//生成2个随机位置
inline void random(int);//生成随机数[0,num),以便上述2个函数使用
void up();
void down();
void left();
void right();
bool isEnd();//判断游戏是否结束
int map[4][4]={0,};
int a=0,b=0;//两个用来储存随机数的值
void print(){
cout << "************************************************" << endl;
cout << "* " << map[0][0] << " " << map[0][1] << " " << map[0][2] << " " << map[0][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "* " << map[1][0] << " " << map[1][1] << " " << map[1][2] << " " << map[1][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "* " << map[2][0] << " " << map[2][1] << " " << map[2][2] << " " << map[2][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "* " << map[3][0] << " " << map[3][1] << " " << map[3][2] << " " << map[3][3] << " *" << endl;
cout << "************************************************" << endl;
cout << "操作详情:(输入后,按回车键结束)" << endl;
cout << "w : 向上移动 s : 向下移动" << endl;
cout << "a : 向左移动 r : 向右移动" << endl;
cout << "q : 退出" << endl;
}
//para num->用户想生成[0,num]间随机数
inline void random(int num){
srand((unsigned int)(time(NULL)));
a=rand()%num;
Sleep(100);
b=rand()%num;
}
//生成随机数
int randomNum(){
int num=rand()%10;
return num>8?4:2;
}
//判断游戏是否结束 结束条件:1.4x4数组中非0元素已满 2.出现2048
bool isEnd(){
for(int a=0;a<4;a++){
for(int b=0;b<4;b++){
if(map[a][b]==2048)return true;
if(map[a][b]==0)return false;
}
}
return true;
}
//生成1个随机位置并赋值
void randomAddress(){
//随着4*4数组中非0个数增加 可能出现卡顿 带优化
while(map[a][b]!=0){
random(3);
}
int num=randomNum();
map[a][b]=num;
cout<<"row:"<<a<<" column"<<b<<" "<<map[a][b]<<endl;
}
//用户点击上移操作
void up(){
int row,column;
//1.将非0元素上移
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(row!=0&&map[row][column]!=0&&map[row-1][column]==0){
map[row-1][column]=map[row][column];
map[row][column]=0;
row--;
}
}
}
//2.相同元素合并 循环遍历每一个元素
for(row=1;row<4;row++){
for(column=0;column<4;column++){
if(map[row][column]==0)continue;
else if(map[row][column]!=map[row-1][column]){
continue;
}else{
map[row-1][column]*=2;
map[row][column]=0;
}
}
}
//3.将合并后非0元素上移
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(row!=0&&map[row][column]!=0&&map[row-1][column]==0){
map[row-1][column]=map[row][column];
map[row][column]=0;
row--;
}
}
}
randomAddress();
}
//用户点击下移操作
void down(){
int row,column;
//1.将非0元素下移
for(row=3;row>=0;row--){
for(column=0;column<4;column++){
while(row!=3&&map[row][column]!=0&&map[row+1][column]==0){
map[row+1][column]=map[row][column];
map[row][column]=0;
row++;
}
}
}
//2.合并同类项
for(row=2;row>=0;row--){
for(column=0;column<4;column++){
if(map[row][column]==0)continue;
else if(map[row][column]!=map[row+1][column]){
continue;
}else{
map[row+1][column]*=2;
map[row][column]=0;
}
}
}
//3.合并后非0
for(row=3;row>=0;row--){
for(column=0;column<4;column++){
while(row!=3&&map[row][column]!=0&&map[row+1][column]==0){
map[row+1][column]=map[row][column];
map[row][column]=0;
row++;
}
}
}
randomAddress();
}
//用户点击左移操作
void left(){
int row,column;
//1.将非0元素左移
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(column!=0&&map[row][column]!=0&&map[row][column-1]==0){
map[row][column-1]=map[row][column];
map[row][column]=0;
column--;
}
}
}
//2.合并元素
for(row=0;row<4;row++){
for(column=1;column<4;column++){
if(map[row][column]==0)continue;
else if(map[row][column]!=map[row][column-1])continue;
map[row][column]=0;
map[row][column-1]*=2;
}
}
//3.
for(row=0;row<4;row++){
for(column=0;column<4;column++){
while(column!=0&&map[row][column]!=0&&map[row][column-1]==0){
map[row][column-1]=map[row][column];
map[row][column]=0;
column--;
}
}
}
randomAddress();
}
void right(){
int row,column;
//1.
for(row=0;row<4;row++){
for(column=3;column>=0;column--){
while(column!=3&&map[row][column]!=0&&map[row][column+1]==0){
map[row][column+1]=map[row][column];
map[row][column]=0;
column++;
}
}
}
//2.右移合并同类项
for(row=0;row<4;row++){
for(column=2;column>=0;column--){
if(map[row][column]==0||map[row][column]!=map[row][column+1])continue;
else{
map[row][column+1]*=2;
map[row][column]=0;
}
}
}
//3.
for(row=0;row<4;row++){
for(column=3;column>=0;column--){
while(column!=3&&map[row][column]!=0&&map[row][column+1]==0){
map[row][column+1]=map[row][column];
map[row][column]=0;
column++;
}
}
}
randomAddress();
}
int main(){
char control;
//数据初始化
randomAddress();
randomAddress();
print();
while(cin>>control){
switch(control){
case 'w':up();break;
case 's':down();break;
case 'a':left();break;
case 'd':right();break;
case 'q':return 0;
}
print();//将移动后元素打印
if(isEnd()){
cout<<"游戏已结束"<<endl;
return 0;
}
}
return 0;
}