2048控制台程序:一份帝国理工C++作业
#include <fstream>
#include <vector>
#include <iostream>
#include <string>
using namespace std; //打印输出数组内容到窗口
void print_square(const vector<int> &square);
//设置默认的初始状态数组,最后一个数是2,其他都是0
void set_default_square(vector<int> &square);
//计算(row,col)坐标处的元素在数组中的索引
int coordtoidx(int row, int col);
//提取一行4个元素
void extract_row(const vector<int>& square, int row, vector<int>& output);
//将移动后(左移或右移)的行数据更新到数组
void update_row(vector<int>& square, int row, const vector<int>& newrow);
//提取一列4个元素
void extract_col(const vector<int>& square, int col, vector<int>& output);
//将移动后(上移或下移)的列数据更新到数组
void update_col(vector<int>& square, int col, const vector<int>& newcol);
//检测某一行或列是否可以移动
bool check_moveable(const vector<int> &rowcol);
//检测游戏是否结束。检测方法:依次检测每一行每一列是否可移动
bool checkgameover(const vector<int> &square);
//向上或向左移动一列或一行数据,移动后的结果放到aftermove数组
void move_up_or_left(const vector<int> &colrow, vector<int> &aftermove);
//向下或向右移动一列或一行数据,移动后的结果放到aftermove数组
void move_down_or_right(const vector<int> &colrow, vector<int> &aftermove);
//向上移动,响应'w'键
void moveup(vector<int> &square);
//向下移动,响应's'键
void movedown(vector<int> &square);
//向左移动,响应'a'键
void moveleft(vector<int> &square);
//向右移动,响应'd'键
void moveright(vector<int> &square);
//检测响应一个按键之后,数组内容是否有变化
bool check_state_change(const vector<int>& oldsquare, const vector<int>& newsquare);
//移动完成之后,在空白处随机选择一处设置元素值2
void add2random(vector<int>& square); int main()
{
ifstream inputfile;
cout<< "enter initial configuration file name:" <<endl;
string infilename;
cin>>infilename;
inputfile.open(infilename);
//inputfile.open("inputconf.txt");
//存放数组数据,总共16个整数
vector<int> squaredata;
int number;
//如果能够正确打开初始数据文件,那么从中读取数据
if (inputfile.is_open())
{
while (inputfile>>number)
{
squaredata.push_back(number);
}
inputfile.close();
}
else
{
cout<<"file not found, using default start configuration:"<<endl;
//使用默认的初始数据,最后一个数是2,其他都是0
set_default_square(squaredata);
}
//输出状态到屏幕
print_square(squaredata); //接收输入的键盘命令:a,s,d,w
char cmd;
//游戏结束标志
bool gameover=false;
//存储上一次的数组状态,用来判断状态是否有更改
vector<int> oldsquaredata;
//循环处理用户输入的命令
while(!gameover)
{
//先记录旧的数组
oldsquaredata=squaredata;
cin>>cmd;
if (cmd=='w')
{
//上移
moveup(squaredata);
}
else if (cmd=='a')
{
//左移
moveleft(squaredata);
}
else if (cmd=='s')
{
//下移
movedown(squaredata);
}
else if (cmd=='d')
{
//右移
moveright(squaredata);
}
else
{
//提示一下只能接收awsd命令
cout<<"note: using 'a' for left, 's' for down, 'd' for right and 'w' for up"<<endl;
}
//检测数组是否有变化
bool square_change=check_state_change(oldsquaredata,squaredata);
if (square_change)
{
//随机选择一个空白处增加一个元素2
add2random(squaredata);
//输出状态到屏幕
print_square(squaredata);
//检测是否game over
gameover=checkgameover(squaredata);
}
}
cout<<"game over"<<endl;
system("pause");
} void print_square(const vector<int> &square)
{
cout<<endl;
for (unsigned int i=; i<square.size(); i++)
{
cout<<square.at(i)<<"\t";
if ((i+)%==)
{
cout<<endl;
}
}
cout<<endl;
}
void set_default_square(vector<int> &square)
{
for (int i=; i<; i++)
{
square.push_back();
}
square.back()=;
}
int coordtoidx(int row, int col)
{
return row*+col;
}
void extract_row(const vector<int>& square, int row, vector<int>& output)
{
for (int c=; c<;c++)
{
int idx=coordtoidx(row,c);
output.push_back(square.at(idx));
}
}
void update_row(vector<int>& square, int row, const vector<int>& newrow)
{
for (int c=; c<; c++)
{
int idx=coordtoidx(row,c);
square[idx]=newrow[c];
}
}
void extract_col(const vector<int>& square, int col, vector<int>& output)
{
for (int r=; r<;r++)
{
int idx=coordtoidx(r,col);
output.push_back(square.at(idx));
}
}
void update_col(vector<int>& square, int col, const vector<int>& newcol)
{
for (int r=; r<;r++)
{
int idx=coordtoidx(r,col);
square[idx]=newcol[r];
}
}
bool check_moveable(const vector<int> &rowcol)
{
int a=rowcol[];
int b=rowcol[];
int c=rowcol[];
int d=rowcol[];
//首先检测是否含有0元素
if(a*b*c*d==)
return true;
if (a==b||b==c||c==d)
{
return true;
}
return false;
}
bool checkgameover(const vector<int> &square)
{
for (int i=; i<; i++)
{
vector<int> row,col;
extract_row(square, i, row);
extract_col(square, i, col);
bool checkrow=check_moveable(row);
bool checkcol=check_moveable(col);
//如果有一行或者一列可以移动,说明游戏尚未结束
if (checkrow||checkcol)
{
return false;
}
}
return true;
}
void move_up_or_left(const vector<int> &colrow, vector<int> &aftermove)
{
vector<int> tmp;
//将colrow中非0元素按照从上到下或者从左到右的顺序放到tmp中
for(int i=; i<; i++)
{
if(colrow[i]!=)
tmp.push_back(colrow[i]);
}
//安顺序将相邻的同值元素相加,计算结果放在tmp2
vector<int> tmp2;
for (unsigned int i=; i<tmp.size(); i++)
{
if (i!=tmp.size()-&&tmp[i]==tmp[i+])
{
tmp2.push_back(tmp[i]*);
i++;
}
else
{
tmp2.push_back(tmp[i]);
}
}
//将计算结果写入aftermove
for (int i=; i<(int)tmp2.size(); i++)
{
aftermove[i]=tmp2[i];
}
}
void move_down_or_right(const vector<int> &colrow, vector<int> &aftermove)
{
vector<int> tmp;
//将colrow中非0元素按照从下到上或者从右到左的顺序放到tmp中
for(int i=; i>=; i--)
{
if(colrow[i]!=)
tmp.push_back(colrow[i]);
}
//计算结果
vector<int> tmp2;
for (int i=; i<(int)tmp.size(); i++)
{
if (i!=tmp.size()-&&tmp[i]==tmp[i+])
{
tmp2.push_back(tmp[i]*);
i++;
}
else
{
tmp2.push_back(tmp[i]);
}
}
//将计算结果写入aftermove,注意afermove数组的索引要从后往前变化
for (int i=; i<(int)tmp2.size(); i++)
{
aftermove[-i]=tmp2[i];
}
}
void moveup(vector<int> &square)
{
for (int i=; i<; i++)
{
//提取一列元素到col
vector<int> col;
extract_col(square, i, col);
//按照规则移动col中的元素,结果放在colaftermove
vector<int> colaftermove();
move_up_or_left(col, colaftermove);
//将移动后的列元素更新到数组square
update_col(square,i,colaftermove);
}
}
void movedown(vector<int> &square)
{
for (int i=; i<; i++)
{
//提取一列元素到col
vector<int> col;
extract_col(square, i, col);
//按照规则移动col中的元素,结果放在colaftermove
vector<int> colaftermove();
move_down_or_right(col, colaftermove);
//将移动后的列元素更新到数组square
update_col(square,i,colaftermove);
}
}
void moveleft(vector<int> &square)
{
for (int i=; i<; i++)
{
//提取一行元素到row
vector<int> row;
extract_row(square, i, row);
//按照规则移动row中的元素,结果放在rowaftermove
vector<int> rowaftermove();
move_up_or_left(row, rowaftermove);
//将移动后的行元素更新到数组square
update_row(square,i,rowaftermove);
}
}
void moveright(vector<int> &square)
{
for (int i=; i<; i++)
{
//提取一行元素到row
vector<int> row;
extract_row(square, i, row);
//按照规则移动row中的元素,结果放在rowaftermove
vector<int> rowaftermove();
move_down_or_right(row, rowaftermove);
//将移动后的行元素更新到数组square
update_row(square,i,rowaftermove);
}
}
bool check_state_change(const vector<int>& oldsquare, const vector<int>& newsquare)
{
return oldsquare!=newsquare;
}
void add2random(vector<int>& square)
{
//统计0元素在数组中的索引
vector<int> zeroidx;
for (int i=; i<; i++)
{
if (square[i]==)
{
zeroidx.push_back(i);
}
}
//0元素的个数
int zerocount=zeroidx.size();
//如果没有0元素
if (zerocount==)
{
return;
}
//随机选一个数,当然这个数不能超过0元素的个数
int random_number=rand()%zerocount;
//找到这个0元素在square中的索引
int choose_one_idx=zeroidx[random_number];
square[choose_one_idx]=;
}
2048控制台程序:一份帝国理工C++作业的更多相关文章
- 数独检测器:帝国理工C++作业
#include <fstream> #include <vector> #include <iostream> #include <string> u ...
- win10控制台程序printf死锁问题
昨天遇到一个奇葩的问题,服务器正常运行但经常出现客户端无法连接的问题.我很好奇,在accept返回的地方断点,发现无法accept了.这就怪了,以前从没出现过这种情况.服务器网络用的asio,无法ac ...
- Quartz+log4net实现控制台程序定时运行,并且记录日志
c# 控制台程序定时运行,并记录日志. 组件Quartz + log4net Quartz定时运行程序,log4net记录日志. 首先建立控制台程序"QuartzTest" 安装Q ...
- C运行时库(C Run-time Library)详解(提供的另一个最重要的功能是为应用程序添加启动函数。Visual C++对控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)
一.什么是C运行时库 1)C运行时库就是 C run-time library,是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 2)C 语言是所谓的“ ...
- VC++中的C运行时库浅析(控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)
1.概论 运行时库是程序在运行时所需要的库文件,通常运行时库是以LIB或DLL形式提供的.C运行时库诞生于20世纪70年代,当时的程序世界还很单纯,应用程序都是单线程的,多任务或多线程机制在此时还属于 ...
- 在.NET Core控制台程序中使用依赖注入
之前都是在ASP.NET Core中使用依赖注入(Dependency Injection),昨天遇到一个场景需要在.NET Core控制台程序中使用依赖注入,由于对.NET Core中的依赖注入机制 ...
- 使用 CommandLineApplication 类创建专业的控制台程序
闲话 在很久很久以前,电脑是命令行/终端/控制台的天下,那屏幕上的光标在行云流水般的键盘敲击下欢快地飞跃着,那一行行的字符输出唰唰唰地滚动着--直到 Windows 95 的出现(那时候我还不知道苹果 ...
- C#基础-关于用json给控制台程序传值的坑
上周遇到了一个非常诡异的坑,首先写了两个程序,第一个程序输出成dll,第二个程序是控制台程序. 在第一个程序里,我使用了process去启动第二个程序,同时传入了一个Json作为参数,即: Proce ...
- 你们信不信一句Console.WriteLine就能让你的控制台程序失去响应
好久没更新博客了,今天是扒衣见君节,难得闲下来就来说说一个最近有趣的发现吧. 首先废话不多说,直接上代码吧 class Program { static void Main(string[] args ...
随机推荐
- QT编写上位机程序一定要初始化变量以及谨慎操作指针
背景: 在编写QT上位机界面时,界面在运行的时候经常出现卡死或者直接挂掉的怪现象. 正文: 上位机有个函数为check_receive():该函数的作用为定时调用循环检测USB是否有数据.若有,则将信 ...
- Mac 用户组:staff、 wheel、admin 的区别
所有的用户都属于 staff 组, 只有具有管理员性质的用户位于 wheel 组中. wheel 是一个特殊的用户组,该组的用户可以使用 su 切换到 root,而 staff 组是所有普通用户的集合 ...
- js读取修改创建txt文本类型文件(.ini)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Nginx初学者指南
Starting, Stopping, and Reloading Configuration To start nginx, run the executable file. Once nginx ...
- python spark 配置
前提:已经装好 java 1.8 和 hadoop 2.7 1. 下载解压放后的目录 /Users/gao/spark-1.4.1-bin-hadoop2.6 2. 在~/.bash_profile ...
- Linux使用手册-vi使用手册
vi使用手册 VI是unix上最常用的文本编辑工具,作为unix软件测试人员,有必要熟练掌握它. 进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filen ...
- 基于php的snmp管理端开发
一.系统环境: 操作系统:CentOS 5.4 内核:Linux_2.6 编译环境:gcc 4.1.2 代码版本:php-5.2.8.tar ...
- caffe学习系列(1):图像数据转换成db(leveldb/lmdb)文件
参考:http://www.cnblogs.com/denny402/p/5082341.html 上述博文用caffe自带的两张图片为例,将图片转为db格式.博主对命令参数进行了详细的解释,很赞. ...
- BZOJ 3445: [Usaco2014 Feb] Roadblock
Description 一个图, \(n\) 个点 \(m\) 条边,求将一条边距离翻倍后使 \(1-n\) 最短路径增加的最大增量. Sol Dijstra. 先跑一边最短路,然后枚举最短路,将路径 ...
- 一个按比特位拷贝数据的函数copybits
一个按比特位拷贝数据的函数 没有进行特别的优化.其实还可以在拷贝源开始位置和目标开始位置是2的整数倍位置的时候进行优化. 说明 这个函数用于从src数组首地址跳过sbb个字节,又跳过ssb个比特位,拷 ...