C++学习笔记
试着写了一下
用一个二维数组模拟游戏棋盘,在二维数组上的空位置随机位置生成数字2或4,然后接收用户操作,向指定的方向移动并合并数字,再次生成数字,如此往复,直到游戏结束。
这里有几个问题:
- 游戏结束条件
- 如何保证随机生成的位置不会覆盖已有数字
- 如何移动与合并数字
游戏结束的条件为,随机生成数字后棋盘为满,且此时已经没有数字可以再合并。而为了保证随机生成的位置不会覆盖已有数字,可以将还没空的数字单独存在一个数组中,生成数字时在这个数组中生成。
移动与合并数字可以根据用户输入的操作依次扫描每排或每列的相邻两个非零数字,判断是否相同,如果有相同数字则可以移动,依次将可合并的数字合并,并排列到用户输入的方向即可
具体实现:
//游戏类
//提供棋盘与函数接口
//2048.h
#pragma once
#include <iostream>
#include<ctime>
#include<conio.h>
using namespace std;
#define GAMESIZE 4
class Game_2048
{
public:
Game_2048();
void ShowChessBoard();
bool MakeNum();
void UpDateEA();
bool Move(char op);
bool MoveAble();
bool IsFull();
char direction();
bool GameOver(bool end);
~Game_2048();
private:
int number_array[GAMESIZE][GAMESIZE];
int **empty_array;
int counter;
};
//编写游戏规则,调用函数接口
//game.cpp
#include<iostream>
using namespace std;
#include"2048.h"
int main()
{
Game_2048 game;
bool is_moved = 1;//用于标记当前输入的方向是否可以移动数字
bool is_created = 1;//标记随机数字是否生成成功
while (1)
{
if(is_moved)//当棋盘内数字产生移动才生成新的数字
is_created = game.MakeNum();
game.ShowChessBoard();//输出当前棋盘
if (game.GameOver(is_created))//GameOver()判断当前游戏是否结束
return 0;
cout << "请操作:(W/A/D/S)" << endl;
char op;
op = game.direction();//接收操作
cout << op <<endl;
is_moved = game.Move(op);
system("cls");
}
system("pause");
return 0;
}
具体的函数实现:
//2048.cpp
#include <iostream>
using namespace std;
#include"2048.h"
Game_2048::Game_2048()
{
for (int i = 0; i < GAMESIZE; i++)
{
for (int j = 0; j < GAMESIZE; j++)
{
this->number_array[i][j] = 0;
}
}
this->counter = 0;
this->UpDateEA();
}
void Game_2048::ShowChessBoard()
{
for (int i = 0; i < GAMESIZE; i++)
{
for (int j = 0; j < GAMESIZE; j++)
{
cout << this->number_array[i][j];
cout << "\t";
}
cout << endl;
cout << endl;
}
}
bool Game_2048::MakeNum()
{
if (this->IsFull())
return 0;
else
{
srand((int)time(0));
int index = rand() % (GAMESIZE*GAMESIZE - counter );
int i = rand() % 3;
if (i % 3)
*this->empty_array[index] = 2;
else
*this->empty_array[index] = 4;
this->counter++;
this->UpDateEA();
return 1;
}
}
void Game_2048::UpDateEA()
{
if (this->empty_array != NULL)
{
delete[] this->empty_array;
this->empty_array = NULL;
}
this->empty_array = new int*[GAMESIZE*GAMESIZE];
int flag = 0;
for (int i = 0; i < GAMESIZE*GAMESIZE ; i++)
{
if (this->number_array[i / GAMESIZE][i % GAMESIZE] == 0)
{
this->empty_array[flag] = &this->number_array[i / GAMESIZE ][i % GAMESIZE];
flag++;
}
}
}
bool Game_2048::IsFull()
{
if (this->counter == GAMESIZE * GAMESIZE)
return 1;
else
return 0;
}
char Game_2048::direction()//读取键盘的方向键
{
int c1 = _getch();
if (c1 == 'w'|| c1 == 'W')return 'u';
if (c1 == 's' || c1 == 'S')return 'd';
if (c1 == 'a' || c1 == 'A')return 'l';
if (c1 == 'd' || c1 == 'D')return 'r';
return 'f';
}
bool Game_2048::MoveAble()
{
if (counter != GAMESIZE * GAMESIZE)
return 1;
else
{
for (int i = 0; i < GAMESIZE; i++)
{
int line1 = 0;
int line2 = 0;
for (int j = 0; j < GAMESIZE; j++)
{
if (this->number_array[i][j] != 0)
{
line1 = this->number_array[i][j];
if (line1 == line2)
return 1;
else
{
line2 = line1;
}
}
}
}
for (int i = 0; i < GAMESIZE; i++)
{
int row1 = 0;
int row2 = 0;
for (int j = 0; j < GAMESIZE; j++)
{
if (this->number_array[j][i] != 0)
{
row1 = this->number_array[j][i];
if (row1 == row2)
return 1;
else
{
row2 = row1;
}
}
}
}
return 0;
}
}
bool Game_2048::Move(char op)
{
if (op == 'u' || op == 'd' || op == 'l' || op == 'r')
{
bool flag = 0;//操作正确后是否移动的标志
int *line1 = NULL, *line2 = NULL;
if (op == 'l' || op == 'r')//左右
{
for (int i = 0; i < GAMESIZE; i++)
{
for (int j = 0; j < GAMESIZE; j++)
{
if (op == 'l')//左移
{
line1 = &this->number_array[i][j];
if (line2 != NULL)
{
if (*line1 == *line2 && *line1 != 0)//合并
{
*line2 += *line1;
*line1 = 0;
flag = 1;
this->counter--;
line2 += 1;
line1 = NULL;
}
else if (*line2 != *line1 && *line1 != 0 && *line2 != 0)//排序
{
if (*(line2 + 1) == 0)
{
*(line2 + 1) = *line1;
*line1 = 0;
line2 += 1;
flag = 1;
}
else
{
line2 = line1;
line1 = NULL;
}
}
else if (*line2 == 0 && *line1 != 0)//排序
{
*line2 = *line1;
*line1 = 0;
flag = 1;
continue;
}
}
else
{
line2 = &this->number_array[i][j];
line1 = NULL;
}
}
else//右移
{
line1 = &this->number_array[i][GAMESIZE - j - 1];
if (line2 != NULL)
{
if (*line1 == *line2 && *line1 != 0)//合并
{
*line2 += *line1;
*line1 = 0;
flag = 1;
this->counter--;
line2 -= 1;
line1 = NULL;
}
else if (*line2 != *line1 && *line1 != 0 && *line2 != 0)//排序
{
if (*(line2 - 1) == 0)
{
*(line2 - 1) = *line1;
*line1 = 0;
line2 -= 1;
flag = 1;
}
else
{
line2 = line1;
line1 = NULL;
}
}
else if (*line2 == 0 && *line1 != 0)//排序
{
*line2 = *line1;
*line1 = 0;
flag = 1;
continue;
}
}
else
{
line2 = &this->number_array[i][GAMESIZE - j - 1];
line1 = NULL;
}
}
}
line2 = NULL;
}
}
else//上下移动
{
for (int i = 0; i < GAMESIZE; i++)
{
for (int j = 0; j < GAMESIZE; j++)
{
if (op == 'u')//上移
{
line1 = &this->number_array[j][i];
if (line2 != NULL)
{
if (*line1 == *line2 && *line1 != 0)//合并
{
*line2 += *line1;
*line1 = 0;
flag = 1;
this->counter--;
line2 += GAMESIZE;
line1 = NULL;
}
else if (*line2 != *line1 && *line1 != 0 && *line2 != 0)//排序
{
if (*(line2 + GAMESIZE) == 0)
{
*(line2 + GAMESIZE) = *line1;
*line1 = 0;
line2 += GAMESIZE;
flag = 1;
}
else
{
line2 = line1;
line1 = NULL;
}
}
else if (*line2 == 0 && *line1 != 0)//排序
{
*line2 = *line1;
*line1 = 0;
flag = 1;
}
}
else
{
line2 = &this->number_array[j][i];
line1 = NULL;
}
}
else//下移
{
line1 = &this->number_array[GAMESIZE - j - 1][i];
if (line2 != NULL)
{
if (*line1 == *line2 && *line1 != 0)//合并
{
*line2 += *line1;
*line1 = 0;
flag = 1;
this->counter--;
line2 -= GAMESIZE;
line1 = NULL;
}
else if (*line2 != *line1 && *line1 != 0 && *line2 != 0)//排序
{
if (*(line2 - GAMESIZE) == 0)
{
*(line2 - GAMESIZE) = *line1;
*line1 = 0;
line2 -= GAMESIZE;
flag = 1;
}
else
{
line2 = line1;
line1 = NULL;
}
}
else if (*line2 == 0 && *line1 != 0)//排序
{
*line2 = *line1;
*line1 = 0;
flag = 1;
}
}
else
{
line2 = &this->number_array[GAMESIZE - j - 1][i];
line1 = NULL;
}
}
}
line2 = NULL;
}
}
this->UpDateEA();
return flag;
}
else
{
cout << "输入有误" << endl;
system("pause");
return false;
}
}
bool Game_2048::GameOver(bool creat)
{
if (creat)
{
if (this->MoveAble())
return 0;
else
cout << "游戏结束" << endl;
return 1;
}
else
cout << "游戏结束" << endl;
return 1;
}
Game_2048::~Game_2048()
{
if (this->empty_array != NULL)
{
delete[] this->empty_array;
this->empty_array = NULL;
}
}