当前位置: 首页 > 工具软件 > n2048 > 使用案例 >

c++简单实现2048

韦睿
2023-12-01

周末实训老师要求做一个2048

查阅大量资料,用c++简单实现了一下

#include <iostream>
#include<stdlib.h>
#include <iomanip>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string>
#include <conio.h>
#define N 4
using namespace std;

class Game {
public:
	int board[N][N]{ 0 };//定义棋盘的大小
	void setchessboard();// 初始棋盘生成
	void printchessboard();//打印棋盘
	void up();
	void down();
	void left();
	void right();// 上下左右四步操作
	int score();//  记录分数
	int ifgameover();// 判断游戏是否结束
};
//Game类,包含二位数组的棋盘、打印棋盘、2048上下左右的操作、计分、以及游戏是否结束的判断

void Game::setchessboard() {               // 初始棋盘生成
	srand((unsigned)time(NULL));
	int x1, y1, x2, y2;
	int num1, num2;
	num1 = rand() % 100;
	num2 = rand() % 100;//num1、num2生成随机数对100取余,大于20时生成2,小于20时生成4
	x1 = rand() % N;
	y1 = rand() % N;//x1,y1控制随机生成数的位置,生成随机数对4取余,能得到0、1、2、3正好对应4*4的数组的下标
	if (num1 > 20) {
		board[x1][y1] = 2;
	}
	else {
		board[x1][y1] = 4;
	}
	do {
		x2 = rand() % N;
		y2 = rand() % N;
	} while (x1 == x2 && y1 == y2);//保证两个生成随机的2或者4位置的不重复性
	if (num2 > 20) {
		board[x2][y2] = 2;
	}
	else {
		board[x2][y2] = 4;
	}
}

void Game::printchessboard() {   // 棋盘的打印实现
	cout << "------------------------" << endl;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cout << "|" <<setw(4) << board[i][j] << "|";
		}
		cout << endl;
		cout << "------------------------" << endl;
	}
}

void Game::up() {//向上合并,第一行不用向上合并。后一行向前一行来看判断操作。
	int h = 0;//定义h判断是否要在为0的位置上生成新的2或4
	for (int a = 1; a < N; a++) {
		for (int b = 0; b < N; b++) {
			if (board[a][b] != 0 && board[a - 1][b] == 0) {//出现了0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
			if (board[a - 1][b] == board[a][b] && board[a - 1][b] != 0) {//有数可以合并,合并后会出现0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
		}
	}
	for (int c = 0; c < N - 1; c++) {//第一行到最后一行的前一行需要操作
		for (int a = c + 1; a > 0; a--) {//从下一行向上一行扫描
			for (int b = 0; b < N; b++) {
				if (board[a - 1][b] == 0) {//上一行的数要是为0,就进行交换
					board[a - 1][b] = board[a][b];
					board[a][b] = 0;// 从上往下进行交换
				}
			}
		}
	}
	for (int a = 1; a < N; a++) {
		for (int b = 0; b < N; b++) {
			board[a - 1][b] == board[a][b] ? board[a - 1][b] *= 2, board[a][b] = 0 : board[a][b] = board[a][b]; //上下两个数是否相等,相等就上面的值*2,下面值变成0(等价于向上合并),不相等就不进行操作
		}
	}
	for (int c = 0; c < N - 1; c++) {//第一行到最后一行的前一行需要操作
		for (int a = c + 1; a > 0; a--) {//从下一行向上一行扫描
			for (int b = 0; b < N; b++) {
				if (board[a - 1][b] == 0) {//上一行的数要是为0,就进行交换
					board[a - 1][b] = board[a][b];
					board[a][b] = 0;// 从上往下进行交换
				}
			}
		}
	}//合并操作后再进行一次上移操作,让值都跑到上面去,既进行向上合并操作
	if (h) {
		srand((unsigned)time(NULL));
		int x, y;
		do {
			x = rand() % N;
			y = rand() % N;
		} while (board[x][y] != 0);//在为0的位置才能生成新的2或者4
		int num = rand() % 100;//与初始化棋盘一样,用来控制在0上生成的数是2还是4
		if (num > 20) {
			board[x][y] = 2;
			h = 0;
		}
		else {
			board[x][y] = 4;
			h = 0;
		}
	}
}

void Game::down() { // 向下合并,最后一行不需要向下进行合并。前一行向后一行判断操作。
	int h = 0;//定义h判断是否要在为0的位置上生成新的2或4
	for (int a = N - 2; a >= 0; a--) {
		for (int b = 0; b < N; b++) {
			if (board[a][b] != 0 && board[a + 1][b] == 0) {//出现了0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
			if (board[a + 1][b] == board[a][b] && board[a + 1][b] != 0) {//有数可以合并,合并后会出现0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
		}
	}
	for (int c = N - 1; c > 0; c--) {//最后一行的前一行到第一行需要操作
		for (int a = c - 1; a < N; a++) {//从上一行向下一行扫描
			for (int b = 0; b < N; b++) {
				if (board[a + 1][b] == 0) {//下一行的数要是0,就进行交换
					board[a + 1][b] = board[a][b];
					board[a][b] = 0;
				}
			}
		}
	}
	for (int a = N - 2; a >= 0; a--) {
		for (int b = 0; b < N; b++) {
			board[a + 1][b] == board[a][b] ? board[a + 1][b] *= 2, board[a][b] = 0 : board[a][b] = board[a][b];//上下两个数是否相等,相等就下面的值*2,上面值变成0(等价于向下合并),不相等就不进行操作
		}
	}
	for (int c = N - 1; c > 0; c--) {//最后一行的前一行到第一行需要操作
		for (int a = c - 1; a < N; a++) {//从上一行向下一行扫描
			for (int b = 0; b < N; b++) {
				if (board[a + 1][b] == 0) {//下一行的数要是0,就进行交换
					board[a + 1][b] = board[a][b];
					board[a][b] = 0;
				}
			}
		}
	}//合并操作后再进行一次下移操作,让值都跑到下面去,既进行向下合并操作
	if (h) {
		srand((unsigned)time(NULL));
		int x, y;
		do {
			x = rand() % N;
			y = rand() % N;
		} while (board[x][y] != 0);//在为0的位置才能生成新的2或者4
		int num = rand() % 100;//与初始化棋盘一样,用来控制在0上生成的数是2还是4
		if (num > 20) {
			board[x][y] = 2;
			h = 0;
		}
		else {
			board[x][y] = 4;
			h = 0;
		}
	}
}

void Game::left() { // 向左合并,第一列不用合并。右一列向左一列判断操作
	int h = 0;//定义h判断是否要在为0的位置上生成新的2或4
	for (int b = 1; b < N; b++) {
		for (int a = 0; a < N; a++) {
			if (board[a][b] != 0 && board[a][b - 1] == 0) {//出现了0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
			if (board[a][b - 1] == board[a][b] && board[a][b] != 0) {//有数可以合并,合并后会出现0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
		}
	}
	for (int c = 0; c < N - 1; c++) {//左第一列到右最后一列的前一列需要操作
		for (int b = c + 1; b > 0; b--) {//从右一列向左一列扫描
			for (int a = 0; a < N; a++) {
				if (board[a][b - 1] == 0) {//左边的数为0,就进行交换
					board[a][b - 1] = board[a][b];
					board[a][b] = 0;
				}
			}
		}
	}
	for (int b = 1; b < N; b++) {
		for (int a = 0; a < N; a++) {
			board[a][b - 1] == board[a][b] ? board[a][b - 1] *= 2, board[a][b] = 0 : board[a][b - 1] = board[a][b - 1];//左右两个数是否相等,相等就左边的值*2,右边值变成0(等价于向左合并),不相等就不进行操作
		}
	}
	for (int c = 0; c < N - 1; c++) {//左第一列到右最后一列的前一列需要操作
		for (int b = c + 1; b > 0; b--) {//从右一列向左一列扫描
			for (int a = 0; a < N; a++) {
				if (board[a][b - 1] == 0) {//左边的数为0,就进行交换
					board[a][b - 1] = board[a][b];
					board[a][b] = 0;
				}
			}
		}
	}//合并操作后再进行一次左移操作,让值都跑到左边去,既进行向左合并操作
	if (h) {
		srand((unsigned)time(NULL));
		int x, y;
		do {
			x = rand() % N;
			y = rand() % N;
		} while (board[x][y] != 0);//在为0的位置才能生成新的2或者4
		int num = rand() % 100;//与初始化棋盘一样,用来控制在0上生成的数是2还是4
		if (num > 20) {
			board[x][y] = 2;
			h = 0;
		}
		else {
			board[x][y] = 4;
			h = 0;
		}
	}
}

void Game::right() { // 向右合并,最后一列不用合并。左一列向右一列判断操作
	int h = 0;//定义h判断是否要在为0的位置上生成新的2或4
	for (int b = N - 2; b >= 0; b--) {
		for (int a = 0; a < N; a++) {
			if (board[a][b] != 0 && board[a][b + 1] == 0) {//出现了0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
			if (board[a][b + 1] == board[a][b] && board[a][b] != 0) {//有数可以合并,合并后会出现0,需要生成2或4,h赋值为1
				h = 1;
				break;
			}
		}
	}
	for (int c = N - 1; c > 0; c--) {//左边第二列到最后一列需要操作
		for (int b = c - 1; b < N - 1; b++) {//从左一列向右一列扫描
			for (int a = 0; a < N; a++) {
				if (board[a][b + 1] == 0) {//右边的数为0,就进行交换
					board[a][b + 1] = board[a][b];
					board[a][b] = 0;
				}
			}
		}
	}
	for (int b = N - 2; b >= 0; b--) {
		for (int a = 0; a < N; a++) {
			board[a][b + 1] == board[a][b] ? board[a][b + 1] *= 2, board[a][b] = 0 : board[a][b] = board[a][b];//左右两个数是否相等,相等就右边的值*2,左边值变成0(等价于向左合并),不相等就不进行操作
		}
	}
	for (int c = N - 1; c > 0; c--) {//左边第二列到最后一列需要操作
		for (int b = c - 1; b < N - 1; b++) {//从左一列向右一列扫描
			for (int a = 0; a < N; a++) {
				if (board[a][b + 1] == 0) {//右边的数为0,就进行交换
					board[a][b + 1] = board[a][b];
					board[a][b] = 0;
				}
			}
		}
	}//合并操作后再进行一次右移操作,让值都跑到右边去,既进行向右合并操作
	if (h) {
		srand((unsigned)time(NULL));
		int x, y;
		do {
			x = rand() % N;
			y = rand() % N;
		} while (board[x][y] != 0);//在为0的位置才能生成新的2或者4
		int num = rand() % 100;//与初始化棋盘一样,用来控制在0上生成的数是2还是4
		if (num > 20) {
			board[x][y] = 2;
			h = 0;
		}
		else {
			board[x][y] = 4;
			h = 0;
		}
	}
}

int Game::score() {//计分函数,返回值为二维数值每一个数的和
	int c = 0;
	for (int a = 0; a < N; a++) {
		for (int b = 0; b < N; b++) {
			c += board[a][b];
		}
	}
	return c;
}

int Game::ifgameover() {//判断游戏是否结束
	int c = 0;//先默认输了
	for (int a = 0; a < N; a++) {
		if (c == 1) break;//c为1,已经判断赢了,跳出
		for (int b = 0; b < N; b++) {
			if (board[a][b] == 2048) {//二维数组中有数字为2048,赢了,c值赋为1
				c = 1;
				break;
			}
		}
	}
	for (int a = 0; a < N; a++) {//检查左右是否有可以合并的
		if (c == 1) break;//c为1,已经判断赢了,跳出
		if (c != 1) {
			for (int b = 0; b < N - 1; b++) {
				if (board[a][b] == 0 || board[a][b] == board[a][b + 1]) {
					c = 2;  //左右还有可以合并的,c值赋为2
					break;
				}
			}
		}
	}
	for (int b = 0; b < N; b++) {//检查上下是否有可以合并的
		if (c == 1) break;//c为1,已经判断赢了,跳出
		if (c != 1) {
			for (int a = 0; a < N - 1; a++) {
				if (board[a][b] == 0 || board[a][b] == board[a + 1][b]) {
					c = 2;//上下还有可以合并的,c值为2
					break;
				}
			}
		}
	}
	return c;//返回c的值,c为0就输了,用计分函数算分,c为2还能继续游戏,c为1就赢了
}

int main()
{

	cout << "—————2048—————" << endl;
	cout << "↑、向上操作;↓、向下操作;←、向左操作;→、向右操作" << endl;
	Game game;
	game.setchessboard();
	game.printchessboard();//打印生成两个随机数的初始棋盘
	while (char ch = _getch()) {//获取用户输入的字符,用ascll码判断是↑↓←→中的哪一个
		int b = game.ifgameover();//b存放判断游戏是否结束的值,0输了,1赢了,2还能继续
		int c = game.score();//c计算输了的时候的分数
		switch (ch) {
		case 75://75是左的ascll码
			game.left();  // 调用函数 void Game::left()执行左操作
			switch (b) {
			case 0:
				system("CLS");//清屏
				cout << "Loser!!!" << endl << "Your point is: " << c << endl;  break;
			case 1:
				system("CLS");
				cout << "You win!" << endl; break;
			case 2:
				system("CLS");
				game.printchessboard(); break;
			}
			break;
		case 72://72是上的ascll码
			game.up(); // 调用函数void Game::up()执行上操作
			switch (b) {
			case 0:
				system("CLS");
				cout << "Loser!!!" << endl << "Your point is:" << c << endl;  break;
			case 1:
				system("CLS");
				cout << "You win!" << endl; break;
			case 2:
				system("CLS");
				game.printchessboard(); break;
			}
			break;
		case 80://80是下的ascll码
			game.down(); // 调用函数void Game::down()执行下操作
			switch (b) {
			case 0:
				system("CLS");
				cout << "Loser!!!" << endl << "Your point is:" << c << endl;  break;
			case 1:
				system("CLS");
				cout << "You win!" << endl; break;
			case 2:
				system("CLS");
				game.printchessboard(); break;
			}
			break;
		case 77://77是右的ascll码
			game.right(); // 调用函数void Game::right()执行右操作
			switch (b) {
			case 0:
				system("CLS");
				cout << "Loser!!!" << endl << "Your point is:" << c << endl;  break;
			case 1:
				system("CLS");
				cout << "You win!" << endl; break;
			case 2:
				system("CLS");
				game.printchessboard(); break;
			}
			break;
		}
	}
	return 0;
}

 类似资料: