当前位置: 首页 > news >正文

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;
}

效果 : 

相关文章:

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…...

159 Linux C++ 通讯架构实战14,epoll 函数代码实战

ngx_epoll_init函数的调用 //&#xff08;3.2&#xff09;ngx_epoll_init函数的调用&#xff08;要在子进程中执行&#xff09; //四章&#xff0c;四节 project1.cpp&#xff1a;nginx中创建worker子进程&#xff1b; //nginx中创建worker子进程 //官方nginx ,一个…...

【鹅厂摸鱼日记(一)】(工作篇)认识八大技术架构

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:重生之我在鹅厂摸鱼⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多知识   &#x1f51d;&#x1f51d; 认识八大架构 1. 前言2. 架构简介&…...

CA根证书——https安全保障的基石

HTTPS通信中&#xff0c;服务器端使用数字证书来证明自己的身份。客户端需要验证服务器发送的证书的真实性。这就需要一个可信的第三方机构&#xff0c;即CA&#xff0c;来颁发和管理证书。CA根证书是证书颁发机构层次结构的顶级证书&#xff0c;客户端信任的所有证书都可以追溯…...

Spark-Scala语言实战(10)

在之前的文章中&#xff0c;我们学习了如何在spark中使用RDD的filter,distinct,intersection三种方法。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 Spark-…...

【C++庖丁解牛】高阶数据结构---红黑树详解(万字超详细全面介绍红黑树)

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.红黑树的概念2.红黑…...

汽车网络安全管理

汽车网络安全管理 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c…...

文本自动粘贴编辑器:支持自动粘贴并筛选手机号码,让信息处理更轻松

在信息时代的浪潮中&#xff0c;文本处理已成为我们日常工作与生活的重要组成部分。无论是商务沟通、社交互动还是个人事务处理&#xff0c;手机号码的筛选与粘贴都显得尤为关键。然而&#xff0c;传统的文本处理方式效率低下、易出错&#xff0c;已无法满足现代人的高效需求。…...

Linux云计算之网络基础9——园区网络架构项目

要求构建大型园区网络架构&#xff0c;方案如下&#xff1a; 园区A 园区c 公司B 要求&#xff1a; 1、A公司园区网络 一台汇聚层三层交换机&#xff0c;两台接入层二层交换机。 出口有一台路由器。 2、A园区有五台服务器。 分别为两台 WEB 服务器&#xff0c;…...

Java 中的 List 集合

文章目录 添加元素获取元素检查元素删除元素修改元素获取列表大小检查列表是否为空清空列表查找元素索引获取列表的子列表 List 是 Java 集合框架中的一个接口&#xff0c;它表示一个有序的集合&#xff08;序列&#xff09;&#xff0c;允许存储重复的元素。List 接口提供了许…...

数据库之DDL操作(数据库,表,字段)

Data Definition Language&#xff0c;数据库定义语言&#xff0c;用来定义数据库对象&#xff08;数据库&#xff0c;表&#xff0c;字段&#xff09; 1.数据库操作 1.1查询所有数据库 show databases; 1.2查询当前数据库 show databases(); 1.3创建数据库 create da…...

5.3.1 配置交换机 SSH 管理和端口安全

5.3.1 实验1:配置交换机基本安全和 SSH管理 1、实验目的 通过本实验可以掌握&#xff1a; 交换机基本安全配置。SSH 的工作原理和 SSH服务端和客户端的配置。 2、实验拓扑 交换机基本安全和 SSH管理实验拓扑如图所示。 交换机基本安全和 SSH管理实验拓扑 3、实验步骤 &a…...

Django--数据库连接

数据库配置 打开mysite/settings.py配置文件&#xff0c;这是整个Django项目的设置中心。Django默认使用SQLite3数据库&#xff0c;因为Python原生支持SQLite3数据库&#xff0c;所以你无须安装任何程序&#xff0c;就可以直接使用它。 下面是默认的数据库配置&#xff1a; …...

CKA 基础操作教程(二)

Kubernetes Deployment 理论学习 Kubernetes Deployment &#xff08;部署&#xff09;是一种 Kubernetes 资源对象&#xff0c;用于定义和管理容器化应用程序的部署和更新。Deployment 提供了一种声明性的方式来定义应用程序的期望状态&#xff0c;并负责确保所需数量的 Pod…...

【SQLServer】快速查看SQL Server中所有数据库中所有表的行数

1.查看某个数据库中每个表的行数 SELECT @@servername as servername, db_name() as databasename, s.name AS schemaname, t.name AS tablename,p.rows AS rowcounts,SUM(a...

Node.js------Express

◆ 能够使用 express.static( ) 快速托管静态资源◆ 能够使用 express 路由精简项目结构◆ 能够使用常见的 express 中间件◆ 能够使用 express 创建API接口◆ 能够在 express 中启用cors跨域资源共享 一.初识Express 1.Express 简介 官方给出的概念&#xff1a;Express 是基…...

CSS - 你实现过0.5px的线吗

难度级别:中级及以上 提问概率:75% 我们知道在网页显示或是网页打印中,像素已经是最小单位了,但在很多时候,即便是最小的1像素,精度却不足以呈现所需的线条精度和细节。因此,为了在网页显示和网页打印中呈现更加细致的线条,为了在视觉…...

hbuilderX创建的uniapp项目转移到vscode

场景&#xff1a;一直使用hbuilderX开发的朋友想转移到vscode获取更好的TypeScript支持&#xff0c;所以想把整个项目目录拖到vscode进行开发&#xff0c;但发现运行不了&#xff0c;提示没有package.json等&#xff0c;并且不能执行pnpm命令 首先&#xff0c;我们先来看一下h…...

JavaScript 事件流

JavaScript与HTML之间的交互是通过事件实现的&#xff0c;而用户与浏览器页面的互动也是通过事件来实现的事件就是文档或浏览器窗口中发生的一些特定的交互瞬间&#xff0c;所以分为两种事件&#xff0c;一是发生在 浏览器对象&#xff08;BOM&#xff09;上的事件&#xff0c;…...

HTML——5.表单、框架、颜色

一、表单 HTML 表单用于在网页中收集用户输入的数据&#xff0c;例如登录信息、搜索查询等。HTML 提供了一系列的表单元素&#xff0c;允许用户输入文本、选择选项、提交数据等。 <!DOCTYPE html> <html lang"en"> <head> <meta charset&q…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...

轻量级Docker管理工具Docker Switchboard

简介 什么是 Docker Switchboard &#xff1f; Docker Switchboard 是一个轻量级的 Web 应用程序&#xff0c;用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器&#xff0c;使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...

StarRocks 全面向量化执行引擎深度解析

StarRocks 全面向量化执行引擎深度解析 StarRocks 的向量化执行引擎是其高性能的核心设计&#xff0c;相比传统行式处理引擎&#xff08;如MySQL&#xff09;&#xff0c;性能可提升 5-10倍。以下是分层拆解&#xff1a; 1. 向量化 vs 传统行式处理 维度行式处理向量化处理数…...

工厂方法模式和抽象工厂方法模式的battle

1.案例直接上手 在这个案例里面&#xff0c;我们会实现这个普通的工厂方法&#xff0c;并且对比这个普通工厂方法和我们直接创建对象的差别在哪里&#xff0c;为什么需要一个工厂&#xff1a; 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类&#xff1a; 两个发…...

【汇编逆向系列】六、函数调用包含多个参数之多个整型-参数压栈顺序,rcx,rdx,r8,r9寄存器

从本章节开始&#xff0c;进入到函数有多个参数的情况&#xff0c;前面几个章节中介绍了整型和浮点型使用了不同的寄存器在进行函数传参&#xff0c;ECX是整型的第一个参数的寄存器&#xff0c;那么多个参数的情况下函数如何传参&#xff0c;下面展开介绍参数为整型时候的几种情…...

PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础

在构建任何动态、数据驱动的Web API时&#xff0c;一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说&#xff0c;深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言&#xff0c;以及学会如何在Python中操作数据库&#xff0c;是…...

生信服务器 | 做生信为什么推荐使用Linux服务器?

原文链接&#xff1a;生信服务器 | 做生信为什么推荐使用Linux服务器&#xff1f; 一、 做生信为什么推荐使用服务器&#xff1f; 大家好&#xff0c;我是小杜。在做生信分析的同学&#xff0c;或是将接触学习生信分析的同学&#xff0c;<font style"color:rgb(53, 1…...