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; }