声明:本程序绝大部分属于原创,交互部分参考了博客园 Judge Young的原创文章 游戏2048源代码 - C语言控制台界面版,

作者Judge Young的算法思想非常值得参考,感谢作者的分享

附上文章链接:https://www.cnblogs.com/judgeyoung/p/3760515.html

算法总体思想:(请结合思维导图观看,移动合并算法篇幅较大,部分放到函数注释)

  1. 游戏主体抽象:将游戏数字面板抽象为一个二维数组,0代表空格。
  2. 移动合并算法:把每一行/列同等对待,只研究一行/列的移动和合并算法,通过遍历来实现所有行/列的移动合并算法。
  3. 游戏结束条件:分为三种情况,主动退出、游戏失败和游戏胜利。
  4. 随机数生成:寻找出空格,平均概率生成2 / 4。
  5. 界面显示:利用清屏再打印,达到界面刷新效果。
  6. 计分系统:游戏结束时,将所有格子中数字相加得到最终分数。
  7. 矩阵翻转:为了减少代码量与复用函数,提高练习效果,这里牺牲了部分效率。
  8. 备注:移动合并算法也可以通过矩阵翻转90度达到更好的函数复用效果,但效率更低。
  9. 再备注:函数声明处有一个撤回功能,可以利用old_squares做出来,但由于作者嫌麻烦所以没有做。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h> #define N 4 //矩阵大小为N * N
#define Max 2048 //胜利条件 int squares[N][N]; //游戏矩阵
int sum; //游戏积分
int old_squares[N][N]; //之前一步操作的矩阵 void GameStart(void); //游戏开始界面
void Print(void); //打印界面、计分
void Operator(char op); //对用户交互进行处理
int Operated(void); //判断矩阵是否发生变化
void Copy(void); //备份上一步的矩阵
void MoveUp(int op); //上移方格
void MoveLeft(int op); //左移方块
void Transpose(int op); //矩阵翻转
int GameOver(char op); //游戏结束:失败,退出和游戏胜利(需设置条件)
int Win(void); //判断游戏胜利
//void Recall(void); //撤回功能
void Random(void); //生成随机数
int HasNull(void); //判断矩阵存在空白位置
void PrintSum(void); //计算游戏积分并打印 int main(void)
{
char op = ' '; GameStart();
Random();
Operator(op);
while (!GameOver(op)) {
Copy();
while (!Operated()) {
op = getch();
Operator(op);
}
Random();
system("cls");
Print();
}
system("pause"); return 0;
} //初始化游戏参数
void GameStart(void) {
int i, j; sum = 0;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
squares[i][j] = 0;
old_squares[i][j] = 0;
}
} printf("Press any key to start the game.\n");
} //打印矩阵
void Print(void) {
int i, j; for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (squares[i][j] == 0) {
printf(" \t");
continue;
}
printf("%d\t", squares[i][j]);
}
printf("\n\n");
} printf("\n");
printf("(W)Up (S)Down (A)Left (D)Right\n");
printf(" (Q)Quit (R)Recall\n\n");
} void Operator(char op) {
switch (op) {
case 'w':
case 'W':
MoveUp(1); break;
case 'a':
case 'A':
MoveLeft(1); break;
case 's':
case 'S':
MoveUp(0); break;
case 'd':
case 'D':
MoveLeft(0); break;
default:
break;
}
} int Operated(void) {
int i, j; for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (old_squares[i][j] != squares[i][j])
return 1;
}
} return 0;
} void Copy(void) {
int i, j; for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
old_squares[i][j] = squares[i][j];
}
}
} //在一行中,使用两个下标变量来遍历列项,假设使用j和k,其中j总在k的后面,用来寻找k项后面第一个不为0的数字,而k项用于表示当前待比较的项,总是和j项之间隔着若干个数字0,或者干脆紧挨着。
void MoveUp(int op) {
int i, j, k; if (op == 0)
Transpose(0); for (i = 0; i < N; i++) {
for (j = 1, k = 0; j < 4; j++) {
if (squares[j][i] > 0) { /* 找出k后面第一个不为空的项,下标为j,之后分三种情况 */
//合并
if (squares[k][i] == squares[j][i]) {
squares[k][i] = 2 * squares[k][i];
squares[j][i] = 0;
k++;
}
//移动
else if (squares[k][i] == 0) {
squares[k][i] = squares[j][i];
squares[j][i] = 0;
}
//碰撞
else {
squares[k + 1][i] = squares[j][i];
if (j != k + 1) { /* 原先两数不挨着 */
squares[j][i] = 0;
}
k++;
}
}
}
} if (op == 0)
Transpose(0);
} void MoveLeft(int op) {
int i, j, k; if (op == 0)
Transpose(1); for (i = 0; i < N; i++) {
for (j = 1, k = 0; j < 4; j++) {
if (squares[i][j] > 0) {
//合并
if (squares[i][k] == squares[i][j]) {
squares[i][k] = 2 * squares[i][k];
squares[i][j] = 0;
k++;
}
//移动
else if (squares[i][k] == 0) {
squares[i][k] = squares[i][j];
squares[i][j] = 0;
}
//碰撞
else {
squares[i][k + 1] = squares[i][j];
if (j != k + 1) { /* 原先两数不挨着 */
squares[i][j] = 0;
}
k++;
}
}
}
} if (op == 0)
Transpose(1);
} void Transpose(int op) {
int i, j, temp = 0; //左右翻转
if (op == 1) {
for (i = 0; i < N; i++) {
for (j = 0; j < N / 2; j++) {
temp = squares[i][j];
squares[i][j] = squares[i][N - j - 1];
squares[i][N - j - 1] = temp;
}
}
}
//上下翻转
else {
for (i = 0; i < N; i++) {
for (j = 0; j < N / 2; j++) {
temp = squares[j][i];
squares[j][i] = squares[N - j - 1][i];
squares[N - j - 1][i] = temp;
}
}
}
} int GameOver(char op) {
int i, j; if (op == 'q' || op == 'Q')
printf("You have quit the game! GameOver!\n");
else if (Win())
printf("Congratulation! You win!\n");
else {
if (HasNull())
return 0;
for (i = 1; i < N; i++) {
for (j = 0; j < N; j++) {
//任意两个相邻的单元值相同,游戏继续
if (squares[i - 1][j] == squares[i][j])
return 0;
if (squares[j][i - 1] == squares[j][i])
return 0;
}
}
} PrintSum();
return 1;
} int Win(void) {
int i, j; for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (squares[i][j] == Max)
return 1;
}
} return 0;
} //在矩阵中随机位置生成数字2/4
void Random(void) {
int sitex, sitey; sitex = rand() % 4;
sitey = rand() % 4;
while (squares[sitex][sitey] != 0) {
sitex = rand() % 4;
sitey = rand() % 4;
} //生成2的概率是2/3,生成4的概率是1/3
if (rand() % 3 == 0)
squares[sitex][sitey] = 4;
else
squares[sitex][sitey] = 2;
} int HasNull(void) {
int i, j; for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (squares[i][j] == 0)
return 1;
}
} return 0;
} void PrintSum(void) {
int i, j; for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
sum += squares[i][j]; printf("Game Over! Your total score is: %d! \n", sum);
}

2048游戏 - C语言不引入图形库简单实现的更多相关文章

  1. 2048游戏C语言代码

    如果程序里面有错误,希望大家能够批评指正! #include<stdio.h> #include<stdlib.h> #include<conio.h> #incl ...

  2. C++学习(三十九)(C语言部分)之 游戏项目(2048游戏)

    /***************************项目 2048**********************c语言编写 图形库制作时间:2019.04.03 准备工具: vs2013 图形库 i ...

  3. 一个用 C 语言写的迷你版 2048 游戏,仅仅有 500个字符

    Jay Chan 用 C 语言写的一个迷你版 2048 游戏,仅仅有 487 个字符. 来围观吧 M[16],X=16,W,k;main(){T(system("stty cbreak&qu ...

  4. powershell字符界面的,powershell加WPF界面的,2048游戏

    ------[序言]------ 1 2048游戏,有段时间很火,我在地铁上看有人玩过.没错,坐地铁很无聊,人家玩我就一直盯着看. 2 我在电脑上找了一个,试玩了以下,没几次格子就满了.我就气呼呼的放 ...

  5. iOS雪花动画、音频图、新闻界面框架、2048游戏、二维码条形码扫码生成等源码

    iOS精选源码 粒子雪花与烟花的动画 iOS 2048游戏 JHSoundWaveView - 简单地声波图.音波图 一个可快速集成的新闻详情界面框架,类似今日头条,腾讯新闻 二维码/条形码扫描及扫描 ...

  6. [python] python实现2048游戏,及代码解析。

    我初学python,有不对之处望大家指教.转载请征得同意. 我在网络上也找了一些2048游戏代码的讲解,但都不是特别详细.所以我希望能够尽量详细的讲解.同时,有的地方我也不懂,希望大家能帮助补充.我会 ...

  7. cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发

     cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发 的产生 视持续更新中.... 视频存放地址例如以下:http://ipd.pps.tv/user/1058663622     ...

  8. 用Python做2048游戏 网易云课堂配套实验课。通过GUI来体验编程的乐趣。

    第1节 认识wxpython 第2节 画几个形状 第3节 再做个计算器 第4节 最后实现个2048游戏 实验1-认识wxpython 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiy ...

  9. android 2048游戏、kotlin应用、跑马灯、动画源码

    Android精选源码 2048游戏源码 android实现获取号码归属地和其他信息诈骗.骚扰 android kotlin仿开眼app源码 android多种reveal动画效果 android K ...

随机推荐

  1. 2020-04-05:谈一下spring事务传播

  2. C#LeetCode刷题-贪心算法

    贪心算法篇 # 题名 刷题 通过率 难度 44 通配符匹配   17.8% 困难 45 跳跃游戏 II   25.5% 困难 55 跳跃游戏   30.6% 中等 122 买卖股票的最佳时机 II C ...

  3. 【HNOI2015】菜肴制作 - 拓扑排序+贪心

    题目描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号为1. 由于菜肴 ...

  4. 30分钟闲置服务器建站(gitlab为例)

    前言 最近博主的阿里云主机又到了续费的时候了,刚买云主机的时候那是各种优惠各种打折,续费的时候只能当孙子了. 为了节省开支,又保证高性能的前提下,买了台10代NUC,内存和ssd自选,搭建一台个人服务 ...

  5. Gulp的安装及用法

    1.安装淘宝镜像 npm install cnpm -g --registry=https://registry.npm.taobao.org cnpm -v 2.生成项目描述文件 package.j ...

  6. jmeter性能测试入门使用参数化

    我经常使用jmeter进行接口测试,这个工具还是很好用的.昨天收到一个需求,需要压测一下接口,jmeter进行接口测试,使用cvs文件进行多个数据参数化. 临时准备了一下发现忘记怎么做参数化了,自己百 ...

  7. Vue Axios 的封装使用

    目录 Axios 说明 安装 Axios 请求配置 响应结构 常用请求方法 默认值配置 全局的 请求配置项 自定义实例默认值 配置的优先顺序 拦截器 个人完整 axios 配置 Axios 说明 Ax ...

  8. Jmeter 常用函数(11)- 详解 __TestPlanName

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回测试计划名称 语法格式 ${__T ...

  9. 第6篇scrum冲刺(5.26)

    一.站立会议 1.照片 2.工作安排 成员 昨天已完成的工作 今天的工作安排 困难 陈芝敏   研究云开发,更新了登录模块,把用户的信息传入数据库了  学习云开发,云函数调用以及数据的前后端传递  遇 ...

  10. 第1篇 Scrum 冲刺博客

    每个成员在Alpha阶段认领的任务 钟智锋 内容 工时 客户端请求对局 1h 客户端请求移动/使用锦囊/技能/进化 1h 把对局信息转换成可传播的信息 2h 客户端通信 3h 编写博客和文档 1h 岑 ...