2048控制台版
文章目录
实现效果:
库函数使用:
cpp
#include<iostream>
#include<Windows.h>//键盘输入读取
#include<iomanip>//控制格式
#include<ctime>//生成随机数种子
初始化变量
cpp
int const ROW = 4;
int const COL = 4;
int game[ROW][COL] = { 0};
int const GAME_CONTINUE = 1;
int const GAME_WIN = 2;
int const GAME_LOSE = 3;
int const UP = 1;
int const DOWN = 2;
int const LEFT = 3;
int const RIGHT = 4;
功能函数实现:
cpp
int Judge();//判断游戏状态
bool CreateNumber();//生成下一个数
void Print();//打印初始化界面
void Process(int move);//实现移动效果
int Input();//读取键盘输入
bool is_Empty(int const a);//可不需要,判断某行谋列是否为0
状态判断函数int Judge();
设计思路:除去最后一行,逐行逐列的检查正下方和右方有无可以消去的元素
cpp
int Judge() {
int count = 0;
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (game[i][j] == 2024)
{
return GAME_WIN;
}
if (!is_Empty(game[i][j])) {
count++;
if (i == ROW - 1) {
if (j != COL - 1&&(game[i][j]==game[i][j+1])) {
count--;
}
}
else {
if (j != COL - 1) {
if (game[i][j] == game[i][j + 1] || game[i][j] == game[i + 1][j]) {
count--;
}
}
else continue;
}
}
}
}
if (count < ROW * COL)return GAME_CONTINUE;
else return GAME_LOSE;
}
数字生成函数 bool CtreateNumber()
实际思路:rand生成随机数,通过非零情况控制生成2和4的概率
cpp
bool CreateNumber() {
/*int x =0;
int y = 0;*/
int x = -1;
int y = -1;
int times = 0,max_times=ROW*COL;//max_times防止满表的时候无限循环
do {
x = rand() % 4;
y = rand() % 4;
times++;
} while (!is_Empty(game[x][y]) && times <= max_times);//有一个为0就跳出去
//控制得到2和4的概率
int value = rand() % 3;
if (times > max_times) {
return false;
}
else {
if (value == 0)
game[x][y] = 4;
else
game[x][y] = 2;
return true;
}
}
打印游戏界面 void Print()
cpp
void Print() {
system("cls");
/*cout << setfill('=') << setw(5 * COL)<<'='<<endl ;*/
cout << setfill('-') << setw(5 * COL) << '-' << endl;
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (is_Empty(game[i][j])) {
cout <<'|' << setfill(' ')<<setw(4) << ' ';
}
else {
cout << '|' << setfill(' ')<<setw(4) << game[i][j];
}
}
cout << '|' << endl;
cout <<setfill('-') << setw(5 * COL) << '-'<<endl ;
}
}
操作函数void Process()
教训:第一次写的时候写了个count,用来记录上面一行(在UP中)的每一列是否都满足为空或者可以相消,这种操作是错的,因为只要可以相消或者只要有空位,就都应该可以往上走
ps:LEFT和Right的函数实现代码与UP和DOWN类似,把对应的col和row对调一下即可
cpp
void Process(int move) {
if (move == UP) {
for (int row = 1; row < ROW; ++row) {
for (int crow = row; crow >= 1; --crow) {
for (int col = 0; col < COL; col++) {
if (is_Empty(game[crow - 1][col])) {
game[crow - 1][col] = game[crow][col];
game[crow][col] = 0;
}
if (game[crow - 1][col] == game[crow][col]) {
game[crow - 1][col] *= 2;
game[crow][col] = 0;
}
}
}
}
}
if (move == DOWN) {
//注意ROW-2指的是倒数第二排
int count = 0;
for (int row = ROW-2; row>=0; --row) {
//crow<ROW-1
for (int crow = row; crow < ROW-1; ++crow) {
for (int col = 0; col < COL; col++) {
if (is_Empty(game[crow + 1][col])) {
game[crow + 1][col] = game[crow][col];
game[crow][col] = 0;
}
else if(game[crow+1][col]==game[crow][col])
{
game[crow + 1][col] *= 2;
game[crow][col] = 0;
}
}
}
}
}
}
键盘输入函数int Input()
说明:sleep函数是为了减少误触,降低敏感性
cpp
int Input() {
int directionUP = 0;
int directionDOWN =0;
int directionLeft = 0;
int directionRight = 0;
int direction = 0;
while (true) {
directionUP = GetAsyncKeyState(VK_UP);
directionDOWN = GetAsyncKeyState(VK_DOWN);
directionLeft = GetAsyncKeyState(VK_LEFT);
directionRight = GetAsyncKeyState(VK_RIGHT);
if (directionUP) {
/*cout << "UP" << endl;*/
direction= UP;
break;
}
if (directionDOWN) {
/*cout << "DOWN" << endl;*/
direction= DOWN;
break;
}
if (directionLeft) {
/*cout << "LEFT" << endl;*/
direction= LEFT;
break;
}
if (directionRight) {
/*cout << "RIGHT" << endl;*/
direction= RIGHT;
break;
}
Sleep(100);
}
return direction;
}
主函数
cpp
int main() {
srand((unsigned int)time(0));
CreateNumber();
Print();
while (true) {
int gameState = Judge();
int direction = Input();
if ((direction)&&(gameState == GAME_CONTINUE)) {
/*CreateNumber();
Print();
Process(direction);*/
Process(direction);
CreateNumber();
Print();
Sleep(100);//防止太敏感
}
else if (gameState == GAME_WIN) {
Print();
cout << "You Win" << endl;
break;
}
else if (gameState == GAME_LOSE) {
Print();
cout << "Sorry,You Lose" << endl;
break;
}
}
return 0;
}
彩蛋:
如果时间足够,会再出有前端版本的实现代码!