zoukankan      html  css  js  c++  java
  • 用C挑战无准备写2048

    下午在刷题过程中,忽然想写2048了,以弥补以前写的那个千多行的,所以简单思考了一下准备采取的数据结构就开始了,本以为一个小时能搞定,结果后面改bug还是多花了些时间。因为在医院,所以声音不敢太大,如果看,建议耳机+声音最大,可以考虑倍速。个人感觉用C写这些东西的意义在于,你去掉了一些花里胡哨的东西,而真的用你的逻辑思考出了这个东西怎么写,并写出来了。乱花渐欲迷人眼,难的是坚守本心!明白学一个东西的意义,有时候比学习它更重要!嗯就这样。下面贴上代码和录制的视频链接。

    //2019年3月16日 17:29:07
    //2048
    //1、地图数据结构   2、合并和移动?   3、判断胜负
    #include<stdio.h>
    #include<stdlib.h>
    #include<windows.h>
    #include<conio.h>
    #include<time.h>
    #include<string.h> 
    #define N 5//地图大小 
    #define M 13//table表的长度 
    #define WINFLAG 11
    
    
    char map[N][N];//地图 
    int table[M];//查表使用
    
    
    void Init();
    void Run();
    void Print();
    int Win();
    void Lose();
    int IsLose();
    int Up(int *isChange);
    int Down(int *isChange);
    int Left(int *isChange);
    int Right(int *isChange);
    void Generator(int dir);
    
    
    void gotoxy(int x, int y); //将光标调整到(x,y)的位置
    
    
    //光标隐藏
    void HideCursor() ; //隐藏光标显示
    
    int main(void)
    {
        srand((unsigned)time(NULL));
        HideCursor();
        Init(); 
        Run();
        return 0;
    }
    
    
    void Generator(int dir)
    {
        //按下右,就按列扫,从左往右随机选一个数生成
        //按下上,就按行扫,从下网上随机选一个数生成    
    //    int begin;
    //    int end;
    //    int mul;//增量
    //    for(int i = begin;i != end;i += mul) 
    //    for(int i = 0;i < N;++i)
    //        for(j = N-1;j >= 0;--j) 
        int flag = 0;
        int i1 = -1,i2 = -1; 
        if(dir == 1 || dir == 2)
        {
            int begin,end,mul;
            dir == 1?begin = 0,end = N,mul = 1:begin = N-1,end = -1,mul = -1;
            for(int i = 0;i < N;++i)
                for(int j = begin;j != end;j += mul) 
                {
                    //保证选一个数,然后其他的随机
                    if(map[i][j] == 0)//选到了一个数
                    {
                        if(flag == 0)//之前没选到过
                        {
                            i1 = i;
                            i2 = j;
                            flag = 1;  
                        }
                        else
                        {
                            if(rand()%3 < 2)
                            {
                                i1 = i;
                                i2 = j;
                            }
                        }    
                    } 
                }
        }
        else if(dir == 3 ||  dir == 4)
        {
            int begin,end,mul;
            dir == 3?begin = 0,end = N,mul = 1:begin = N-1,end = -1,mul = -1;
            for(int j = begin;j != end;j += mul)
                for(int i = 0;i < N;++i)
                {
                    //保证选一个数,然后其他的随机
                    if(map[i][j] == 0)//选到了一个数
                    {
                        if(flag == 0)//之前没选到过
                        {
                            i1 = i;
                            i2 = j;
                            flag = 1;  
                        }
                        else
                        {
                            if(rand()%3 < 2)
                            {
                                i1 = i;
                                i2 = j;
                            }
                        }    
                    } 
                }
        }
        if(i1 == i2 && i2 == -1)
            return;
        map[i1][i2] = 1;
    }
    
    int Up(int *isChange)
    {
        //往上,所以是从上往下扫描
        //一列一列的算 
    
        for(int j = 0;j < N;++j)
        {
            int k = 0;
            for(int i = 1;i < N;++i)
            {
                if(map[i][j] != 0)//当前处理的这一位是有数字的 
                {
                    //只要是非0,且没有合并,则相加 
                    //这里保证map[i][j]是有数字的 
                    if(map[i][j] == map[k][j])
                    {
                        //与那个数字进行交互。合并操作 
                        map[k][j] += 1;
                        map[i][j] = 0; 
                        if(map[k][j] == 12)
                            return 5;
                        *isChange = 1;
                    } 
                    else if(map[k][j] == 0)//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
                    {
                        //把当前位置上的数移过去   特判的移动操作 
                        map[k][j] = map[i][j];
                        map[i][j] = 0; 
                        *isChange = 1;
                    }
                    else if(k+1 != i)//移动操作 
                    {
                        map[k+1][j] = map[i][j];//2 0 0 4  2 4 0 0     
                        map[i][j] = 0;//4 2 0 0
                        ++k; 
                        *isChange = 1;
                    }
                    
                    else//没有合并,且不是特判的 
                        ++k; 
                }
            }
        }
        return 1;
    }
    int Down(int *isChange)
    {
        for(int j = 0;j < N;++j)
        {
            int k = N-1;
            for(int i = N-2;i >= 0;--i)
            {
                if(map[i][j] != 0)//当前处理的这一位是有数字的 
                {
                    //只要是非0,且没有合并,则相加 
                    //这里保证map[i][j]是有数字的 
                    if(map[i][j] == map[k][j])
                    {
                        //与那个数字进行交互。合并操作 
                        map[k][j] += 1;
                        map[i][j] = 0; 
                        if(map[k][j] == 12)
                            return 5;
                        *isChange = 1;
                    } 
                    else if(map[k][j] == 0)//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
                    {
                        //把当前位置上的数移过去   特判的移动操作 
                        map[k][j] = map[i][j];
                        map[i][j] = 0; 
                        *isChange = 1;
                    }
                    else if(k-1 != i)//移动操作 
                    {
                        map[k-1][j] = map[i][j];//2 0 0 4  2 4 0 0     
                        map[i][j] = 0;//4 2 0 0
                        --k; 
                        *isChange = 1;
                    }
                    else//没有合并,且不是特判的 
                        --k; 
                }
            }
        }
        return 2;
    }
    int Left(int *isChange)
    {
        //合并?什么情况下合并?什么情况下移动?
        //一行一行处理
        //从左往右处理
        //这个有数字,我们才需要处理,没数字不用管  2 0 4 8    2 4 0 8    2 4 8 0
        for(int i = 0;i < N;++i)
        {
            int k = 0;
            for(int j = 1;j < N;++j)
            {
                if(map[i][j] != 0)//当前处理的这一位是有数字的 
                {
                    //这里保证map[i][j]是有数字的 
                    if(map[i][j] == map[i][k])
                    {
                        //与那个数字进行交互。合并操作 
                        map[i][k] += 1;
                        map[i][j] = 0; 
                        if(map[i][k] == 12)
                            return 5;
                        *isChange = 1;
                    }
                    else if(map[i][k] == 0)//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
                    {
                        //把当前位置上的数移过去   特判的移动操作 
                        map[i][k] = map[i][j];
                        map[i][j] = 0; 
                        *isChange = 1;
                    } 
                    else if(k+1 != j)//移动操作 
                    {
                        map[i][k+1] = map[i][j];//2 0 0 4  2 4 0 0     
                        map[i][j] = 0;//4 2 0 0
                        ++k; 
                        *isChange = 1;
                    }
                    else
                        ++k; 
                }
            }
        }
        return 3;
    }
    int Right(int *isChange)
    {
        //从右至左 
        for(int i = 0;i < N;++i)
        {
            int k = N-1;
            for(int j = N-2;j >= 0;--j)
            {
                if(map[i][j] != 0)//当前处理的这一位是有数字的 
                {
                    //这里保证map[i][j]是有数字的 
                    if(map[i][j] == map[i][k])
                    {
                        //与那个数字进行交互。合并操作 
                        map[i][k] += 1;
                        map[i][j] = 0; 
                        if(map[i][k] == 12)
                            return 5;
                        *isChange = 1;
                    }
                    else if(map[i][k] == 0)//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
                    { 
                        map[i][k] = map[i][j];
                        map[i][j] = 0; 
                        *isChange = 1;
                    } 
                    else if(k-1 != j)//移动操作 
                    {
                        map[i][k-1] = map[i][j];    
                        map[i][j] = 0;
                        --k; 
                        *isChange = 1;
                    }
                    else
                        --k;
                }
            }
        }
        return 4;
    }
    
    
    void Init()
    {
        int n = 16;//随机地图的数目 
        //先求table
        table[0] = 1;
        for(int i = 1;i < M;++i) 
            table[i] = table[i-1]<<1;//等同于*2 
    //    for(int i = 0;i < M;++i)
    //        printf("%5d",table[i]);
    //及时测试,验证正确性,免得日后找bug麻烦
        
        //随机地图   随机生成3个2? 
        memset(map,0,sizeof(map));
        for(int i = 0;i < n;++i)
        {
            int i1 = rand()%N;
            int i2 = rand()%N;
            //随机一组下标,让地图那个位置变成1
            map[i1][i2] = 1; //这个1代表2的一次,最终展现的是2 
        }
    }
    void Run()
    {
        int isChange = 0;//检测是否发生了变化 
        int flag = 0;
        while(1)
        {
            Print();
            isChange = 0;
            switch(getch())
            {
                case 'w':flag = Up(&isChange);break;
                case 's':flag = Down(&isChange);break;
                case 'a':flag = Left(&isChange);break;
                case 'd':flag = Right(&isChange);break;
            }
            if(flag != 5 && isChange)
                Generator(flag);
            if(flag == 5)
            {
                Win();
                break;
            }
            else if(IsLose())
            {
                Print();
                Lose();
                break;
            }    
        }
    }
    void Print()
    {
        gotoxy(0,0);
        for(int i = 0;i < N;++i)
        {
            for(int j = 0;j < N;++j)
                if(map[i][j] != 0)
                    printf("%3d  ",table[map[i][j]]);
                else
                    printf("     ");
            putchar('
    ');
        }
    }
    int Win()
    {
        printf("You are winner!
    ");
    }
    void Lose()
    {
        printf("You are loser!
    ");
    }
    int IsLose()
    {
        //判断是否还具备可操作空间
        for(int i = 0;i < N;++i)
             for(int j = 0;j < N-1;++j)
             {
                 if(map[i][j] == map[i][j+1])
                     return 0;
                else if(map[i][j]*map[i][j+1] == 0)
                    return 0;    
            }
        for(int j = 0;j < N;++j)
             for(int i = 0;i < N-1;++i)
             {
                 if(map[i][j] == map[i+1][j])
                     return 0;
                else if(map[i][j]*map[i+1][j] == 0)
                    return 0;    
            }
        Print();
        return 1;
    }
    //光标跳转
    void gotoxy(int x, int y) //将光标调整到(x,y)的位置
    {
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD pos;
        pos.X = x;
        pos.Y = y;
        SetConsoleCursorPosition(handle, pos);
    }
    
    
    //光标隐藏
    void HideCursor()  //隐藏光标显示
    {
        CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
    }
    View Code

    哔哩哔哩配套视频链接:https://www.bilibili.com/video/av46465862/

  • 相关阅读:
    分布式并行计算MapReduce
    备份
    【爬虫综合作业】猫眼电影TOP100分析
    爬取全部的校园新闻
    获取一篇新闻的全部信息
    爬虫原理
    中文词频统计
    复合数据类型,英文词频统计
    字符串、文件操作,英文词频统计预处理
    期末大作业
  • 原文地址:https://www.cnblogs.com/YaLi/p/10544882.html
Copyright © 2011-2022 走看看