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=0; i<square.size(); i++)
    {
        cout<<square.at(i)<<"\t";
        if ((i+1)%4==0)
        {
            cout<<endl;
        }
    }
    cout<<endl;
}
void set_default_square(vector<int> &square)
{
    for (int i=0; i<16; i++)
    {
        square.push_back(0);
    }
    square.back()=2;
}
int coordtoidx(int row, int col)
{
    return row*4+col;
}
void extract_row(const vector<int>& square, int row, vector<int>& output)
{
    for (int c=0; c<4;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=0; c<4; 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=0; r<4;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=0; r<4;r++)
    {
        int idx=coordtoidx(r,col);
        square[idx]=newcol[r];
    }
}
bool check_moveable(const vector<int> &rowcol)
{
    int a=rowcol[0];
    int b=rowcol[1];
    int c=rowcol[2];
    int d=rowcol[3];
    //首先检测是否含有0元素
    if(a*b*c*d==0)
        return true;
    if (a==b||b==c||c==d)
    {
        return true;
    }
    return false;
}
bool checkgameover(const vector<int> &square)
{
    for (int i=0; i<4; 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=0; i<4; i++)
    {
        if(colrow[i]!=0)
            tmp.push_back(colrow[i]);
    }
    //安顺序将相邻的同值元素相加,计算结果放在tmp2
    vector<int> tmp2;
    for (unsigned int i=0; i<tmp.size(); i++)
    {
        if (i!=tmp.size()-1&&tmp[i]==tmp[i+1])
        {
            tmp2.push_back(tmp[i]*2);
            i++;
        }
        else
        {
            tmp2.push_back(tmp[i]);
        }
    }
    //将计算结果写入aftermove
    for (int i=0; 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=3; i>=0; i--)
    {
        if(colrow[i]!=0)
            tmp.push_back(colrow[i]);
    }
    //计算结果
    vector<int> tmp2;
    for (int i=0; i<(int)tmp.size(); i++)
    {
        if (i!=tmp.size()-1&&tmp[i]==tmp[i+1])
        {
            tmp2.push_back(tmp[i]*2);
            i++;
        }
        else
        {
            tmp2.push_back(tmp[i]);
        }
    }
    //将计算结果写入aftermove,注意afermove数组的索引要从后往前变化
    for (int i=0; i<(int)tmp2.size(); i++)
    {
        aftermove[3-i]=tmp2[i];
    }
}
void moveup(vector<int> &square)
{
    for (int i=0; i<4; i++)
    {
        //提取一列元素到col
        vector<int> col;
        extract_col(square, i, col);
        //按照规则移动col中的元素,结果放在colaftermove
        vector<int> colaftermove(4);
        move_up_or_left(col, colaftermove);
        //将移动后的列元素更新到数组square
        update_col(square,i,colaftermove);
    }
}
void movedown(vector<int> &square)
{
    for (int i=0; i<4; i++)
    {
        //提取一列元素到col
        vector<int> col;
        extract_col(square, i, col);
        //按照规则移动col中的元素,结果放在colaftermove
        vector<int> colaftermove(4);
        move_down_or_right(col, colaftermove);
        //将移动后的列元素更新到数组square
        update_col(square,i,colaftermove);
    }
}
void moveleft(vector<int> &square)
{
    for (int i=0; i<4; i++)
    {
        //提取一行元素到row
        vector<int> row;
        extract_row(square, i, row);
        //按照规则移动row中的元素,结果放在rowaftermove
        vector<int> rowaftermove(4);
        move_up_or_left(row, rowaftermove);
        //将移动后的行元素更新到数组square
        update_row(square,i,rowaftermove);
    }
}
void moveright(vector<int> &square)
{
    for (int i=0; i<4; i++)
    {
        //提取一行元素到row
        vector<int> row;
        extract_row(square, i, row);
        //按照规则移动row中的元素,结果放在rowaftermove
        vector<int> rowaftermove(4);
        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=0; i<16; i++)
    {
        if (square[i]==0)
        {
            zeroidx.push_back(i);
        }
    }
    //0元素的个数
    int zerocount=zeroidx.size();
    //如果没有0元素
    if (zerocount==0)
    {
        return;
    }
    //随机选一个数,当然这个数不能超过0元素的个数
    int random_number=rand()%zerocount;
    //找到这个0元素在square中的索引
    int choose_one_idx=zeroidx[random_number];
    square[choose_one_idx]=2;
}
时间: 2024-07-31 19:29:32

2048控制台程序:一份帝国理工C++作业的相关文章

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

#include <fstream> #include <vector> #include <iostream> #include <string> using namespace std; bool check_sudoku(const vector<int>& input); int coordtoidx(int row, int col); void extract_row(const vector<int>&

Windows控制台程序“选定模式”的问题

最近用Nodejs写了个代理程序,一直用的好好的,木有问题,今天突然发现不能用了,使用telnet去连代理的端口也能连通,可是服务就是不能正常使用,提示连接超时. 当时猜测是Nodejs的某个地方阻塞了,分析了下代码,怎么也想不明白不能有阻塞的地方啊. 又是各种倒腾,后来发现一个奇怪的问题,我把鼠标放到Nodejs的控制台上,默认进入了编辑模式,而且整个应用的标题变成了"选定 XXXX"这种形式,我想退出程序,需要按两次Ctrl+C,难道是这的问题? 又来有测试了下,果真还是这的问题,

VS2017新建windows控制台程序打印中文乱码问题

最近刚换上VS2017,由于手头又要做个MFC的程序,所以写控制台程序做功能测试,然后发现居然乱码了. 于是用VS2017新建windows控制台应用程序,在main函数种加一句printf("你好");后,运行结果依然乱码 用notapad++打开该文件后,点击菜单栏的编码一项,发现是UTF-8无BOM格式编码,然后改成以ANSI格式编码后 也就是说VS是用UTF-8来编码代码文件的,编译出的程序中字符串也是按照UTF-8编码的,而控制台却是按照ANSI编码来理解的. 打个比方,A用

.net开发环境的认识,控制台程序的创建,输出,输入,定义变量,变量赋值,值覆盖,值拼接,值打印 两种数据类型,整形类型转换

首先感谢向立凯老师带我走进.net这个很好的软件开发程序.通过两天的学习在这个领域的了解也多了很多,让大家先了解一下c#语言 c#是一种全新且简单.安全.快捷面向对象的程序设计语言.是专门为.net应用开发的语言..net的开发都基于一个统一的开发环境 Visual Studio.net.下面我们来看看怎么在Visual Studio.net.下创建以新的项目: 1.打开 2.新建一个项目 通过执行文件-新建-项目菜单命令,会弹出一个新建项目对话框.在这个对话框中选择开发语言为c#,选择框架版本

2017-2-17 c#基础学习 (控制台程序的创建,输出,输入,定义变量,变量赋值,值覆盖,值拼接,值打印)

1 控制台程序的创建 > 新建项目  ,选择 c#,  框架选择4.0 , 选择控制应用台程序, 选择文件保存位置 修改名字. 2 c#输出与输入 >在main函数中编写代码 >在编写时可以先插入Console.ReadLine();防止程序闪退 > Console.Write("实例语句");//不换行输出 Console.WriteLine("示例语句");//换行输出 Console.ReadLine();//等待用户输入 防止闪退 结

控制台程序添加滚轮滑动支持

控制台程序默认只能通过拖动滚动条来查看窗口中打印的内容,操作起来十分不方便. 本文通过多线程技术为控制台窗体添加鼠标滚轮滑动功能.值得注意的是,在有内容输出时,窗口会自动定位到输出的光标处: 这种情况最好是先暂停住主线程,然后再滚动鼠标查看打印的内容,查看完毕后,再继续执行主线程. 首先,需要让控制台程序的屏幕缓冲区高度 > 窗口高度(此时窗口右侧会产生滚动条),否则无需滚动窗口. 下列代码实现了如下功能: (1)滚动鼠标滑动窗口 (2)按空格键,暂停/继续主线程 #include <wind

利用管道获取控制台程序的标准输出

1.该程序调用控制台程序hello.exe,通过管道获取到hello.exe的标准输出数据,并打印到当前程序的标准输出. #include <Windows.h> #include <iostream> #include <string> using namespace std; void invoke(string exe); int main(int argc, char* argv[]) { string exe = "hello.exe";

VS win32命令控制台程序与单片机串口数据传输

最近有个小的训练 大致是需要用摄像头检测圆,然后把圆的xy坐标发送给单片机. 但是网上大部分都是基于MFC串口控件的例程.大海捞针找到了个win32命令控制台的串口例程 ,自己改了一下贡献出来. 直接调用API实现串口通信 两个例程 如果编译运行有问题 直接复制源文件到新win32命令工程中运行 平台-VS2013-win32 例程1:摄像头识别小圆,然后通过串口输出小圆的xy坐标.单片机可以直接接受,具体串口配置自己配置.摄像头需要 opencv的库,我的库是opencv2.4.12. 例程2

重温delphi之控制台程序:Hello World!

原文:重温delphi之控制台程序:Hello World! 这二天用c#开发ActiveX时,发现不管怎么弄,c#就是没办法生成ocx的纯正activeX控件,而且还要强迫用户安装巨大的.net framework(我只是想做一个简单截屏功能的activeX整合到silverlight聊天室中),于是想起了曾经用过一年的delphi,虽然时过境迁,现在早以是.net的天下,但是不可否认,delphi仍是win32原生程序最佳的开发工具之一. 关于Delphi的语法学习,可以参见这个chm文档,