目录
1.游戏初始化
利用随机数,初始化方块的起始位置,起始方块的数值为2或4,出现数字2的几率更大一些。代码如下:
int Num() {
int num;
if (rand() % 10 == 0) {//1/10的情况为4
num = 4;
}
else
num = 2;
return num;
}
void Init(int n) {
srand((unsigned int)time(NULL));
int i = 0;
while (i < n) {
int x = rand() % ROW;
int y = rand() % COL;
if (map[x][y] == 0) {
map[x][y] = Num();
i++;
}
}
}
2.界面绘制
不同的数值,采用不同颜色的矩形进行区分。每次操作后,清屏再重新进行打印。
void Draw() {
system("cls");
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
int x = j * GRID_WIDTH + (j + 1) * INTERVAL;
int y = i * GRID_WIDTH + (i + 1) * INTERVAL;
switch(map[i][j])
{
case 0:
setfillcolor(RGB(205, 193, 180));
break;
case 2:
setfillcolor(RGB(238, 228, 218));
break;
case 4:
setfillcolor(RGB(224, 193, 163));
break;
case 8:
setfillcolor(RGB(242, 177, 121));
break;
case 16:
setfillcolor(RGB(245, 149, 99));
break;
case 32:
setfillcolor(RGB(246, 124, 95));
break;
case 64:
setfillcolor(RGB(246, 94, 59));
break;
case 128:
setfillcolor(RGB(242, 177, 121));
break;
case 256:
setfillcolor(RGB(237, 204, 97));
break;
case 512:
setfillcolor(RGB(255, 0, 128));
break;
case 1024:
setfillcolor(RGB(145, 0, 72));
break;
default:
setfillcolor(RGB(242, 17, 158));
break;
}
solidroundrect(x, y, x + GRID_WIDTH, y + GRID_WIDTH, 15, 15);
if (map[i][j] != 0) {
if(map[i][j]==2|| map[i][j] == 4)
settextcolor(RGB(118, 105, 87));
else
settextcolor(WHITE);
setbkmode(TRANSPARENT);
settextstyle(50, 0, _T("Consolas"));
char str[10];
sprintf(str, "%d", map[i][j]);
int n_x = x + (GRID_WIDTH - textwidth(str))/2;
int n_y = y + (GRID_WIDTH - textheight(str)) / 2;
outtextxy(n_x,n_y,str);
}
}
}
}
3.方块移动
方块向同一方向移动,相邻的方块数值若相同则合并。
bool moveup() {
bool flg = false;
for (int i = 0; i < COL; i++) {
int tmp = 0;
for (int j = 1; j < ROW; j++) {
if (map[j][i] != 0) {
if (map[tmp][i] == 0) {
map[tmp][i] = map[j][i];
map[j][i] = 0;
flg = true;
}
else if (map[j][i] == map[tmp][i]) {
map[tmp][i] += map[j][i];
map[j][i] = 0;
tmp++;
flg = true;
}
else {
map[tmp+1][i] = map[j][i];
if (tmp+1 != j) {
map[j][i] = 0;
flg = true;
}
tmp++;
}
}
}
}
return flg;
}
bool movedown() {
bool flg = false;
for (int i = 0; i <COL; i++) {
int tmp = 3;
for (int j = 2; j >=0; j--) {
if (map[j][i] != 0) {
if (map[tmp][i] == 0) {
map[tmp][i] = map[j][i];
map[j][i] = 0;
flg = true;
}
else if (map[j][i] == map[tmp][i]) {
map[tmp][i] += map[j][i];
map[j][i] = 0;
tmp--;
flg = true;
}
else {
map[tmp - 1][i] = map[j][i];
if (tmp - 1 != j) {
map[j][i] = 0;
flg = true;
}
tmp--;
}
}
}
}
return flg;
}
bool moveleft() {
bool flg = false;
for (int i = 0; i < ROW; i++) {
int tmp = 0;
for (int j = 1; j < COL; j++) {
if (map[i][j] != 0) {
if (map[i][tmp] == 0) {
map[i][tmp] = map[i][j];
map[i][j] = 0;
flg = true;
}
else if (map[i][j] == map[i][tmp]) {
map[i][tmp] += map[i][j];
map[i][j] = 0;
tmp++;
flg = true;
}
else {
map[i][tmp + 1] = map[i][j];
if (tmp + 1 != j) {
map[i][j] = 0;
flg = true;
}
tmp++;
}
}
}
}
return flg;
}
bool moveright() {
bool flg = false;
for (int i = 0; i < ROW; i++) {
int tmp = 3;
for (int j = 2; j >= 0; j--) {
if (map[i][j] != 0) {
if (map[i][tmp] == 0) {
map[i][tmp] = map[i][j];
map[i][j] = 0;
flg = true;
}
else if (map[i][j] == map[i][tmp]) {
map[i][tmp] += map[i][j];
map[i][j] = 0;
tmp--;
flg = true;
}
else {
map[i][tmp - 1] = map[i][j];
if (tmp - 1 != j) {
map[i][j] = 0;
flg = true;
}
tmp--;
}
}
}
}
return flg;
}
4.判断游戏胜利或结束
若出现数值为2048的方块则游戏胜利,若并无空格,并且相邻方块数字都不一样,则游戏失败。
void over() // 判断是否2048获胜
{
for (int i = 0; i <ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[i][j] == 2048)
{
gameover= true;
}
}
}
}
bool IsGameover(int(*arr)[COL])
{
int count0 = 0;//统计0的个数
int i;
int j;
//判断是否有空格
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (arr[i][j] == 0)
count0++;
}
}
if (count0 != 0)//还有空格
return false;
//是否有相邻的数字一样
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (j + 1 < COL)//判断当前的值和右边是否相同
if (arr[i][j] == arr[i][j + 1])
return false;
if (i + 1 < ROW)//判断当前的值和下标是否相同
if (arr[i][j] == arr[i + 1][j])
return false;
}
}
return true;
}
5.全部代码
#define _CRT_SECURE_NO_WARNINGS//这一句必须放在第一行
#include <stdio.h>
#include <math.h>
#include <graphics.h>
#include <conio.h>
#include<time.h>
#include <windows.h>
#define ROW 4
#define COL ROW
#define KEY_UP 72 /* 方向键'上'的扫描码码值 */
#define KEY_DOWN 80 /* 方向键'下'的扫描码码值 */
#define KEY_LEFT 75 /* 方向键'左'的扫描码码值 */
#define KEY_RIGHT 77 /* 方向键'右'的扫描码码值 */
#define GRID_WIDTH 100 //格子宽度
#define INTERVAL 15 //间隔
int map[4][4] = { 0 };
bool gameover = false;
int Num() {
int num;
if (rand() % 10 == 0) {//1/10的情况为4
num = 4;
}
else
num = 2;
return num;
}
void Init(int n) {
//static int seed = 0;
//srand((unsigned int)time(NULL)+seed);每次产生的值不挨在一起
srand((unsigned int)time(NULL));
int i = 0;
while (i < n) {
int x = rand() % ROW;
int y = rand() % COL;
if (map[x][y] == 0) {
map[x][y] = Num();
i++;
}
}
}
void Draw() {
system("cls");
//cleardevice();
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
int x = j * GRID_WIDTH + (j + 1) * INTERVAL;
int y = i * GRID_WIDTH + (i + 1) * INTERVAL;
switch(map[i][j])
{
case 0:
setfillcolor(RGB(205, 193, 180));
break;
case 2:
setfillcolor(RGB(238, 228, 218));
break;
case 4:
setfillcolor(RGB(224, 193, 163));
break;
case 8:
setfillcolor(RGB(242, 177, 121));
break;
case 16:
setfillcolor(RGB(245, 149, 99));
break;
case 32:
setfillcolor(RGB(246, 124, 95));
break;
case 64:
setfillcolor(RGB(246, 94, 59));
break;
case 128:
setfillcolor(RGB(242, 177, 121));
break;
case 256:
setfillcolor(RGB(237, 204, 97));
break;
case 512:
setfillcolor(RGB(255, 0, 128));
break;
case 1024:
setfillcolor(RGB(145, 0, 72));
break;
default:
setfillcolor(RGB(242, 17, 158));
break;
}
solidroundrect(x, y, x + GRID_WIDTH, y + GRID_WIDTH, 15, 15);
if (map[i][j] != 0) {
if(map[i][j]==2|| map[i][j] == 4)
settextcolor(RGB(118, 105, 87));
else
settextcolor(WHITE);
setbkmode(TRANSPARENT);
settextstyle(50, 0, _T("Consolas"));
char str[10];
sprintf(str, "%d", map[i][j]);
int n_x = x + (GRID_WIDTH - textwidth(str))/2;
int n_y = y + (GRID_WIDTH - textheight(str)) / 2;
outtextxy(n_x,n_y,str);
}
}
}
}
bool moveup() {
bool flg = false;
for (int i = 0; i < COL; i++) {
int tmp = 0;
for (int j = 1; j < ROW; j++) {
if (map[j][i] != 0) {
if (map[tmp][i] == 0) {
map[tmp][i] = map[j][i];
map[j][i] = 0;
flg = true;
}
else if (map[j][i] == map[tmp][i]) {
map[tmp][i] += map[j][i];
map[j][i] = 0;
tmp++;
flg = true;
}
else {
map[tmp+1][i] = map[j][i];
if (tmp+1 != j) {
map[j][i] = 0;
flg = true;
}
tmp++;
}
}
}
}
return flg;
}
bool movedown() {
bool flg = false;
for (int i = 0; i <COL; i++) {
int tmp = 3;
for (int j = 2; j >=0; j--) {
if (map[j][i] != 0) {
if (map[tmp][i] == 0) {
map[tmp][i] = map[j][i];
map[j][i] = 0;
flg = true;
}
else if (map[j][i] == map[tmp][i]) {
map[tmp][i] += map[j][i];
map[j][i] = 0;
tmp--;
flg = true;
}
else {
map[tmp - 1][i] = map[j][i];
if (tmp - 1 != j) {
map[j][i] = 0;
flg = true;
}
tmp--;
}
}
}
}
return flg;
}
bool moveleft() {
bool flg = false;
for (int i = 0; i < ROW; i++) {
int tmp = 0;
for (int j = 1; j < COL; j++) {
if (map[i][j] != 0) {
if (map[i][tmp] == 0) {
map[i][tmp] = map[i][j];
map[i][j] = 0;
flg = true;
}
else if (map[i][j] == map[i][tmp]) {
map[i][tmp] += map[i][j];
map[i][j] = 0;
tmp++;
flg = true;
}
else {
map[i][tmp + 1] = map[i][j];
if (tmp + 1 != j) {
map[i][j] = 0;
flg = true;
}
tmp++;
}
}
}
}
return flg;
}
bool moveright() {
bool flg = false;
for (int i = 0; i < ROW; i++) {
int tmp = 3;
for (int j = 2; j >= 0; j--) {
if (map[i][j] != 0) {
if (map[i][tmp] == 0) {
map[i][tmp] = map[i][j];
map[i][j] = 0;
flg = true;
}
else if (map[i][j] == map[i][tmp]) {
map[i][tmp] += map[i][j];
map[i][j] = 0;
tmp--;
flg = true;
}
else {
map[i][tmp - 1] = map[i][j];
if (tmp - 1 != j) {
map[i][j] = 0;
flg = true;
}
tmp--;
}
}
}
}
return flg;
}
bool keyControl()
{
bool flg = false;
switch (_getch())
{
case KEY_UP:
flg = moveup();
break;
case KEY_DOWN:
flg=movedown();
break;
case KEY_LEFT:
flg=moveleft();
break;
case KEY_RIGHT:
flg=moveright();
break;
}
return flg;
}
void over() // 判断是否2048获胜
{
for (int i = 0; i <ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (map[i][j] == 2048)
{
gameover= true;
}
}
}
}
bool IsGameover(int(*arr)[COL])
{
int count0 = 0;//统计0的个数
int i;
int j;
//判断是否有空格
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (arr[i][j] == 0)
count0++;
}
}
if (count0 != 0)//还有空格
return false;
//是否有相邻的数字一样
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (j + 1 < COL)//判断当前的值和右边是否相同
if (arr[i][j] == arr[i][j + 1])
return false;
if (i + 1 < ROW)//判断当前的值和下标是否相同
if (arr[i][j] == arr[i + 1][j])
return false;
}
}
return true;
}
int main() {
//绘图窗口初始化
initgraph(475,475);
// 读取图片至绘图窗口
loadimage(NULL, _T("2048背景.png"));
Init(2);
while (!gameover) {
Draw();
if (!keyControl())
continue;
Init(1);
over();
if (gameover) {
Draw();
settextcolor(RGB(252, 85, 49));
settextstyle(100, 0, _T("微软雅黑"));
outtextxy(80, 15 * 4, _T("游戏胜利"));
Sleep(3000);
}
else if (IsGameover(map)) {
Draw();
settextcolor(RGB(120, 67, 21));
settextstyle(100, 0, _T("微软雅黑"));
outtextxy(80, 15 * 4, _T("游戏失败"));
Sleep(3000);
break;
}
}
closegraph();
return 0;
}