用VC++6.0的控制台实现2048小游戏的程序

 更新时间:2015年03月06日 09:07:11   作者:geek_monkey  
本文是作者拜读刘地同学的《C语言控制台版2048》之后感觉非常不错,添加了注释之后分享给大家的,方便更多的初学者阅读学习,有需要的小伙伴参考下。

首先感谢这位大侠的无私分享,仔细学习这个程序以后收获很多,试着添加一些注释

源程序是从开源中国看到的,原作者是 刘地(sir?)
地址为http://www.oschina.net/code/snippet_593413_46040
geek_monkey于2015年3月5日为拜读该程序,受益匪浅
为了方便自己,以及更多初学者阅读,我试着写了写了注释供参考
我是C语言初学者,如有错误希望指正。轻喷

复制代码 代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>
int x[4][4],y[4][4],z=0,o=0;//z表示的是当前矩阵中的非零数字的数量,z为16则说明数字排满了,本局输了
                            //o表示最大数字的值,本例设定的是1024
typedef int row[4];  //row代表具有4个元素的整型数组
row *p=x, *q=y;//P是整型指针数组,有4组,每组有4个元素。p[1]=x[1]=*(x+1)
void show()//显示函数
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            if(p[i][j]==0)
            {
                printf("-     ");//没有放置数字(也就是数字为0时)显示一个小横杠
            }
            else
            {
                printf("%-4d  ",p[i][j]);//显示位宽为4的整数,-表示左对齐
            }
        }
        printf("\n\n");
    }
    printf("\n\n");
}
void over()//将2维数组左右对调
{
    int i,j;
    row *r;
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            q[i][3-j]=p[i][j];
        }
    r=p,p=q,q=r;
}
void left()//将2维数组逆时针转动90°
{
    int i,j;
    row *r;
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            q[3-j][i]=p[i][j];
        }
    r=p,p=q,q=r;
}
void right()//将2维数组顺时针转动90°
{
    int i,j;
    row *r;
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            q[j][3-i]=p[i][j];
        }
    r=p,p=q,q=r;
}
void inc()//此函数的作用是在0数字的位置上随机放置一个2或者4
{
    int i,j,k;
    for(;;)
    {
        k=rand()%16,i=k/4,j=k%4;//这个操作可以保证i,j小于等于4,不会放到二维数组外边
        if(p[i][j]==0)break;//确认p[i][j]是空白的,然后才能放置2或者4
    }
    if(rand()%2) //随机产生2或者4,理论上rand()%2的结果,0,1,几率各占一半
    {
        p[i][j]=4;
    }
    else
    {
        p[i][j]=2;
    }
    z++;
}
void merge(char c)
{
    int i,j,k,t;
    switch(c)//注,这个stitch没有default,也没有给按下右方向键的处理语句。即,按下右方向键,则跳过switch
    {
        case 'H'://检测到按了上方向键
            right();//顺时针转动90度
        break;
        case 'K'://左
            over();//左右对称换
        break;
        case 'P'://下
            left(); //逆90
        break;
    }
    //上边这个switch语句是将矩阵变换,将数字推向上,左或者下的操作转换为推向右的操作。
    //下边这个循环语句的功能是,把每一行的数字都往右边推,数字大小一样则合并。
    for(i=0;i<4;i++)//一行一行地检测
    {
        for(j=k=3;j>=0 && p[i][j]==0;j--);//从第i行的右边开始,向左找非零元素。也就是要让p[i][j]不为0的时候,结束本条for语句
        if(j<0)continue;//经过下边的右推操作,第i行最左边的值也非0,说明此行操作结束,跳出i的for循环,执行i+1行的右推操作
            t=p[i][j],p[i][j]=0,p[i][k]=t;//P[i][j]是P[i][k]左边的一个数。这里的j的值是由上一条语句找出来的,通过t传值保证了这个p[i][k]不为0
            for(j--;j>=0;j--)
            {
                t=p[i][j];
                if(t!=0)//如果p[i][j]不为0,就检测它与右侧的p[i][k]是否为相同
                {
                    p[i][j]=0;
                    if(p[i][k]==t)
                    {
                        z--,p[i][k]+=t;//相同则加倍,同时非0数字的数量减少一个
                        o=(t==512);//t为512代表最大值是1024,此时o==1,游戏以胜利结束
                    }
                    else
                    {
                        k--,p[i][k]=t;//不停则将p[i][j]的值赋给p[i][k],即数据右移动一位
                    }
                }
            }
    }
    switch(c)
    {
        case 'H'://按下,上方向键,矩阵逆时针旋转90°。这个操作与之前那个switch正好相反
            left();
        break;
        case 'K'://左右再次对调
            over();
        break;
        case 'P':
            right();
        break;
    }
    inc();
}
int main()
{
    char a,b;
    srand(time(NULL));
    inc();
    inc();//放置两个初始值
    show();
    while(z<16 && !o)//游戏结束条件,z==16或者o==1
    {
        a=getch();
        if(a==-32)//方向键的第一个字节为-32.char是无符的,这里为什么是-32还没弄明白
        {
            b=getch();
            if(b==72||b==75||b==77||b==80)
            {
                merge(b);
                show();
            }
        }
    }
    if(o)
    {
        printf("congratulations!");
    }
    else
    {
        printf("sorry, you failed!");
    }
    getch();
    return 0;
}
/*
特殊按键是两个字节,第一个字节是表示按的是特殊键的(普通键就一个字节),第 二个字节就是按键的ASCII码,
当按下“普通键”时,它的低8位数存放该字符的ASCII码。
对于特殊键,低8位为0。特殊键包括箭头键、功能键等。高8位字节存放该键的扫描码
#define KEY_LEFT 75   K   左
#define KEY_RIGHT 77  M   右
#define KEY_UP 72     H   上
#define KEY_DOWN 80   P   下
*/

以上就是本文分享的内容了,希望对大家学习VC++能有所帮助。

相关文章

  • C语言实现链表贪吃蛇

    C语言实现链表贪吃蛇

    这篇文章主要为大家详细介绍了C语言实现链表贪吃蛇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • C++求四个正整数最大公约数的方法

    C++求四个正整数最大公约数的方法

    这篇文章主要介绍了C++求四个正整数最大公约数的方法,涉及C++求余算法的运用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2016-05-05
  • 浅谈使用C++多级指针存储海量qq号和密码

    浅谈使用C++多级指针存储海量qq号和密码

    这篇文章主要介绍了浅谈使用C++多级指针存储海量qq号和密码,分享了相关实例代码,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 带你粗略了解C++流的读写文件

    带你粗略了解C++流的读写文件

    这篇文章主要为大家总结了C++中输入输出流及文件流操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-08-08
  • 用C++实现,将一句话里的单词进行倒置的方法详解

    用C++实现,将一句话里的单词进行倒置的方法详解

    本篇文章是对用C++实现,将一句话里的单词进行倒置的方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言计算代码执行所耗CPU时钟周期

    C语言计算代码执行所耗CPU时钟周期

    本文给大家介绍的是使用C语言来计算代码执行所耗CPU时钟周期的代码,非常的简单实用,不过要依托于sync,有需要的小伙伴自己参考下吧。
    2015-03-03
  • C++ move()函数案例详解

    C++ move()函数案例详解

    这篇文章主要介绍了C++ move()函数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Pipes实现LeetCode(195.第十行)

    Pipes实现LeetCode(195.第十行)

    这篇文章主要介绍了Pipes实现LeetCode(195.第十行),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++改变编程入口为main函数

    C++改变编程入口为main函数

    这篇文章主要介绍了C++改变编程入口为main函数的方法的相关资料,需要的朋友可以参考下
    2015-06-06
  • C++中的对象数组详细解析

    C++中的对象数组详细解析

    在建立数组时,同样要调用构造函数。如果有50个元素,就需要调用50次构造函数。在需要的时候,可以在定义数组时提供实参以实现初始化
    2013-10-10

最新评论