C++在控制台上实现2048游戏

来源:互联网 发布:读地理地图软件 编辑:程序博客网 时间:2024/04/24 19:17
    刚学完C++基础,想找一个项目练练手,萌发写一个2048的游戏的想法,既然有想法,就是干!!自己第一次独立完成一个项目(也不是全部是独立的,开始之前参考过代码),虽然只有几百行代码,但这是一个开始,朝着自己梦想一步一个脚印。fighting!!    首先在网上找了一个2048的项目,http://www.jb51.net/article/51111.htm,用这个代码运行了一下,大概有了整体的认识,并且粗略的看了一下模块。在这个程序中,有一些bug:    ①和我们平常玩的2048不同,这个游戏生成的随机数是2的次方,我们一般只会生成2和4;    ②游戏中每一次移动后生成新数的位置是第一个空格,降低游戏的体验;    ③游戏只有两个相邻的大小相同的数才会结合,中间存在0的话,不会结合;其实是由于每次移动只会移动一格导致的;    ④游戏中含有零,看起来不舒服;    虽然有这些问题,但是这个程序给了我整体的思路,让我能够自己接下来走自己的路。

接下来是自己做项目遇到的一些问题和解决方法,最后附上自己的源代码

一、控制台如何从键盘上获得方向键    之前简单的以为方向键就是简单的ASCII码,too young too simple。  http://blog.csdn.net/feilong911hao/article/details/42081967,看完这篇博客之后弄明白。之前问过很多人,各种搜也没找到,感谢博主和万能的CSDN。      总结:①方向键有两个字节,第一个字节不是ASCII码,后面一个字节才是         ②使用getch()没有回显的从键盘输入。

代码:

//返回值//  1   上   72//  2   下   80//  3   左   75//  4   右   77int get_direction(){    char c1,c2;    int ret = 0;    c1 = getch();    if (!isascii(c1))    {        c2 = getch();        switch(c2)        {        case 72: ret = 1;break;        case 80: ret = 2;break;        case 75: ret = 3;break;        case 77: ret = 4;break;        default: break;        }    }    return ret;}
二、随机数的生成    使用srand()和rand(),srand()使用time(0)当前的时间当做随机数种子,避免伪随机数;    http://wenku.baidu.com/link?url=XkB5uCfIkKL_LyBqEoM5ueoxl29mwXtEyfAzGSwfHsgGRB3-N9eR0O0EFoElSa1-YISWXb1mevClbOLytYDhFMoJrnrkhnlxK-brQsslt4O 

代码:

//随机产生一个0-n-1的数字int rand_pro_s(int n){    srand(time(0));    int k = rand()%n;    return k;}
三、移动(难点)    将移动分为两步,第一步是合并相邻两个相同的数字(中间可以含有0);第二步,方格里面的数字全部向移动的方向移动,去除中间的零。    第一步:之前没有理清思想,只合并了相邻的两个数字,没有考虑含有0的情况。思路:遍历每一行或者列,k来存放每一个非零的数,遇见一个非零,如果和k相等,那么就将这个数变为2k,另外的数变为0.    第二步:使用一个k来作为记录非零的个数,然后遍历。

代码

void up_dir(){    //完成第一步    int i,j;    for (i=0; i<4; i++)    {        /*for (j=0; j<3;)        {            if (array[j][i] == array[j+1][i])            {                array[j][i] = array[j][i] + array[j+1][i];                array[j+1][i] = 0;                j += 2;                continue;            }            j++;        }*/        int k = 0;        int x = 0;         int y = 0;        for (j=0; j<4; j++)        {            if (k==array[j][i] && k!=0)            {                //array[x][y] = 2*array[x][y];                //array[x][y] = 2*k;                array[x][y] = 2*k;                array[j][i] = 0;                k = 0;                continue;            }            if (array[j][i]!=0)            {                k = array[j][i];                //此处的bug是x和y分别应该存储j和i                x = j;                y = i;            }        }    }    for (i=0; i<4; i++)    {        int k = 0;        for (j=0; j<4; j++)        {            //if (array[j][i])//此处有bug,假如k和j相等            if (array[j][i])            {                if (k != j)                {                    array[k][i] = array[j][i];                    array[j][i] = 0;                }                k++;            }        }    }    insert_num();    system("cls");//清屏    display();}
四、如何随机插入一个数(难点)    使用剩余空格数N,并且将空格的坐标记录下来,生成1-N的随机数n,并且在第n个空格插入2或者4.    tips:①vector<vector<int>> v(16 ,vector<int>());vector中含有vector不能定义为空          ②插入数字的时候需要判断空格数五、如何判定游戏结束    看是否能够水平移动或者竖直移动,在移动操作的函数中修改,不改变二维数组的值即可

程序所有的代码

#include <iostream>#include <cstdlib>  //rand(),time()#include <ctime>    #include <conio.h>  //getch()#include <ctype.h>  //#include <vector>#include <math.h>   //pow#include <iomanip>  //setwusing namespace std;int array[4][4] = {0};//申请全局数组作为方格里面的数//0—3的随机数产生int rand_pro(){    srand(time(0));    int k = rand()%4;    return k;}////////////////////////////////////界面函数//////////////////////////////////////////////////////////////之前的界面void display1(){    int i,j;    for (i=0; i<4; i++)    {        for(j=0; j<4; j++)        {            cout<<array[i][j]<<"    ";        }        cout<<endl;    }    cout<<"----------------------------------"<<endl;}//界面美化,不显示0,显示外框void display2(){    int i,j;    for (i=0; i<4; i++)    {        for(j=0; j<4; j++)        {            if (array[i][j] == 0)            {                cout<<" "<<"    ";            }            else                cout<<array[i][j]<<"    ";        }        cout<<endl;    }    cout<<"----------------------------------"<<endl;}void display() //显示棋盘  {      cout<<setw(46)<<"X2048 by ziyunmumu"<<endl;      cout<<setw(50)<<" |-----------------------|"<<endl;      for(int i=0;i<=3;i++)       {          cout<<setw(24)<<"";          for(int j=0;j<=3;j++)          {              //SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);             if (array[i][j] == 0)            {                cout<<setw(2)<<"|"<<setw(4)<<" ";              }            else                cout<<setw(2)<<"|"<<setw(4)<<array[i][j];              if(j==3)              {                  cout<<setw(2)<<"|"<<endl;                  cout<<setw(50)<<" |-----------------------|"<<endl;              }          }      }  }  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////新游戏的开始////////////////////////////////////////////////////////////void new_game(){    //初始化内容    int i,j;    for(i=0;i<4;i++)    {        for (j=0;j<4;j++)        {            array[i][j] = 0;        }    }    int m = rand_pro();    int n = rand_pro();    array[m][n] = 2;    display();}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////随机产生一个0-n-1的数字int rand_pro_s(int n){    srand(time(0));    int k = rand()%n;    return k;}//随机产生一个1-n的数字int rand_pro_ss(int n){    srand(time(0));    int k = rand()%n+1;    return k;}//统计0的个数,并且通过一个vector来存放坐标//p需要判断vector<vector<int>> zero_num(int* p){    int i,j;    int k = 0;    vector<vector<int>> v(16 ,vector<int>());    for (i=0; i<4; i++)    {        for (j=0; j<4; j++)        {            if (array[i][j] == 0)            {                v[k].push_back(i);                v[k].push_back(j);                k++;            }        }    }    *p = k;    return v;}//随机插入一个数字,通空格的个数随机插入//返回值为true就说明成功插入,否则未能插入bool insert_num(){    int k = 0;    vector<vector<int>> v;    v = zero_num(&k);    if (k>0)    {        int m = rand_pro_s(k);        int x = v[m][0];        int y = v[m][1];        array[x][y] = pow(2.0,rand_pro_ss(2));        return true;    }    return false;}////////////////////////////////////获得键盘方向//////////////////////////////////////////////////////////////获取方向//返回值//  1   上   72//  2   下   80//  3   左   75//  4   右   77int get_direction(){    char c1,c2;    int ret = 0;    c1 = getch();    if (!isascii(c1))    {        c2 = getch();        switch(c2)        {        case 72: ret = 1;break;        case 80: ret = 2;break;        case 75: ret = 3;break;        case 77: ret = 4;break;        default: break;        }    }    return ret;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////移动操作//////////////////////////////////////////////////////////////上下左右操作//操作分为两步,首先将相邻的相同数字加起来,然后去除空格//操作完之后需要插入数字//之前分为两步的想法有问题,假如是两个相同数字之间有0的话,也是可以结合的void up_dir(){    //完成第一步    int i,j;    for (i=0; i<4; i++)    {        /*for (j=0; j<3;)        {            if (array[j][i] == array[j+1][i])            {                array[j][i] = array[j][i] + array[j+1][i];                array[j+1][i] = 0;                j += 2;                continue;            }            j++;        }*/        int k = 0;        int x = 0;         int y = 0;        for (j=0; j<4; j++)        {            if (k==array[j][i] && k!=0)            {                //array[x][y] = 2*array[x][y];                //array[x][y] = 2*k;                array[x][y] = 2*k;                array[j][i] = 0;                k = 0;                continue;            }            if (array[j][i]!=0)            {                k = array[j][i];                //此处的bug是x和y分别应该存储j和i                x = j;                y = i;            }        }    }    for (i=0; i<4; i++)    {        int k = 0;        for (j=0; j<4; j++)        {            //if (array[j][i])//此处有bug,假如k和j相等            if (array[j][i])            {                if (k != j)                {                    array[k][i] = array[j][i];                    array[j][i] = 0;                }                k++;            }        }    }    insert_num();    system("cls");//清屏    display();}void down_dir(){    //完成第一步    int i,j;    for (i=0; i<4; i++)    {        /*for (j=3; j>0;)        {            if (array[j][i] == array[j-1][i])            {                array[j][i] = array[j][i] + array[j-1][i];                array[j-1][i] = 0;                j -= 2;                continue;            }            j--;        }*/        int k = 0;        int x = 0;         int y = 0;        for (j=3; j>=0; j--)        {            if (k==array[j][i] && k!=0)            {                array[x][y] = 2*k;                array[j][i] = 0;                k = 0;                continue;            }            if (array[j][i]!=0)            {                k = array[j][i];                x = j;                y = i;            }        }    }    for (i=0; i<4; i++)    {        int k = 3;        for (j=3; j>=0; j--)        {            if (array[j][i])            {                if (k != j)                {                    array[k][i] = array[j][i];                    array[j][i] = 0;                }                k--;            }        }    }    insert_num();    system("cls");//清屏    display();}void left_dir(){    int i,j;    for (i=0; i<4; i++)    {        int k = 0;        int x = 0;         int y = 0;        for (j=0; j<4; j++)        {            if (k==array[i][j] && k!=0)            {                array[x][y] = 2*k;                array[i][j] = 0;                k = 0;                continue;            }            if (array[i][j]!=0)            {                k = array[i][j];                x = i;                y = j;            }        }    }    for (i=0; i<4; i++)    {        int k = 0;        for (j=0; j<4; j++)        {            if (array[i][j])            {                if (k != j)                {                    array[i][k] = array[i][j];                    array[i][j] = 0;                }                k++;            }        }    }    insert_num();    system("cls");//清屏    display();}void right_dir(){    //完成第一步    int i,j;    for (i=0; i<4; i++)    {        int k = 0;        int x = 0;         int y = 0;        for (j=3; j>=0; j--)        {            if (k==array[i][j] && k!=0)            {                array[x][y] = 2*k;                array[i][j] = 0;                k = 0;                continue;            }            if (array[i][j]!=0)            {                k = array[i][j];                x = i;                y = j;            }        }    }    for (i=0; i<4; i++)    {        int k = 3;        for (j=3; j>=0; j--)        {            if (array[i][j])            {                if (k != j)                {                    array[i][k] = array[i][j];                    array[i][j] = 0;                }                k--;            }        }    }    insert_num();    system("cls");//清屏    display();}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////游戏结束//////////////////////////////////////////////////////////////判断游戏结束//将求解最大值和判断2048糅合在一起bool iswin(){    int i,j;    for (i=0; i<4; i++)    {        for (j=0; j<4; j++)        {            if (array[i][j] == 2048)            {                return true;            }        }    }    return false;}//构造函数can_up...,不能改变全局变量的值//只需要两个方向,水平或者垂直;bool can_ver(){    int i,j;    for (i=0; i<4; i++)    {        int k = 0;        for (j=0; j<4; j++)        {            if (k==array[j][i] && k!=0)            {                return true;            }            if (array[j][i]!=0)            {                k = array[j][i];            }        }    }    return false;}bool can_hor(){    int i,j;    for (i=0; i<4; i++)    {        int k = 0;        for (j=3; j>=0; j--)        {            if (k==array[i][j] && k!=0)            {                return true;            }            if (array[i][j]!=0)            {                k = array[i][j];            }        }    }    return false;}//怎么做到提前预判已经不能左右移动了bool islose(){    int k = 0;    zero_num(&k);    if (k>0)    {        return false;    }    if (can_ver() || can_hor())    {        return false;    }    return true;}////////////////////////////////////////////////////////////////////////////////////////////////void main(){    new_game();    int dir = 0;    while(1)    {        if (iswin())        {            cout<<"you win"<<endl;            break;        }        if (islose())        {            cout<<"you lose"<<endl;            break;        }        dir = get_direction();        switch(dir)        {        case 1: up_dir();break;        case 2: down_dir();break;        case 3: left_dir();break;        case 4: right_dir();break;        default:break;        }    }    system("pause");}
0 0
原创粉丝点击