用C挑战无准备写2048
下午在刷题过程中,忽然想写2048了,以弥补以前写的那个千多行的,所以简单思考了一下准备采取的数据结构就开始了,本以为一个小时能搞定,结果后面改bug还是多花了些时间。因为在医院,所以声音不敢太大,如果看,建议耳机+声音最大,可以考虑倍速。个人感觉用C写这些东西的意义在于,你去掉了一些花里胡哨的东西,而真的用你的逻辑思考出了这个东西怎么写,并写出来了。乱花渐欲迷人眼,难的是坚守本心!明白学一个东西的意义,有时候比学习它更重要!嗯就这样。下面贴上代码和录制的视频链接。
- //2019年3月16日 17:29:07
- //2048
- //1、地图数据结构 2、合并和移动? 3、判断胜负
- #include<stdio.h>
- #include<stdlib.h>
- #include<windows.h>
- #include<conio.h>
- #include<time.h>
- #include<string.h>
- #define N 5//地图大小
- #define M 13//table表的长度
- #define WINFLAG 11
- char map[N][N];//地图
- int table[M];//查表使用
- void Init();
- void Run();
- void Print();
- int Win();
- void Lose();
- int IsLose();
- int Up(int *isChange);
- int Down(int *isChange);
- int Left(int *isChange);
- int Right(int *isChange);
- void Generator(int dir);
- void gotoxy(int x, int y); //将光标调整到(x,y)的位置
- //光标隐藏
- void HideCursor() ; //隐藏光标显示
- int main(void)
- {
- srand((unsigned)time(NULL));
- HideCursor();
- Init();
- Run();
- return ;
- }
- void Generator(int dir)
- {
- //按下右,就按列扫,从左往右随机选一个数生成
- //按下上,就按行扫,从下网上随机选一个数生成
- // int begin;
- // int end;
- // int mul;//增量
- // for(int i = begin;i != end;i += mul)
- // for(int i = 0;i < N;++i)
- // for(j = N-1;j >= 0;--j)
- int flag = ;
- int i1 = -,i2 = -;
- if(dir == || dir == )
- {
- int begin,end,mul;
- dir == ?begin = ,end = N,mul = :begin = N-,end = -,mul = -;
- for(int i = ;i < N;++i)
- for(int j = begin;j != end;j += mul)
- {
- //保证选一个数,然后其他的随机
- if(map[i][j] == )//选到了一个数
- {
- if(flag == )//之前没选到过
- {
- i1 = i;
- i2 = j;
- flag = ;
- }
- else
- {
- if(rand()% < )
- {
- i1 = i;
- i2 = j;
- }
- }
- }
- }
- }
- else if(dir == || dir == )
- {
- int begin,end,mul;
- dir == ?begin = ,end = N,mul = :begin = N-,end = -,mul = -;
- for(int j = begin;j != end;j += mul)
- for(int i = ;i < N;++i)
- {
- //保证选一个数,然后其他的随机
- if(map[i][j] == )//选到了一个数
- {
- if(flag == )//之前没选到过
- {
- i1 = i;
- i2 = j;
- flag = ;
- }
- else
- {
- if(rand()% < )
- {
- i1 = i;
- i2 = j;
- }
- }
- }
- }
- }
- if(i1 == i2 && i2 == -)
- return;
- map[i1][i2] = ;
- }
- int Up(int *isChange)
- {
- //往上,所以是从上往下扫描
- //一列一列的算
- for(int j = ;j < N;++j)
- {
- int k = ;
- for(int i = ;i < N;++i)
- {
- if(map[i][j] != )//当前处理的这一位是有数字的
- {
- //只要是非0,且没有合并,则相加
- //这里保证map[i][j]是有数字的
- if(map[i][j] == map[k][j])
- {
- //与那个数字进行交互。合并操作
- map[k][j] += ;
- map[i][j] = ;
- if(map[k][j] == )
- return ;
- *isChange = ;
- }
- else if(map[k][j] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
- {
- //把当前位置上的数移过去 特判的移动操作
- map[k][j] = map[i][j];
- map[i][j] = ;
- *isChange = ;
- }
- else if(k+ != i)//移动操作
- {
- map[k+][j] = map[i][j];//2 0 0 4 2 4 0 0
- map[i][j] = ;//4 2 0 0
- ++k;
- *isChange = ;
- }
- else//没有合并,且不是特判的
- ++k;
- }
- }
- }
- return ;
- }
- int Down(int *isChange)
- {
- for(int j = ;j < N;++j)
- {
- int k = N-;
- for(int i = N-;i >= ;--i)
- {
- if(map[i][j] != )//当前处理的这一位是有数字的
- {
- //只要是非0,且没有合并,则相加
- //这里保证map[i][j]是有数字的
- if(map[i][j] == map[k][j])
- {
- //与那个数字进行交互。合并操作
- map[k][j] += ;
- map[i][j] = ;
- if(map[k][j] == )
- return ;
- *isChange = ;
- }
- else if(map[k][j] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
- {
- //把当前位置上的数移过去 特判的移动操作
- map[k][j] = map[i][j];
- map[i][j] = ;
- *isChange = ;
- }
- else if(k- != i)//移动操作
- {
- map[k-][j] = map[i][j];//2 0 0 4 2 4 0 0
- map[i][j] = ;//4 2 0 0
- --k;
- *isChange = ;
- }
- else//没有合并,且不是特判的
- --k;
- }
- }
- }
- return ;
- }
- int Left(int *isChange)
- {
- //合并?什么情况下合并?什么情况下移动?
- //一行一行处理
- //从左往右处理
- //这个有数字,我们才需要处理,没数字不用管 2 0 4 8 2 4 0 8 2 4 8 0
- for(int i = ;i < N;++i)
- {
- int k = ;
- for(int j = ;j < N;++j)
- {
- if(map[i][j] != )//当前处理的这一位是有数字的
- {
- //这里保证map[i][j]是有数字的
- if(map[i][j] == map[i][k])
- {
- //与那个数字进行交互。合并操作
- map[i][k] += ;
- map[i][j] = ;
- if(map[i][k] == )
- return ;
- *isChange = ;
- }
- else if(map[i][k] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
- {
- //把当前位置上的数移过去 特判的移动操作
- map[i][k] = map[i][j];
- map[i][j] = ;
- *isChange = ;
- }
- else if(k+ != j)//移动操作
- {
- map[i][k+] = map[i][j];//2 0 0 4 2 4 0 0
- map[i][j] = ;//4 2 0 0
- ++k;
- *isChange = ;
- }
- else
- ++k;
- }
- }
- }
- return ;
- }
- int Right(int *isChange)
- {
- //从右至左
- for(int i = ;i < N;++i)
- {
- int k = N-;
- for(int j = N-;j >= ;--j)
- {
- if(map[i][j] != )//当前处理的这一位是有数字的
- {
- //这里保证map[i][j]是有数字的
- if(map[i][j] == map[i][k])
- {
- //与那个数字进行交互。合并操作
- map[i][k] += ;
- map[i][j] = ;
- if(map[i][k] == )
- return ;
- *isChange = ;
- }
- else if(map[i][k] == )//我们是说k是第一个非零的,但初始的时候我们为了好运算,是没做判断的
- {
- map[i][k] = map[i][j];
- map[i][j] = ;
- *isChange = ;
- }
- else if(k- != j)//移动操作
- {
- map[i][k-] = map[i][j];
- map[i][j] = ;
- --k;
- *isChange = ;
- }
- else
- --k;
- }
- }
- }
- return ;
- }
- void Init()
- {
- int n = ;//随机地图的数目
- //先求table
- table[] = ;
- for(int i = ;i < M;++i)
- table[i] = table[i-]<<;//等同于*2
- // for(int i = 0;i < M;++i)
- // printf("%5d",table[i]);
- //及时测试,验证正确性,免得日后找bug麻烦
- //随机地图 随机生成3个2?
- memset(map,,sizeof(map));
- for(int i = ;i < n;++i)
- {
- int i1 = rand()%N;
- int i2 = rand()%N;
- //随机一组下标,让地图那个位置变成1
- map[i1][i2] = ; //这个1代表2的一次,最终展现的是2
- }
- }
- void Run()
- {
- int isChange = ;//检测是否发生了变化
- int flag = ;
- while()
- {
- Print();
- isChange = ;
- switch(getch())
- {
- case 'w':flag = Up(&isChange);break;
- case 's':flag = Down(&isChange);break;
- case 'a':flag = Left(&isChange);break;
- case 'd':flag = Right(&isChange);break;
- }
- if(flag != && isChange)
- Generator(flag);
- if(flag == )
- {
- Win();
- break;
- }
- else if(IsLose())
- {
- Print();
- Lose();
- break;
- }
- }
- }
- void Print()
- {
- gotoxy(,);
- for(int i = ;i < N;++i)
- {
- for(int j = ;j < N;++j)
- if(map[i][j] != )
- printf("%3d ",table[map[i][j]]);
- else
- printf(" ");
- putchar('\n');
- }
- }
- int Win()
- {
- printf("You are winner!\n");
- }
- void Lose()
- {
- printf("You are loser!\n");
- }
- int IsLose()
- {
- //判断是否还具备可操作空间
- for(int i = ;i < N;++i)
- for(int j = ;j < N-;++j)
- {
- if(map[i][j] == map[i][j+])
- return ;
- else if(map[i][j]*map[i][j+] == )
- return ;
- }
- for(int j = ;j < N;++j)
- for(int i = ;i < N-;++i)
- {
- if(map[i][j] == map[i+][j])
- return ;
- else if(map[i][j]*map[i+][j] == )
- return ;
- }
- Print();
- return ;
- }
- //光标跳转
- void gotoxy(int x, int y) //将光标调整到(x,y)的位置
- {
- HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
- COORD pos;
- pos.X = x;
- pos.Y = y;
- SetConsoleCursorPosition(handle, pos);
- }
- //光标隐藏
- void HideCursor() //隐藏光标显示
- {
- CONSOLE_CURSOR_INFO cursor_info = { , };
- SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
- }
哔哩哔哩配套视频链接:https://www.bilibili.com/video/av46465862/
用C挑战无准备写2048的更多相关文章
- 用python实现一个无界面的2048
转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5519453.html 以前游戏2048火的时候,正好用其他的语言编写了一个,现在学习python,正好想起来,便决定 ...
- js280行代码写2048
2048 原作者就是用Js写的,一直想尝试.但久久未动手. 昨天教学生学习JS代码.最好还是就做个有趣的游戏好了.2048这么火,是一个不错的选择. 思路: 1. 数组 ,2维数组4x4 2. 移动算 ...
- 一起来写2048(160行python代码)
前言: Life is short ,you need python. --Bruce Eckel 我与2048的缘,不是缘于一个玩家,而是一次,一次,重新的ACM比赛.四月份校赛初赛,第一次碰到20 ...
- 一起写2048(160行python代码)
前言: Life is short ,you need python. --Bruce Eckel 我与2048的缘,不是缘于一个玩家.而是一次,一次,重新的ACM比赛.四月份校赛初赛,第一次碰到20 ...
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- python写2048小游戏
#!/usr/bin/env python # coding=utf-8 #******************************************************** # > ...
- 初学者cocos2dx 写2048 为了和大家一起分享
第一个是在头文件 部分的代码是学习不变 大多数写自己. class HelloWorld : public cocos2d::CCLayer { public: virtual bool init( ...
- R语言写2048游戏
2048 是一款益智游戏,只需要用方向键让两两相同的数字碰撞就会诞生一个翻倍的数字,初始数字由 2 或者 4 构成,直到游戏界面全部被填满,游戏结束. 编程时并未查看原作者代码,不喜勿喷. 程序结构如 ...
- js写2048游戏代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
随机推荐
- svn取消文件夹关联的方法
新建个记事本,贴入以下代码,保存后重命名后缀为reg,然后在目标文件夹右键就出现了删除SVN的选项了. 代码如下: Windows Registry Editor Version 5.00 [HKEY ...
- Navicat Premium 连接MySQL数据库出现Authentication plugin 'caching_sha2_password' cannot be loaded的解决方案
1. 管理员权限运行命令提示符,登陆MySQL mysql -u root -p root 2. 修改账户密码加密规则并更新用户密码 ALTER USER 'root'@'localhost' ID ...
- Mongodb的入门(1)window安装mongodb
mongodb: Mongodb,分布式文档存储数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案.MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数 ...
- JQuery 引用方式
# head里面 <script src="jquery.min.js"></script> <script src="common.js& ...
- [SQL SERVER] 映射网络驱动器,让SQL服务器可见
在服务器上运行: EXEC sp_configure 'show advanced options', 1; GO RECONFIGURE; GO EXEC sp_configure 'xp_cmds ...
- Linux内存管理(text、rodata、data、bss、stack&heap)
一.各内存区段的介绍 系统内的程序分为程序段和数据段,具体又可细分为一下几个部分: (1)text段-代码段 text段存放程序代码,运行前就已经确定(编译时确定),通常为只读,可以直接在ROM或Fl ...
- 【转】什么是JavaScript
转自mdn学习网站-什么是JavaScript 什么是JavaScript? 欢迎来到 MDN JavaScript 初学者的课程! 在第一篇文章中,我们将会站在一定的高度来俯看 JavaScript ...
- python 统计学的各种检验
1.使用python中的Numpy进行t检验 http://www.atyun.com/7476.html 2.scipy中的卡方检验 http://wiki.mbalib.com/wiki/%E5% ...
- 安装配置maven私服-nexus
1.ubuntu下的Bundle安装方式 1.1. 去官网下载安装包:http://www.sonatype.org/nexus/ 我这里下载的是:nexus-2.8.1-01-bundle.zip, ...
- JavaScript验证字符串只能包含数字或者英文字符的代码实例
验证字符串只能包含数字或者英文字符的代码实例:本章节分享一段代码实例,它实现了验证字符串内容是否只包含英文字符或者数字.代码实例如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...