#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++作业的更多相关文章

  1. 数独检测器:帝国理工C++作业

    #include <fstream> #include <vector> #include <iostream> #include <string> u ...

  2. win10控制台程序printf死锁问题

    昨天遇到一个奇葩的问题,服务器正常运行但经常出现客户端无法连接的问题.我很好奇,在accept返回的地方断点,发现无法accept了.这就怪了,以前从没出现过这种情况.服务器网络用的asio,无法ac ...

  3. Quartz+log4net实现控制台程序定时运行,并且记录日志

    c# 控制台程序定时运行,并记录日志. 组件Quartz + log4net Quartz定时运行程序,log4net记录日志. 首先建立控制台程序"QuartzTest" 安装Q ...

  4. C运行时库(C Run-time Library)详解(提供的另一个最重要的功能是为应用程序添加启动函数。Visual C++对控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)

    一.什么是C运行时库 1)C运行时库就是 C run-time library,是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 2)C 语言是所谓的“ ...

  5. VC++中的C运行时库浅析(控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)

    1.概论 运行时库是程序在运行时所需要的库文件,通常运行时库是以LIB或DLL形式提供的.C运行时库诞生于20世纪70年代,当时的程序世界还很单纯,应用程序都是单线程的,多任务或多线程机制在此时还属于 ...

  6. 在.NET Core控制台程序中使用依赖注入

    之前都是在ASP.NET Core中使用依赖注入(Dependency Injection),昨天遇到一个场景需要在.NET Core控制台程序中使用依赖注入,由于对.NET Core中的依赖注入机制 ...

  7. 使用 CommandLineApplication 类创建专业的控制台程序

    闲话 在很久很久以前,电脑是命令行/终端/控制台的天下,那屏幕上的光标在行云流水般的键盘敲击下欢快地飞跃着,那一行行的字符输出唰唰唰地滚动着--直到 Windows 95 的出现(那时候我还不知道苹果 ...

  8. C#基础-关于用json给控制台程序传值的坑

    上周遇到了一个非常诡异的坑,首先写了两个程序,第一个程序输出成dll,第二个程序是控制台程序. 在第一个程序里,我使用了process去启动第二个程序,同时传入了一个Json作为参数,即: Proce ...

  9. 你们信不信一句Console.WriteLine就能让你的控制台程序失去响应

    好久没更新博客了,今天是扒衣见君节,难得闲下来就来说说一个最近有趣的发现吧. 首先废话不多说,直接上代码吧 class Program { static void Main(string[] args ...

随机推荐

  1. 用SQLite查看编辑android导出的微信聊天记录

    上一篇我们已经能够完成文字版微信聊天记录导出android了,也即复制或剪切MicroMsg.db文件到电脑,以.db格式结尾的文件是数据库文件(database document),需要安装相关数据 ...

  2. sql批量更换dedecms文章来源和作者

    前面写了一篇修改dedecms默认文章来源 "未知"改为关键词,那个是修改以后发布的文章“来源”才会变成自己设定的关键词,如果修改之前已经有很多文章了,那些文章“来源”还是显示“未 ...

  3. MySQL Python教程(4)

    Class cursor.MySQLCursorBuffered 该类从Class cursor.MySQLCursorBuffered继承,如果需要,可以在执行完SQL语句后自动缓冲结果集合.imp ...

  4. DAY2 Python 标准库 -> Getpass 模块 -> 命令行下输入密码的方法.

    getpass 模块 getpass 模块提供了平台无关的在命令行下输入密码的方法. getpass(prompt) 会显示提示字符串, 关闭键盘的屏幕反馈, 然后读取密码. 如果提示参数省略, 那么 ...

  5. oracle asm 概念

    automated storage management ,即自动存储管理,简称asm .. 在oracle 10g 这个版本之前,管理一个大型数据库成千上万的数据文件对数据库管理员来说是一个既无技术 ...

  6. HDU 5053 the Sum of Cube

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5053 解题报告:用来陶冶情操的题,求a到b的三次方的和. #include<stdio.h> ...

  7. iOS中多线程原理与runloop介绍

    一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...

  8. ios中二维码的使用之一: 二维码的生成

    iOS在7之后,具备了原生的二维码生成API; 生成二维码的准备:  #import <CoreImage/CoreImage.h> 导入框架: 开始生成: //1- 创建过滤器 CIFi ...

  9. linux中diff命令用法

    diff 命 令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版 本的diff还支持二进制文件.diff程 ...

  10. BZOJ 3665: maths

    Sol 矩阵乘法+快速幂+欧拉定理. 首先观察题目可以发现 \(A_n\) 可以表示成关于 \(K\) 和 \(A_0\) 的几次幂的形式. \(A_0\) 就比较简单了 \(m^n\) 所以第一部分 ...