c语言实现2048小游戏

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>int best = 0 ;// 定义2048游戏的结构体 
typedef struct { int martix[16];			// 当前4*4矩阵的数字 int martixPrior[16];	// 上一步的4*4矩阵的数字 int emptyIndex[16];		// 空位置的索引值 int emptyCount;			// 空位置的数量 int score;				// 当前的分数 int step;				// 记录操作步数 
}Game;int solve_best(int best){FILE *file;file = fopen("C:/Users/Redmi/Desktop/a.txt", "w"); // 以写入方式打开文件,如果文件不存在则创建if (file == NULL) {perror("Error opening file");return -1;}// 向文件中写入内容fprintf(file, "%d", best);fclose(file); // 关闭文件
}int get_best(){FILE *file;// 打开文件以读取原有数字file = fopen("C:/Users/Redmi/Desktop/a.txt", "r");if (file == NULL) {perror("Error opening file for reading");return -1;}int num = 0 ;// 读取原有数字int originalNumber;if (fscanf(file, "%d", &num) != 1) {perror("Error reading original number from file");fclose(file);return -1;}fclose(file); // 关闭文件return num ;
}// 生成[min, max]的随机整数
int RandomInt(int min, int max) {	srand((unsigned)time(NULL) + rand());	//以时间为随机种子return min + rand() % (max - min + 1);
}// 结构体的初始化 
void gameInit(Game *game) {int i;game->score = 0;game->step = 0;game->emptyCount = 16;for(i = 0; i < 16; i++) { game->martix[i] = 0;game->martixPrior[i] = 0;game->emptyIndex[i] = -1;}
}// 空位检测
void emptyDetect(Game *game) {int i = 0, j = 0;game->emptyCount = 0;for(i = 0; i < 16; i++) { game->emptyIndex[i] = -1; }for(i = 0; i < 16; i++) {if (game->martix[i] == 0) {game->emptyIndex[j++] = i;game->emptyCount++;}}
}// 在随机空位生成数字
void numberGenerate(Game *game) {int pos, numberIs4;numberIs4 = RandomInt(0, 3);	// 生成数字4的概率,这里为 1/4 pos = game->emptyIndex[RandomInt(0, game->emptyCount - 1)];if (numberIs4 == 0) { game->martix[pos] = 4; } else { game->martix[pos] = 2; }
} // 获取某行或某列
int *getLine(int *martix, int row, int col) {int i, *array;array = (int *)malloc(sizeof(int)*4);for (i = 0; i < 4; i++) {if (col != -1) { *(array+i) = *(martix + col+(i*4)); }if (row != -1) { *(array+i) = *(martix + row*4+i); }}return array;
} // 数字边缘对齐 
int *numberAlign(int *array, int reverse) {// reverse : 0: 向左对齐、向上对齐;  1: 向右对齐,向下对齐// 0 0 2 0 --> 2 0 0 0// 2 0 2 0 --> 2 2 0 0int i, j;int *newArray;newArray = (int *)malloc(sizeof(int)*4);for(j = 0; j < 4; j++) { *(newArray + j) = 0; }if (reverse == 0) {j = 0;for(i = 0; i < 4; i++) {if (*(array + i) != 0) { *(newArray + j) = *(array + i);j++;}}}if (reverse == 1) {j = 3;for(i = 3; i >= 0; i--) {if (*(array + i) != 0) {*(newArray + j) = *(array + i);j--;}}}return newArray;
}// 相邻数字相加
int *numberMerge(Game *game, int *array, int reverse) {int i, j, num1, num2;int *newArray;newArray = (int *)malloc(sizeof(int)*4);if (reverse == 0) {j = 0;for (i = 0; i < 4; i++) {num1 = *(array + i);num2 = 0;if (i != 3) { num2 = *(array + i + 1); } if (num1 == num2 && num1 > 0 && num2 > 0) {*(newArray + j) = num1 + num2;*(array + i + 1) = 0;game->score += (num1 + num2); } else {*(newArray + j) = *(array + i);}j++;}}if (reverse == 1) {j = 3;for (i = 3; i >= 0; i--) {num1 = *(array + i);num2 = 0;if (i != 0) { num2 = *(array + i - 1); }if (num1 == num2 && num1 > 0 && num2 > 0) {*(newArray + j) = num1 + num2;*(array + i - 1) = 0;game->score += (num1 + num2);} else {*(newArray + j) = *(array + i);}j--;}}return newArray;
}// 数字移动
void numberMoving(Game *game, int direction) {int *line[4];int i, j;switch(direction) {case 1:for (i = 0; i < 4; i++) {line[0] = getLine(game->martix, i, -1);line[1] = numberAlign(line[0], 0);line[2] = numberMerge(game, line[1], 0);line[3] = numberAlign(line[2], 0);for (j = 0; j < 4; j++) { game->martix[i*4+j] = *(line[3] + j);game->martixPrior[i*4+j] = *(line[0] + j);}}break;case 2:for(i = 0; i < 4; i++) {line[0] = getLine(game->martix, i, -1);line[1] = numberAlign(line[0], 1);line[2] = numberMerge(game, line[1], 1);line[3] = numberAlign(line[2], 1);for (j = 0; j < 4; j++) { game->martix[i*4+j] = *(line[3] + j);game->martixPrior[i*4+j] = *(line[0] + j);}}break;case 3:for(i = 0; i < 4; i++) {line[0] = getLine(game->martix, -1, i);line[1] = numberAlign(line[0], 0);line[2] = numberMerge(game, line[1], 0);line[3] = numberAlign(line[2], 0);for (j = 0; j < 4; j++) { game->martix[i+4*j] = *(line[3] + j);game->martixPrior[i+4*j] = *(line[0] + j);}}break;case 4:for(i = 0; i < 4; i++) {line[0] = getLine(game->martix, -1, i);line[1] = numberAlign(line[0], 1);line[2] = numberMerge(game, line[1], 1);line[3] = numberAlign(line[2], 1);for (j = 0; j < 4; j++) { game->martix[i+4*j] = *(line[3] + j); game->martixPrior[i+4*j] = *(line[0] + j);}}break;}for (j = 0; j < 4; j++) { free(line[j]); }}// 游戏结束判定
int gameOverDetect(Game *game) {// 当判定为输时返回 1 int i, j, row, col;if (game->emptyCount > 0) { return 0; }for (i = 0; i < 16; i++) {int numberBeside[4] = {0, 0, 0, 0};		// 相邻上下左右四个位置的数字row = i / 4;col = i % 4;if (row - 1 >= 0) { numberBeside[0] = game->martix[(row-1)*4+col]; }		// 获取上面的数字if (row + 1 < 4) { numberBeside[1] = game->martix[(row+1)*4+col]; }			// 获取下面的数字 if (col - 1 >= 0) { numberBeside[2] = game->martix[row*4+(col-1)]; }		// 获取左边的数字 if (col + 1 < 4) { numberBeside[3] = game->martix[row*4+(col+1)]; }			// 获取右边的数字 for(j = 0; j < 4; j++) {if (game->martix[i] == numberBeside[j]) { return 0; }}}return 1;
} // 键盘操作 
int keyboardPress() {// 返回值: 0: 无效操作; 1、2、3、4: 左右上下;int charAscii;charAscii = _getch();if (charAscii == 65 || charAscii == 97) { return 1; }		// A, 左if (charAscii == 68 || charAscii == 100) { return 2; }		// D, 右if (charAscii == 87 || charAscii == 119) { return 3; }		// W, 上if (charAscii == 83 || charAscii == 115) { return 4; }		// S, 下 return 0;
}// 检查数字是否移动过
int checkNumberMove(Game *game) {// 返回值: 0: 数字没有移动过; 1: 数字移动过 int i;for(i = 0; i < 16; i++) {if (game->martix[i] != game->martixPrior[i]) { return 1; } }return 0;
}// 游戏开始时随机生成2个数字 
void gameStart(Game *game) {int i;gameInit(game);emptyDetect(game);numberGenerate(game);emptyDetect(game);numberGenerate(game);emptyDetect(game);
}// 绘制画面
void drawGame(Game *game) {int row;system("cls");printf("\n      GAME : 2 0 4 8 BEST : %d    \n",best);printf("\n按键说明:  W:上  A:左  S:下  D:右\n\n");for(row = 0; row < 4; row++) {if (row == 0) { printf("---------------------------------\n"); }printf("|\t|\t|\t|\t|\n");if (game->martix[row*4] != 0) { printf("|%7d", game->martix[row*4]); } else { printf("|\t"); }if (game->martix[row*4+1] != 0) { printf("|%7d", game->martix[row*4+1]); } else { printf("|\t"); }if (game->martix[row*4+2] != 0) { printf("|%7d", game->martix[row*4+2]); } else { printf("|\t"); }if (game->martix[row*4+3] != 0) { printf("|%7d|\n", game->martix[row*4+3]); } else { printf("|\t|\n"); }printf("|\t|\t|\t|\t|\n");printf("---------------------------------\n");}printf("步数: %d\n分数: %d\n\n", game->step, game->score);
} // 主程序 
int main() {Game *gamePtr;int key;best = get_best() ;gamePtr = (Game *)malloc(sizeof(Game));gameInit(gamePtr);gameStart(gamePtr);drawGame(gamePtr);while(gameOverDetect(gamePtr) != 1) {key = keyboardPress();// 移动数字后生成数字 if (key != 0) {numberMoving(gamePtr, key);if (checkNumberMove(gamePtr) != 0) {emptyDetect(gamePtr);numberGenerate(gamePtr);emptyDetect(gamePtr);gamePtr->step += 1;drawGame(gamePtr); }}}printf("%d\n",gamePtr->score);if(gamePtr->score > best){solve_best(best) ;}printf("\n游 戏 结 束 !\n"); return 0;
}

效果 : 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1017. 负二进制转换

解题思路 相关代码 class Solution {public String baseNeg2(int n) {if(n0) return "0";String s"";while(n!0)if(Math.abs(n)%20){nn/(-2);ss0;}else{ss1; n (n-1)/(-2);}String t reverse(s);return t;}public String reverse(String s){Str…

前端三剑客 —— JavaScript (第一节)

目录 回顾内容 1.弹性布局 2.网格布局 JavaScript 概述 发展 浏览器 什么是Javascript JavaScript 能干什么 JavaScript需要的环境 JavaScript初体验 基本数据 JS书写方式 行内JS 页面JS 外部JS 1&#xff09;创建外部JS文件 2&#xff09;编写页面 对话框 警…

【Threejs进阶教程-效果篇】1.Threejs文字与css2d/css3d技术

Threejs文字与css2d/css3d技术 学习ThreeJS的捷径学习之前先搞清楚自己想要什么样的效果贴图文字准备一张带文字的png贴图使用sprite来进行贴图实现2D始终面朝相机的文字使用planeGeometry来贴图实现3D文字使用planeGeometry来贴图实现伪3D文字动态贴图文字html2Canvas 文字几何…

操作系统复习

虚拟内存 内存(memory)资源永远都是稀缺的&#xff0c;当越来越多的进程需要越来越来内存时&#xff0c;某些进程会因为得不到内存而无法运行&#xff1b; 虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存&#xff0c;而实际上&#xff0…

HTML基础知识详解(下)(如果想知道html的全部基础知识点,那么只看这一篇就足够了!)

前言&#xff1a;在上一篇文章中&#xff0c;我们已经学习完了超链接标签、列表标签和表格标签&#xff0c;但是我们还有一些标签没有学习&#xff0c;在这篇文章中&#xff0c;我们将学习剩余的标签。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页…

JAVA并发编程(一)

JAVA并发编程&#xff08;一&#xff09; 1.1JAVA线程API 1.1.1currentThread package com.lisus2000.thread;/** * 当前线程 * */ public class Test07 extends Thread {public Test07() {System.out.println("new Test07()......" Thread.currentThread().getNa…

vivado中移位寄存器的优化(二)

移位寄存器优化用于改善移位寄存器单元&#xff08;SRLs&#xff09;与其他逻辑单元之间的负裕量路径的时序。如果存在对移位寄存器单元&#xff08;SRL16E或SRLC32E&#xff09;的时序违规&#xff0c;优化会从SRL寄存器链的开始或结束位置提取一个寄存器&#xff0c;并将其放…

深入理解数据结构第三弹——二叉树(3)——二叉树的基本结构与操作

二叉树&#xff08;1&#xff09;&#xff1a;深入理解数据结构第一弹——二叉树&#xff08;1&#xff09;——堆-CSDN博客 二叉树&#xff08;2&#xff09;&#xff1a;深入理解数据结构第二弹——二叉树&#xff08;2&#xff09;——堆排序及其时间复杂度-CSDN博客 前言…

面试:HashMap

目录 1、底层数据结构&#xff0c;1.7 与1.8有何不同? 2、为何要用红黑树&#xff0c;为何一上来不树化&#xff0c;树化阈值为何是8&#xff0c;何时会树化&#xff0c;何时会退化为链表? 3、索引如何计算? hashCode都有了&#xff0c;为何还要提供hash()方法?数组容量为…

【Easy云盘 | 第十二篇】分享模块(获取分享信息、校验分享码、获取文件列表)

文章目录 4.4.4获取分享信息4.4.5校验分享码4.4.6获取文件列表 4.4.4获取分享信息 明天做 4.4.5校验分享码 明天做 4.4.6获取文件列表 明天做

Vue3大事件项目1 登录注册

创建项目 引入 element-ui 组件库 登录&#xff1a;注册样式准备之后&#xff0c;配置校验规则&#xff08;4个条件&#xff1a;一数据、二规则&#xff09; 1. 校验相关 (1) 给当前表单绑上整个的数据对象&#xff1a;el-form > :model"ruleForm" 绑…

云服务器是不是云盘?

​  云服务器是不是云盘?云服务器和云盘是两个不同的概念&#xff0c;尽管它们都是云计算服务的一部分。云服务器是一种提供计算能力的服务&#xff0c;可以运行各种应用程序和服务&#xff0c;而云盘则是一种提供数据存储和共享服务的工具。 具体来说&#xff1a; 云服务器…

【Qt】事件

目录 一、介绍 二、进入离开事件 三、鼠标事件 3.1 鼠标单击事件 3.2 鼠标释放事件 3.3 鼠标双击事件 3.4 鼠标移动事件 3.5 滚轮事件 四、按键事件 4.1 单个按键 4.2 组合按键 五、定时器 5.1 QTimerEvent类 5.2 QTimer类 5.3 获取系统日期及时间 六、窗口移…

蓝桥杯刷题 前缀和与差分-[NewOJ P1819]推箱子(C++)

题目描述 在一个高度为H的箱子前方&#xff0c;有一个长和高为N的障碍物。 障碍物的每一列存在一个连续的缺口&#xff0c;第i列的缺口从第l各单位到第h个单位&#xff08;从底部由0开始数&#xff09;。 现在请你清理出一条高度为H的通道&#xff0c;使得箱子可以直接推出去。…

深度学习理论基础(二)深度神经网络DNN

目录 一、基础知识点Ⅰ 参数部分Ⅱ 模型部分 二、深度神经网络模型搭建1. 准备数据集2. 划分数据集3. 搭建模型4. 训练网络5. 测试网络6. 保存与导入模型 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&…

每日一题(leetcode31):下一个排列-思维

思路&#xff1a;从后往前找到第一个nums[i-1]>nums[i] 然后从后往前(len-1 -->i(包含))找到第一个大于nums[i-1]的数&#xff0c;与nums[i-1]交换&#xff0c;然后对下标区间为[i,len-1]的元素进行排序。 class Solution { public:void nextPermutation(vector<in…

[深度学习] 无人车环境准备

1. 安装过程基本遵循以下步骤 电脑端环境配置 - OriginBot智能机器人开源套件 需要注意以下两点&#xff1a; 1> 由于深度学习需要的包和镜像体积都比较大&#xff0c;所以虚拟机硬盘大小建议120GB 2> 虚拟机的网络适配器应该设置为桥接模式&#xff0c;如果使用NAT模…

vivado 使用网表插入调试探测流程

使用网表插入调试探测流程 在 Vivado 工具中插入调试核的过程以分层方式来演示 &#xff0c; 以应对多样化的 Vivado 用户组的不同需求 &#xff1a; • 最高层是根据选定调试的一组信号线来自动创建并配置 Integrated Logic Analyzer (ILA) 核的简单向导。 • 下一层是“…

File,IO流,递归详解

File类 介绍 java.io.File类是Java语言提供了用来描述文件和目录(文件夹)的 构造 方法 注意&#xff1a; 构造方法中通常用的是第一个方法文件和目录可以通过File封装成对象File封装的对象仅仅是一个路径名&#xff0c;它是可以存在的&#xff0c;也可以不存在 绝对路径…

【二分查找】Leetcode x 的平方根

题目解析 69. x 的平方根 这道题表面是没有顺序性&#xff0c;但是我们可以发现如果使用枚举策略&#xff0c;它是包含顺序性质的&#xff0c;因此我们将枚举算法改进成二分算法 算法讲解 我们让left指针指向1&#xff0c; right指针指向x 如果当前的mid计算出来的平方 &g…