C控制台实现2048小游戏

image.png
#include"stdafx.h"
#include"stdlib.h"
#include"stdio.h"
#include"time.h"
#include"conio.h"
#include"windows.h"

int grid[4][4] = { 0 };  //保存4*4的格子数字
int score = 0;//游戏分数

void gotoXY(int x, int y)      //设定输出位置
{
    COORD c;   //光标位置
    c.X = x - 1;
    c.Y = y - 1;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);//获取句柄,设置位置

    HANDLE hOutStd = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cci;   //控制台光标信息结构类型
    cci.dwSize = 1;   //光标大小
    cci.bVisible = 0;      //是否显示光标  true显示
    SetConsoleCursorInfo(hOutStd, &cci);   //设置控制台屏幕光标大小和可见性
}



void printGrid() {   //打印游戏表格
    system("cls");
    printf("======C语言控制台版2048游戏======\n");
    for (int i = 0; i < 4; i++) {
        printf("---------------------------------\n");
        for (int j = 0; j < 4; j++) {
            if (grid[i][j] == 0) { printf("|  \t"); }//打印空数
            else printf("| %d\t", grid[i][j]);//打印数字
        }
        printf("|\n");//换行
    }

    printf("---------------------------------\n");

    gotoXY(18 * 2, 5);//定位输出
    printf("目前得分:%d", score);
    gotoXY(18 * 2, 7);
    printf("《请按四个方向箭头进行操作》");
}


void  randomNum() {
    srand((unsigned int)time(NULL));
    int x = rand() % 4;   //随机坐标
    int y = rand() % 4;

    while (grid[x][y] != 0) {//生成的位置已经有数字就重新生成
        x = rand() % 4;
        y = rand() % 4;
    }

    int z = rand() % 5;//概率媒介

    if (z == 0)grid[x][y] = 4;//五分之一的概率产生数字4
    else grid[x][y] = 2;//五分之四的概率产生数字2
}


//获取格子中的最大的数字
int getMax() {
    int max = 0;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (grid[i][j] > max) {
                max = grid[i][j];
            }
        }
    }
    return max;
}


int  gameOver() {

    int result = 1;//等于0继续游戏,等于1结束游戏

    //计算最大的数为2048时赢得游戏结束
    if (getMax() == 2048) {
        result = 1;
        printf("恭喜你赢得游戏!/n");
        system("pause");
    }

    //判断存在空格子,继续
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            if (grid[i][j] == 0) result = 0;
            break;
        }
    }


    //如果格子都不为空,需要进一步判断相邻格子数字是否相同
    if (result == 1) {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (i != 0 && grid[i][j] == grid[i - 1][j]) result = 0;  //与上面的数比较
                if (i != 3 && grid[i][j] == grid[i + 1][j]) result = 0;  //与下面的数比较
                if (j != 0 && grid[i][j] == grid[i][j - 1]) result = 0;//与左边的数比较
                if (j != 3 && grid[i][j] == grid[i][j + 1]) result = 0;//与右边的数比较
            }
        }
    }

    return result;

}


//向上划
int toUp() {

    int col, row;
    int isMove = 0;//默认0不移动,设置为1表明已经移动

    for (col = 0; col < 4; col++) {
        for (row = 1; row < 4; row++) {//纵向开始
            if (grid[row][col] && grid[row - 1][col] == 0) {  //本格不为空,上一格数为空,补空位
                grid[row - 1][col] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                //重置row,补位到最终位置
                if (row > 1) row -= 2;
                isMove = 1;
            }
        }

        //纵向相邻相同的数字则累加合位
        for (int row = 1; row < 4; row++) {
            if (grid[row][col] && grid[row - 1][col] == grid[row][col]) {//本格不为空,且与上一格数字相同则合并
                grid[row - 1][col] *= 2;
                score += grid[row][col];
                grid[row][col] = 0;//合并完后置空
                isMove = 1;
            }
        }

        //合并后再次补空位
        for (row = 1; row < 4; row++) {
            if (grid[row][col] && grid[row - 1][col] == 0) {  //本格数不为空,上一格数为空,补空位
                grid[row - 1][col] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                //重置row,补位到最终位置
                if (row > 1) row -= 2;
            }
        }

    }


    return isMove;

}

//向下划
int toDown() {
    int col, row;
    int isMove = 0;//默认0不移动

    for (col = 0; col < 4; col++) {
        for (row = 2; row >= 0; row--) {//纵向开始
            if (grid[row][col] && grid[row + 1][col] == 0) {  //本格数不为空,下一格数为空,补空位
                grid[row + 1][col] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                 //重置row,补位到最终位置
                if (row < 2) row += 2;
                isMove = 1;
            }
        }

        //纵向相邻相同的数字则累加合位
        for (row = 2; row >= 0; row--) {
            if (grid[row][col] && grid[row + 1][col] == grid[row][col]) {//本格不为空,且与下一格数字相同则合并
                grid[row + 1][col] *= 2;
                score += grid[row][col];
                grid[row][col] = 0;//合并完后置空
                isMove = 1;
            }
        }

        //合并后再次补空位
        for (row = 2; row >= 0; row--) {
            if (grid[row][col] && grid[row + 1][col] == 0) {  //本格数不为空,下一格数为空,补空位
                grid[row + 1][col] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                 //重置row,补位到最终位置
                if (row < 2) row += 2;
            }
        }

    }


    return isMove;

}


//向左划
int toLeft() {
    int col, row;
    int isMove = 0;//默认0不移动

    for (row = 0; row < 4; row++) {
        for (col = 1; col < 4; col++) {//横向开始
            if (grid[row][col] && grid[row][col - 1] == 0) {  //本格数不为空,左格数为空,补空位
                grid[row][col - 1] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                //重置col,补位到最终位置
                if (col > 1) col -= 2;
                isMove = 1;
            }
        }

        //横向相邻相同的数字则累加合位
        for (int col = 1; col < 4; col++) {
            if (grid[row][col] && grid[row][col - 1] == grid[row][col]) {//本格不为空,且与左边数字相同则合并
                grid[row][col - 1] *= 2;
                score += grid[row][col];
                grid[row][col] = 0;//合并完后置空
                isMove = 1;
            }
        }

        //合并后再次补空位
        for (col = 1; col < 4; col++) {
            if (grid[row][col] && grid[row][col - 1] == 0) {  //本格数不为空,左格数为空,补空位
                grid[row][col - 1] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                //重置col,补位到最终位置
                if (col > 1) col -= 2;
            }
        }

    }

    return isMove;

}


//向右划
int toRight() {
    int col, row;
    int isMove = 0;//默认0不移动

    for (row = 0; row < 4; row++) {
        for (col = 2; col >= 0; col--) {//横向开始
            if (grid[row][col] && grid[row][col + 1] == 0) {  //本格数不为空,右格数为空,补空位
                grid[row][col + 1] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                //重置col,补位到最终位置
                if (col < 2) col += 2;
                isMove = 1;
            }
        }

        //横向相邻相同的数字则累加合位
        for (col = 2; col >= 0; col--) {
            if (grid[row][col] && grid[row][col + 1] == grid[row][col]) {//本格不为空,且与右边数字相同则合并
                grid[row][col + 1] *= 2;
                score += grid[row][col];
                grid[row][col] = 0;//合并完后置空
                isMove = 1;
            }
        }

        //合并后再次补空位
        for (col = 2; col >= 0; col--) {
            if (grid[row][col] && grid[row][col + 1] == 0) {  //本格数不为空,右格数为空,补空位
                grid[row][col + 1] = grid[row][col];
                grid[row][col] = 0;//补位后置空
                 //重置col,补位到最终位置
                if (col < 2) col += 2;
            }
        }

    }

    return isMove;
}

//接收移动按键并刷新格子移动
void moveDirection() {
    int ch = _getch();

    switch (ch) {
        //向上箭头 224 72  判断接收两次
    case 72: //上划
        if (toUp() == 1) {
            randomNum();
            printGrid();
        }
        break;
        //向下箭头 224 80  判断接收两次
    case 80://下划
        if (toDown() == 1) {
            randomNum();
            printGrid();
        }
        break;
        //向左箭头 224 75  判断接收两次
    case 75: //左划
        if (toLeft() == 1) {
            randomNum();
            printGrid();
        }
        break;
        //向右箭头 224 77  判断接收两次
    case 77://右划
        if (toRight() == 1) {
            randomNum();
            printGrid();
        }
        break;
    default:break;
    }
}


void playGame() {   //开始游戏

    int flag = 1;

    while (flag) {
        //初始化格子,设置为0
        memset(grid, 0, sizeof(grid));
        //产生两个随机数字
        randomNum();
        randomNum();
        //打印格子
        printGrid();

        //游戏没有结束就可以一直操作,1是结束游戏
        while (gameOver() == 0) {
            //接收移动按键并进行移动
            moveDirection();
        }

        system("cls");
        printf("游戏结束,您的分数为:%d\n", score);
        printf("按y继续游戏,按n退出游戏!\n");


        //切换英文输入法
        keybd_event(VK_SHIFT, 0, 0, 0);
        Sleep(100);
        keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);

        int mark = 1;
        while (mark) {

            //接收按键
            char ch = _getch();

            if (ch == 'y' || ch == 'Y') {
                flag = 1;
                mark = 0;
                score = 0;
            }
            else if (ch == 'n' || ch == 'N') {
                system("cls");
                printf("欢迎下次来玩!\n");
                system("pause");
                exit(1);
            }
            else {
                printf("输入错误,请重新输入!\n");
            }
        }
    }
}

int main() {
    //进行2048游戏
    playGame();
    system("pause");
    return 0;
}

你可能感兴趣的:(C控制台实现2048小游戏)