zoukankan      html  css  js  c++  java
  • C语言写的2048小游戏

    基于"基于C_语言的2048算法设计_颜冠鹏.pdf"
    这一篇文献提供的思路
    在中国知网上能找到 就不贴具体内容了
    [摘 要] 针对2048的游戏规则,分析了该游戏的算法特点,对其相关的功能需求和算法设计进行了简单介绍,提出了一种 新的设计方案。解决了该设计在方阵数据结构、运动算法和游戏结束判断方面的问题,并阐述了以队列方式进行坐标运算和操 作扩展的关键技术。软件测试表明,该设计的方块数值最大值受方阵阶数和操作次数的限制,四阶方阵的理论最大值为 65 536, 智力极高的人可达 16 384,而一般人仅能达到 2 048 左右。
    [关键词] 2048 算法设计 数据结构 坐标运算 队列
    中图分类号:TP301.6 文献标识码:A 文章编号:1008- 1739(2014)24- 62- 5

    主要是几个小的函数
    用两个for循环打印地图和遍历地图
    把一个4*4的二维数组改成一个一维数组来简化处理思路

    学到的知识

    switch函数每一个case都需要加break来结束判断
    for在c99标准下 初始化的循环变量和外界所有变量毫无关系
    c99标准才有了布尔型变量
    尽量不要大循环套小循环 嵌套四层循环之后就晕了 下断点都不好调试
    如果数组越界访问会返回0
    随机数函数必须撒种子 不然每次都是同一个值

    //
    //  main.c
    //  2048
    //  表示 为了练习C语言 在这先写着一个小游戏吧
    //  “听说以后上课要用?”
    //  调试代码已注释 目前游戏所有功能均实现
    //  唯一不足的是在苹果系统环境无getch函数
    //  且不会自行实现 在其他系统直接include <conio.h>
    //  把getchar改为getch即可畅玩2048
    //  Created by licsber on 2018/10/11.
    //  Copyright © 2018 licsber. All rights reserved.
    //
    
    #include <stdio.h>//emmmm
    #include <stdbool.h> //c里没有布尔型变量 c99标准才加的
    #include <time.h>//用于产生随机数
    #include <stdlib.h>
    //#include <ncurses.h>//图形界面库 等后来更新printMap函数再引用
    
    void gameStart(void);//游戏开始
    void randomAdd(void);//在空格随机加2和4 其中2为十分之九概率
    void printMap(void);//用printf打印地图
    void getDirection(void);//读取键盘输入
    void moveUp(void);//上
    void moveDown(void);//下
    void moveLeft(void);//左
    void moveRight(void);//右
    void moveForward(void);//推进
    void moveMerge(void);//合并
    bool checkIfGameOver(void);//检测游戏是否over 即无空位同时相邻数组元素各不相等
    void restart(void);//重新开始
    void loop(void);//循环游戏
    //int countZero(void);//还有几个是0
    //int returnZero(int line);
    
    int score = 0;//当前得分
    int map[4][4]={
        {0,0,0,0},
        {0,0,0,0},
        {0,0,0,0},
        {0,0,0,0}
    };//这是地图 用二维数组实现
    int tmp[4] = {0,0,0,0};
    
    void gameStart(void){
        printf("Welcome to play 2048 game! by licsber
    ");
        randomAdd();
        printMap();
        printf("[w][s][a][d]move [r]restart [q]quit
    ");
    }
    
    void randomAdd(void){
        srand((unsigned int)time(NULL));//撒随机数种子
        //printf("%d",rand());
        int i,j,time = 0;//行 列 循环次数(debug用)
        do{
            i = rand() % 4;
            j = rand() % 4;
            time++;
        }while (map[i][j] != 0);
        if (rand() % 10 == 0 ) {
            map[i][j]=4;
        }
        else{
            map[i][j]=2;
        }
        //printf("%d",time);
        //上面的代码在格子快满之后也有几率循环N次都不停
        //todo改进方案:先找到所有空格子
        //下面的代码是有问题的 有几率无限循环
        /*
         bool finish = 0;//本轮是否已放置方块
         for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 4; j++) {
         if (!map[i][j]) {
         if (rand() % 16 == 0 && finish == 0) {
         // 十分之一的概率放4
         if (rand() % 10 == 0 ) {
         map[i][j]=4;
         }
         else{
         map[i][j]=2;
         }
         finish = 1;
         }
         }
         }
         }
         if (finish == 0) {
         randomAdd();
         }
         else{
         return;
         }
         */
    }
    
    void printMap(void){
        for (int i = 0; i < 4; i++) {
            printf("          ");
            for (int j = 0; j < 4; j++) {
                printf("%4d ",map[i][j]);
            }
            printf("
    ");
        }
        return;
    }
    
    void getDirection(void){
        tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
        char in = getchar();
        switch (in) {
            case 'w':
                moveUp();
                break;
            case 's':
                moveDown();
                break;
            case 'a':
                moveLeft();
                break;
            case 'd':
                moveRight();
                break;
            case 'r':
                restart();
                break;
            case 'q':
                exit(0);
                break;
            default:
                getDirection();
                break;
        }
    }
    
    void moveUp(void){
        for (int line = 0; line < 4; line++) {
            for (int i = 0; i < 4; i++) {
                tmp[i] = map[i][line];
            }
            moveMerge();
            for (int i = 0; i < 4; i++) {
                map[i][line] = tmp[i];
            }
        }
    }
    
    void moveDown(void){
        for (int line = 0; line < 4; line++) {
            for (int i = 0; i < 4; i++) {
                tmp[3 - i] = map[i][line];
            }
            moveMerge();
            for (int i = 0; i < 4; i++) {
                map[i][line] = tmp[3 - i];
            }
        }
    }
    
    void moveLeft(void){
        for (int line = 0; line < 4; line++) {
            for (int i = 0; i < 4; i++) {
                tmp[i] = map[line][i];
            }
            moveMerge();
            for (int i = 0; i < 4; i++) {
                map[line][i] = tmp[i];
            }
        }
    }
    
    void moveRight(void){
        for (int line = 0; line < 4; line++) {
            for (int i = 3; i >= 0; i--) {
                tmp[3 - i] = map[line][i];
            }
            moveMerge();
            for (int i = 3; i >= 0; i--) {
                map[line][i] = tmp[3 - i];
            }
        }
    }
    
    bool checkIfGameOver(void){
        //先检查格子是不是都满了
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (!map[i][j]) {
                    //只要有空的格子 游戏就没结束
                    return false;
                }
            }
        }
        //格子满了之后
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                if (map[i][j] == map[i+1][j] || map[i][j] == map[i][j+1]) {
                    //如果一个格子和它右边或下边相等 游戏也没结束
                    //这里数组如果越界访问会返回0 所以不影响结果
                    return false;
                }
            }
        }
        return true;
    }
    
    void moveForward(void){
        //i为0的话就把最先一个非零的j挪到i的位置
        int j = 0;
        for (int i = 0; i < 4; i++) {
            j++;
            if (tmp[i] == 0) {
                for (; j < 4; j++) {
                    if (tmp[j] != 0) {
                        tmp[i] = tmp[j];
                        tmp[j] = 0;
                        break;
                    }
                }
            }
        }
    }
    
    void moveMerge(void){
        //处理合并 每合并一次就推进一次
        moveForward();
        for (int i = 0; i < 3; i++) {
            if (tmp[i] == tmp[i + 1]) {
                tmp[i] *=2;
                tmp[i + 1] = 0;
                moveForward();
            }
        }
    }
    
    
    /*
    int countZero(void){
        int zero = 0;
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (!map[i][j]) {
                    zero++;
                }
            }
        }
        return zero;
    }
    */
    
    void restart(void){
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                map[i][j] = 0;
            }
        }
        gameStart();
        loop();
    }
    
    
    
    void loop(void){
        for(;;) {
            getDirection();
            printMap();
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (!map[i][j]) {
                        //只要有空的格子 就加
                        randomAdd();
                        goto go;
                    }
                }
            }
        go:
            if (checkIfGameOver() ==  true){
                printf("You are lose!");
                exit(0);
            }
        }
    }
    
    int main() {
        gameStart();
        loop();
        return 0;
    }
    
    
  • 相关阅读:
    C#动态执行代码
    C#的动态编译执行
    Win7/Vista激活后添加grub引导Linux最简单方法!无需命令行!
    乔布斯:关于 Flash 的思考
    I want to live in a honest country
    twitter bbs
    my follow rule on twitter
    blog will be repleace by twitter?
    blog Prediction
    也说说对blog是否需要静态页面的一点看法
  • 原文地址:https://www.cnblogs.com/licsber/p/2048game.html
Copyright © 2011-2022 走看看