下午在刷题过程中,忽然想写2048了,以弥补以前写的那个千多行的,所以简单思考了一下准备采取的数据结构就开始了,本以为一个小时能搞定,结果后面改bug还是多花了些时间。因为在医院,所以声音不敢太大,如果看,建议耳机+声音最大,可以考虑倍速。个人感觉用C写这些东西的意义在于,你去掉了一些花里胡哨的东西,而真的用你的逻辑思考出了这个东西怎么写,并写出来了。乱花渐欲迷人眼,难的是坚守本心!明白学一个东西的意义,有时候比学习它更重要!嗯就这样。下面贴上代码和录制的视频链接。

  1. //2019年3月16日 17:29:07
  2. //2048
  3. //1、地图数据结构 2、合并和移动? 3、判断胜负
  4. #include<stdio.h>
  5. #include<stdlib.h>
  6. #include<windows.h>
  7. #include<conio.h>
  8. #include<time.h>
  9. #include<string.h>
  10. #define N 5//地图大小
  11. #define M 13//table表的长度
  12. #define WINFLAG 11
  13.  
  14. char map[N][N];//地图
  15. int table[M];//查表使用
  16.  
  17. void Init();
  18. void Run();
  19. void Print();
  20. int Win();
  21. void Lose();
  22. int IsLose();
  23. int Up(int *isChange);
  24. int Down(int *isChange);
  25. int Left(int *isChange);
  26. int Right(int *isChange);
  27. void Generator(int dir);
  28.  
  29. void gotoxy(int x, int y); //将光标调整到(x,y)的位置
  30.  
  31. //光标隐藏
  32. void HideCursor() ; //隐藏光标显示
  33.  
  34. int main(void)
  35. {
  36. srand((unsigned)time(NULL));
  37. HideCursor();
  38. Init();
  39. Run();
  40. return ;
  41. }
  42.  
  43. void Generator(int dir)
  44. {
  45. //按下右,就按列扫,从左往右随机选一个数生成
  46. //按下上,就按行扫,从下网上随机选一个数生成
  47. // int begin;
  48. // int end;
  49. // int mul;//增量
  50. // for(int i = begin;i != end;i += mul)
  51. // for(int i = 0;i < N;++i)
  52. // for(j = N-1;j >= 0;--j)
  53. int flag = ;
  54. int i1 = -,i2 = -;
  55. if(dir == || dir == )
  56. {
  57. int begin,end,mul;
  58. dir == ?begin = ,end = N,mul = :begin = N-,end = -,mul = -;
  59. for(int i = ;i < N;++i)
  60. for(int j = begin;j != end;j += mul)
  61. {
  62. //保证选一个数,然后其他的随机
  63. if(map[i][j] == )//选到了一个数
  64. {
  65. if(flag == )//之前没选到过
  66. {
  67. i1 = i;
  68. i2 = j;
  69. flag = ;
  70. }
  71. else
  72. {
  73. if(rand()% < )
  74. {
  75. i1 = i;
  76. i2 = j;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. else if(dir == || dir == )
  83. {
  84. int begin,end,mul;
  85. dir == ?begin = ,end = N,mul = :begin = N-,end = -,mul = -;
  86. for(int j = begin;j != end;j += mul)
  87. for(int i = ;i < N;++i)
  88. {
  89. //保证选一个数,然后其他的随机
  90. if(map[i][j] == )//选到了一个数
  91. {
  92. if(flag == )//之前没选到过
  93. {
  94. i1 = i;
  95. i2 = j;
  96. flag = ;
  97. }
  98. else
  99. {
  100. if(rand()% < )
  101. {
  102. i1 = i;
  103. i2 = j;
  104. }
  105. }
  106. }
  107. }
  108. }
  109. if(i1 == i2 && i2 == -)
  110. return;
  111. map[i1][i2] = ;
  112. }
  113.  
  114. int Up(int *isChange)
  115. {
  116. //往上,所以是从上往下扫描
  117. //一列一列的算
  118.  
  119. for(int j = ;j < N;++j)
  120. {
  121. int k = ;
  122. for(int i = ;i < N;++i)
  123. {
  124. if(map[i][j] != )//当前处理的这一位是有数字的
  125. {
  126. //只要是非0,且没有合并,则相加
  127. //这里保证map[i][j]是有数字的
  128. if(map[i][j] == map[k][j])
  129. {
  130. //与那个数字进行交互。合并操作
  131. map[k][j] += ;
  132. map[i][j] = ;
  133. if(map[k][j] == )
  134. return ;
  135. *isChange = ;
  136. }
  137. else if(map[k][j] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
  138. {
  139. //把当前位置上的数移过去 特判的移动操作
  140. map[k][j] = map[i][j];
  141. map[i][j] = ;
  142. *isChange = ;
  143. }
  144. else if(k+ != i)//移动操作
  145. {
  146. map[k+][j] = map[i][j];//2 0 0 4 2 4 0 0
  147. map[i][j] = ;//4 2 0 0
  148. ++k;
  149. *isChange = ;
  150. }
  151.  
  152. else//没有合并,且不是特判的
  153. ++k;
  154. }
  155. }
  156. }
  157. return ;
  158. }
  159. int Down(int *isChange)
  160. {
  161. for(int j = ;j < N;++j)
  162. {
  163. int k = N-;
  164. for(int i = N-;i >= ;--i)
  165. {
  166. if(map[i][j] != )//当前处理的这一位是有数字的
  167. {
  168. //只要是非0,且没有合并,则相加
  169. //这里保证map[i][j]是有数字的
  170. if(map[i][j] == map[k][j])
  171. {
  172. //与那个数字进行交互。合并操作
  173. map[k][j] += ;
  174. map[i][j] = ;
  175. if(map[k][j] == )
  176. return ;
  177. *isChange = ;
  178. }
  179. else if(map[k][j] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
  180. {
  181. //把当前位置上的数移过去 特判的移动操作
  182. map[k][j] = map[i][j];
  183. map[i][j] = ;
  184. *isChange = ;
  185. }
  186. else if(k- != i)//移动操作
  187. {
  188. map[k-][j] = map[i][j];//2 0 0 4 2 4 0 0
  189. map[i][j] = ;//4 2 0 0
  190. --k;
  191. *isChange = ;
  192. }
  193. else//没有合并,且不是特判的
  194. --k;
  195. }
  196. }
  197. }
  198. return ;
  199. }
  200. int Left(int *isChange)
  201. {
  202. //合并?什么情况下合并?什么情况下移动?
  203. //一行一行处理
  204. //从左往右处理
  205. //这个有数字,我们才需要处理,没数字不用管 2 0 4 8 2 4 0 8 2 4 8 0
  206. for(int i = ;i < N;++i)
  207. {
  208. int k = ;
  209. for(int j = ;j < N;++j)
  210. {
  211. if(map[i][j] != )//当前处理的这一位是有数字的
  212. {
  213. //这里保证map[i][j]是有数字的
  214. if(map[i][j] == map[i][k])
  215. {
  216. //与那个数字进行交互。合并操作
  217. map[i][k] += ;
  218. map[i][j] = ;
  219. if(map[i][k] == )
  220. return ;
  221. *isChange = ;
  222. }
  223. else if(map[i][k] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
  224. {
  225. //把当前位置上的数移过去 特判的移动操作
  226. map[i][k] = map[i][j];
  227. map[i][j] = ;
  228. *isChange = ;
  229. }
  230. else if(k+ != j)//移动操作
  231. {
  232. map[i][k+] = map[i][j];//2 0 0 4 2 4 0 0
  233. map[i][j] = ;//4 2 0 0
  234. ++k;
  235. *isChange = ;
  236. }
  237. else
  238. ++k;
  239. }
  240. }
  241. }
  242. return ;
  243. }
  244. int Right(int *isChange)
  245. {
  246. //从右至左
  247. for(int i = ;i < N;++i)
  248. {
  249. int k = N-;
  250. for(int j = N-;j >= ;--j)
  251. {
  252. if(map[i][j] != )//当前处理的这一位是有数字的
  253. {
  254. //这里保证map[i][j]是有数字的
  255. if(map[i][j] == map[i][k])
  256. {
  257. //与那个数字进行交互。合并操作
  258. map[i][k] += ;
  259. map[i][j] = ;
  260. if(map[i][k] == )
  261. return ;
  262. *isChange = ;
  263. }
  264. else if(map[i][k] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
  265. {
  266. map[i][k] = map[i][j];
  267. map[i][j] = ;
  268. *isChange = ;
  269. }
  270. else if(k- != j)//移动操作
  271. {
  272. map[i][k-] = map[i][j];
  273. map[i][j] = ;
  274. --k;
  275. *isChange = ;
  276. }
  277. else
  278. --k;
  279. }
  280. }
  281. }
  282. return ;
  283. }
  284.  
  285. void Init()
  286. {
  287. int n = ;//随机地图的数目
  288. //先求table
  289. table[] = ;
  290. for(int i = ;i < M;++i)
  291. table[i] = table[i-]<<;//等同于*2
  292. // for(int i = 0;i < M;++i)
  293. // printf("%5d",table[i]);
  294. //及时测试,验证正确性,免得日后找bug麻烦
  295.  
  296. //随机地图 随机生成3个2?
  297. memset(map,,sizeof(map));
  298. for(int i = ;i < n;++i)
  299. {
  300. int i1 = rand()%N;
  301. int i2 = rand()%N;
  302. //随机一组下标,让地图那个位置变成1
  303. map[i1][i2] = ; //这个1代表2的一次,最终展现的是2
  304. }
  305. }
  306. void Run()
  307. {
  308. int isChange = ;//检测是否发生了变化
  309. int flag = ;
  310. while()
  311. {
  312. Print();
  313. isChange = ;
  314. switch(getch())
  315. {
  316. case 'w':flag = Up(&isChange);break;
  317. case 's':flag = Down(&isChange);break;
  318. case 'a':flag = Left(&isChange);break;
  319. case 'd':flag = Right(&isChange);break;
  320. }
  321. if(flag != && isChange)
  322. Generator(flag);
  323. if(flag == )
  324. {
  325. Win();
  326. break;
  327. }
  328. else if(IsLose())
  329. {
  330. Print();
  331. Lose();
  332. break;
  333. }
  334. }
  335. }
  336. void Print()
  337. {
  338. gotoxy(,);
  339. for(int i = ;i < N;++i)
  340. {
  341. for(int j = ;j < N;++j)
  342. if(map[i][j] != )
  343. printf("%3d ",table[map[i][j]]);
  344. else
  345. printf(" ");
  346. putchar('\n');
  347. }
  348. }
  349. int Win()
  350. {
  351. printf("You are winner!\n");
  352. }
  353. void Lose()
  354. {
  355. printf("You are loser!\n");
  356. }
  357. int IsLose()
  358. {
  359. //判断是否还具备可操作空间
  360. for(int i = ;i < N;++i)
  361. for(int j = ;j < N-;++j)
  362. {
  363. if(map[i][j] == map[i][j+])
  364. return ;
  365. else if(map[i][j]*map[i][j+] == )
  366. return ;
  367. }
  368. for(int j = ;j < N;++j)
  369. for(int i = ;i < N-;++i)
  370. {
  371. if(map[i][j] == map[i+][j])
  372. return ;
  373. else if(map[i][j]*map[i+][j] == )
  374. return ;
  375. }
  376. Print();
  377. return ;
  378. }
  379. //光标跳转
  380. void gotoxy(int x, int y) //将光标调整到(x,y)的位置
  381. {
  382. HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  383. COORD pos;
  384. pos.X = x;
  385. pos.Y = y;
  386. SetConsoleCursorPosition(handle, pos);
  387. }
  388.  
  389. //光标隐藏
  390. void HideCursor() //隐藏光标显示
  391. {
  392. CONSOLE_CURSOR_INFO cursor_info = { , };
  393. SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
  394. }

哔哩哔哩配套视频链接:https://www.bilibili.com/video/av46465862/

用C挑战无准备写2048的更多相关文章

  1. 用python实现一个无界面的2048

    转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5519453.html 以前游戏2048火的时候,正好用其他的语言编写了一个,现在学习python,正好想起来,便决定 ...

  2. js280行代码写2048

    2048 原作者就是用Js写的,一直想尝试.但久久未动手. 昨天教学生学习JS代码.最好还是就做个有趣的游戏好了.2048这么火,是一个不错的选择. 思路: 1. 数组 ,2维数组4x4 2. 移动算 ...

  3. 一起来写2048(160行python代码)

    前言: Life is short ,you need python. --Bruce Eckel 我与2048的缘,不是缘于一个玩家,而是一次,一次,重新的ACM比赛.四月份校赛初赛,第一次碰到20 ...

  4. 一起写2048(160行python代码)

    前言: Life is short ,you need python. --Bruce Eckel 我与2048的缘,不是缘于一个玩家.而是一次,一次,重新的ACM比赛.四月份校赛初赛,第一次碰到20 ...

  5. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  6. python写2048小游戏

    #!/usr/bin/env python # coding=utf-8 #******************************************************** # > ...

  7. 初学者cocos2dx 写2048 为了和大家一起分享

    第一个是在头文件 部分的代码是学习不变  大多数写自己. class HelloWorld : public cocos2d::CCLayer { public: virtual bool init( ...

  8. R语言写2048游戏

    2048 是一款益智游戏,只需要用方向键让两两相同的数字碰撞就会诞生一个翻倍的数字,初始数字由 2 或者 4 构成,直到游戏界面全部被填满,游戏结束. 编程时并未查看原作者代码,不喜勿喷. 程序结构如 ...

  9. js写2048游戏代码

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

随机推荐

  1. svn取消文件夹关联的方法

    新建个记事本,贴入以下代码,保存后重命名后缀为reg,然后在目标文件夹右键就出现了删除SVN的选项了. 代码如下: Windows Registry Editor Version 5.00 [HKEY ...

  2. Navicat Premium 连接MySQL数据库出现Authentication plugin 'caching_sha2_password' cannot be loaded的解决方案

    1. 管理员权限运行命令提示符,登陆MySQL mysql -u root -p root 2. 修改账户密码加密规则并更新用户密码  ALTER USER 'root'@'localhost' ID ...

  3. Mongodb的入门(1)window安装mongodb

    mongodb: Mongodb,分布式文档存储数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案.MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数 ...

  4. JQuery 引用方式

    # head里面 <script src="jquery.min.js"></script> <script src="common.js& ...

  5. [SQL SERVER] 映射网络驱动器,让SQL服务器可见

    在服务器上运行: EXEC sp_configure 'show advanced options', 1; GO RECONFIGURE; GO EXEC sp_configure 'xp_cmds ...

  6. Linux内存管理(text、rodata、data、bss、stack&heap)

    一.各内存区段的介绍 系统内的程序分为程序段和数据段,具体又可细分为一下几个部分: (1)text段-代码段 text段存放程序代码,运行前就已经确定(编译时确定),通常为只读,可以直接在ROM或Fl ...

  7. 【转】什么是JavaScript

    转自mdn学习网站-什么是JavaScript 什么是JavaScript? 欢迎来到 MDN JavaScript 初学者的课程! 在第一篇文章中,我们将会站在一定的高度来俯看 JavaScript ...

  8. python 统计学的各种检验

    1.使用python中的Numpy进行t检验 http://www.atyun.com/7476.html 2.scipy中的卡方检验 http://wiki.mbalib.com/wiki/%E5% ...

  9. 安装配置maven私服-nexus

    1.ubuntu下的Bundle安装方式 1.1. 去官网下载安装包:http://www.sonatype.org/nexus/ 我这里下载的是:nexus-2.8.1-01-bundle.zip, ...

  10. JavaScript验证字符串只能包含数字或者英文字符的代码实例

    验证字符串只能包含数字或者英文字符的代码实例:本章节分享一段代码实例,它实现了验证字符串内容是否只包含英文字符或者数字.代码实例如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...