搜档网
当前位置:搜档网 › C语言 之 2048小游戏

C语言 之 2048小游戏

C语言 之 2048小游戏

//在编译器内运行前先在工程项目文件夹下新建“save.txt”文档(不然无法运行),在外部Debug文件夹下运行请先在Debug目录下新建“save.txt”文档(不然无法运行)
//程序经过调试,绝对能运行,可能还有些许Bug未修改


/**************************************************头 文 件****************************************************************/
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
#include "time.h"
#include "conio.h"
/****************************************************定 义******************************************************************/
#define SIZE 4
#define Up 72
#define Down 80
#define Left 75
#define Right 77
#define F1 59
#define _1 49
#define _2 50
#define _3 51
#define _4 52
#define _5 53
#define _6 54
#define _7 55
#define _8 56
#define Enter 13
#define Space 32
#define UInt32 unsigned int
/*********************************************定 义 全 局 变 量**********************************************************/
UInt32 g_szMat[SIZE*SIZE];//存放数字的矩阵
UInt32 g_szAddMat[SIZE*SIZE];//相邻两数字相加,保证每次只能移动一次并相加,并且进行相应的标记
int Scorce = 0;//记录分数
int E = 1;//用于判断游戏是否结束
int num = 0;//记录单格最高分
int HS = 0;//记录最高分
/***********************************************函 数 声 明****************************************************************/
void gotoxy(int x, int y);//坐标函数
int color(int c);//颜色函数
void Init();//系统初始化
void PrintUI(UInt32 *pszMat);//打印游戏界面
void generateOneNumber();//生成2或者4的随机数
int GetBlackCount();//找空白的格子
int TextColors(int i);//根据数字修改颜色
int ApiPrintMsg(int id);//打印消息
UInt32 GetByPosition(int i, int j);//获取数字位置的值
void SetByPosition(int i, int j, UInt32 uData);//设置数字位置的值
int GetAddMatByPosition(int i, int j);//获取相邻数字相加位置的值
void SetAddMatByPosition(int i, int j, UInt32 uData);//设置相邻位置相加的值
int GetUserCommand();//游戏界面用户操作
int CaidanCommand(int e);//菜单界面用户操作
int BeforeMove();//移动前
void AfterMove();//移动后
int MoveOneStep(int i1, int j1, int i2, int j2, UInt32 *uData);//移动一个值,从i1,j1移动到i2,j2,返回移动结果并更新uData
void MoveUp();//向上移动
void MoveDown();//向下移动
void MoveLeft();//向左移动
void MoveRight();//向右移动
int MoveOneUp(int i, int j);//向上移动一步
int MoveOneDown(int i, int j);//向下移动一步
int MoveOneLeft(int i, int j);//向左移动一步
int MoveOneRight(int i, int j);//向右移动一步
void ResetAddMat();//重置相邻数字相加位置的值
int Pangduan();//判断游戏结束
int Pangduanheng(int r,

UInt32 *u);//判断横向相邻数组的值是否相同
int Pangduanzong(int r, UInt32 *u);//判断纵向相邻数组的值是否相同
int Pangduan_0(int r, UInt32 *u);//判断数组内的值是否存在0
void HuanyingUI();//游戏欢迎界面
void Bangzhu();//打印帮助界面
void JieshuUI();//打印游戏结束界面
void Replay();//重新游戏
void WinUI();//打印胜利界面
void CaidanUI();//打印菜单界面
void ZantingUI();//打印暂停界面
void Zuigaofen();//产生最高分
void Chafen();//查询最高分
void Shuoming();//游戏说明
void Youxi();//执行游戏
void File_in();//在文件中读取最高分
void File_out();//储存最高分进文件
int Tuichu(int e);//退出游戏
void Guanyu();//关于游戏
/*************************************************函 数 主 体*************************************************************/
void Init()//系统初始化
{
HuanyingUI();
generateOneNumber();
generateOneNumber();
PrintUI(g_szMat);
}

void main()//主函数
{
File_in();
Youxi();
}

void PrintUI(UInt32 *pszMat)//打印游戏界面
{
int i, j, uData;
gotoxy(13, 2);
color(14);
printf("欢迎使用2048小游戏\t\t");
color(5);
printf("Scorce:");
color(11);
printf(" %d", Scorce);
color(12);
printf("\t\t菜单:F1");
color(15);
printf("\n");
gotoxy(8, 3);
color(13);
printf("==============================================================\n\n");
for (i = 0; SIZE>i; i++)
{
for (j = 0; SIZE>j; j++)
{
uData = pszMat[SIZE*i + j];
if (0 != uData)
{
TextColors(uData);
printf("%15d", uData);
}
else
{
color(15);
printf("%15s", "口");
}
}
printf("\n\n\n\n");
}
printf("\n");
gotoxy(8, 19);
color(11);
printf("==============================================================\n\n");
color(15);
}

int GetBlackCount()//找空白的格子
{
int i, nCount = 0;
for (i = 0; i{
nCount += 0 == g_szMat[i] ? 1 : 0;
}
return nCount;
}

void generateOneNumber()//生成2或者4的随机数
{
int i, iPos;
int iBlankCount = GetBlackCount();
if (0 == iBlankCount)
{
printf("%s", "系统错误");
return;
}
srand((unsigned int)time(0));
iPos = rand() % iBlankCount + 1;
for (i = 0; i{
if (0 == g_szMat[i])
{
iPos--;
if (0 == iPos)
{
srand((unsigned int)time(0));
g_szMat[i] = rand() % 10 <= 5 ? 2 : 4;
return;
}
}
}
}

int TextColors(int number)//根据数字修改颜色
{
switch (number)
{
case 2:return color(14); break;
case 4:return color(2); break;
case 8:return color(3); break;
case 16:return color(4); break;
case 32:return color(5); break;
case 64:return color(6); break;
case 128:return color(7); break;
case 256:return color(8); break;
case 512:return color(9); break;
case 1024:return color(10); break;
case 2048:return color(11); break;
case 4096:return color(1

2); break;
case 8192:return color(13); break;
default:return color(15); break;
}
return 0;
}

int ApiPrintMsg(int id)//打印消息
{
switch (id)
{
case 0:color(5); return printf("%s", "。。。内部错误。。。"); break;
case 1: color(5); return printf("%s", "。。。游戏开始。。。"); break;
case 2:color(5); return printf("%s", "。。。命令错误。。。"); break;
case 11:color(14); return printf("%s", "。。。游戏胜利。。。"); break;
case 12:color(5); return printf("%s", "。。。游戏失败。。。"); break;
case 13:color(12); return printf("%s", "。。。游戏结束。。。"); break;
case -1:color(10); return printf("%s", "。。。游戏进行中。。。"); break;
default:color(15); return printf("%s", "。。。未知错误。。。"); break;
}
return 0;
}

UInt32 GetByPosition(int i, int j)//获取数字位置的值
{
if (0>i || 0>j || SIZE <= i || SIZE <= j)
{
ApiPrintMsg(0);
return 0;
}
return g_szMat[SIZE*i + j];
}

void SetByPosition(int i, int j, UInt32 uData)//设置数字位置的值
{
g_szMat[SIZE*i + j] = uData;
}

int GetAddMatByPosition(int i, int j)//获取两个相邻数字相加位置的值
{
return g_szAddMat[SIZE*i + j];
}

void SetAddMatByPosition(int i, int j, UInt32 uData)//获取两个相邻数字相加位置的值
{
g_szAddMat[SIZE*i + j] = uData;
}

int GetUserCommand()//游戏界面用户操作
{
char cCmd;
cCmd = getch();
switch (cCmd)
{
case Up:MoveUp(); break;
case Down:MoveDown(); break;
case Left:MoveLeft(); break;
case Right:MoveRight(); break;
case F1:CaidanUI(); break;
}
return 1;
}

int CaidanCommand(int e)//菜单界面用户操作
{
char c;
c = getch();
switch (c)
{
case _1:system("cls"); PrintUI(g_szMat); return (e = 0); break;
case _2:ZantingUI(); return (e = 0); break;
case _3:Replay(); break;
case _4:e = Tuichu(e); return e; break;
case _5:Chafen(); break;
case _6:Bangzhu(); break;
case _7:Shuoming(); break;
case _8:Guanyu(); break;
}
}

void ResetAddMat()//重置相邻数字相加位置的值
{
memset(g_szAddMat, 0, SIZE*SIZE*sizeof(int));
}

int BeforeMove()//移动前
{
ResetAddMat();
return 1;
}

void AfterMove()//移动后
{
if (2048 == num)
{
WinUI();
num += 1;
}
generateOneNumber();
PrintUI(g_szMat);
if (13 == Pangduan())
{
JieshuUI();
}
else
{
gotoxy(26, 21);
ApiPrintMsg(Pangduan());
}
}

int MoveOneStep(int i1, int j1, int i2, int j2, UInt32 *uData)//移动一个值从i1,j1移动到i2,j2移动的结果,并更新uData
{
UInt32 uNextData = GetByPosition(i2, j2);
if (0 == uNextData)
{
SetAddMatByPosition(i2, j2, GetAddMatByPosition(i1, j1));
SetAddMatByPosition(i1, j1, 0);
SetByPosition(i1, j1, 0);
SetByPosition(i2, j2, (*uData));
return 1;
}
if (0 == GetAddMatByPosition(i1, j1) && 0 == GetAddMatByPosition(i2, j2) && (*uData) == uNextData)
{
(*uDat

a) *= 2;
Scorce += *uData;
if (*uData>num) num = *uData;
SetByPosition(i1, j1, 0);
SetByPosition(i2, j2, (*uData));
SetAddMatByPosition(i2, j2, 1);
return 1;
}
return 0;
}

void MoveUp()//向上移动
{
int i, j;
int moved = 0;
if (0 == BeforeMove())
{
return;
}
for (j = 0; j{
for (i = 0; i{
moved = (1 == MoveOneUp(i, j) ? 1 : moved);
}
}
if (1 == moved)
{
AfterMove();
}
}

int MoveOneUp(int i, int j)//向上移动一步
{
int moved = 0;
UInt32 uData = GetByPosition(i, j);
while (i>0)
{
if (0 == MoveOneStep(i, j, i - 1, j, &uData))
{
break;
}
else
{
moved = 1;
i--;
}
}
return moved;
}

void MoveDown()//向下移动
{
int i, j;
int moved = 0;
if (0 == BeforeMove())
{
return;
}
for (j = SIZE-1; j>=0; j--)
{
for (i = SIZE-1; i>=0; i--)
{
moved = (1 == MoveOneDown(i, j) ? 1 : moved);
}
}
if (1 == moved)
{
AfterMove();
}
}

int MoveOneDown(int i, int j)//向下移动一步
{
int moved = 0;
UInt32 uData = GetByPosition(i, j);
while (i<(SIZE - 1))
{
if (0 == MoveOneStep(i, j, i + 1, j, &uData))
{
break;
}
else
{
moved = 1;
i++;
}
}
return moved;
}

void MoveLeft()//向左移动
{
int i, j;
int moved = 0;
if (0 == BeforeMove())
{
return;
}
for (j = 0; j{
for (i = 0; i{
moved = (1 == MoveOneLeft(i, j) ? 1 : moved);
}
}
if (1 == moved)
{
AfterMove();
}
}

int MoveOneLeft(int i, int j)//向左移动一步
{
int moved = 0;
UInt32 uData = GetByPosition(i, j);
while (j>0)
{
if (0 == MoveOneStep(i, j, i, j - 1, &uData))
{
break;
}
else
{
moved = 1;
j--;
}
}
return moved;
}

void MoveRight()//向右移动
{
int i, j;
int moved = 0;
if (0 == BeforeMove())
{
return;
}
for (j = SIZE-1; j>=0; j--)
{
for (i = SIZE-1; i>=0; i--)
{
moved = (1 == MoveOneRight(i, j) ? 1 : moved);
}
}
if (1 == moved)
{
AfterMove();
}
}

int MoveOneRight(int i, int j)//向右移动一步
{
int moved = 0;
UInt32 uData = GetByPosition(i, j);
while (j<(SIZE - 1))
{
if (0 == MoveOneStep(i, j, i, j + 1, &uData))
{
break;
}
else
{
moved = 1;
j++;
}
}
return moved;
}

void gotoxy(int x, int y)//坐标函数
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

int color(int c)//颜色函数
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
return 0;
}

int Pangduan()//判断游戏结束
{
int r = 0;
r = Pangduanheng(r, g_szMat);
r = Pangduanzong(r, g_szMat);
r = Pangduan_0(r, g_szMat);
if (r == 0) return 13;
else return -1;
}

int Pangduanheng(int r, UInt32 *u)//判断横向相邻数组的值是否相同
{
int i, j;
for (i = 0; i{
for (j = 0; j<(SIZE

- 1); j++)
{
if (u[SIZE*i + j] == u[SIZE*i + j + 1]) r += 1;
}
}
return r;
}

int Pangduanzong(int r, UInt32 *u)//判断纵向相邻数组的值是否相同
{
int i, j;
for (j = 0; j{
for (i = 0; i<(SIZE - 1); i++)
{
if (u[SIZE*i + j] == u[SIZE*(i + 1) + j]) r += 1;
}
}
return r;
}

int Pangduan_0(int r, UInt32 *u)//判断数组内的值是否存在0
{
int i, j;
for (i = 0; i{
for (j = 0; j{
if (0 == u[SIZE*i + j]) r += 1;
}
}
return r;
}

void HuanyingUI()//游戏欢迎界面
{
color(11);
gotoxy(28, 9);
printf("Welcome to 2048!!!");
color(12);
gotoxy(21, 12);
printf("分别按键盘上、下、左、右进行游戏");
color(13);
gotoxy(28, 15);
system("pause");
system("cls");
}

void Bangzhu()//打印帮助界面
{
int c;
system("cls");
color(12);
gotoxy(37, 7);
printf("帮 助");
color(13);
gotoxy(23, 10);
printf("分别按键盘上、下、左、右控制游戏");
color(15);
gotoxy(28, 13);
printf("按任意键返回上一级。。。");
getch();
CaidanUI();
}

void JieshuUI()//打印游戏结束界面
{
int i, j;
system("cls");
color(11);
for (i = 4; i <= 17; i++)
{
for (j = 23; j <= 56; j++)
{
gotoxy(j, i);
if (j % 2 != 0)
{
if (i == 4 || i == 17 || j == 23 || j == 55) printf("*");
}
}
}
Zuigaofen();
color(12);
gotoxy(30, 6);
ApiPrintMsg(Pangduan());
color(10);
gotoxy(31, 9);
printf("你的得分是:");
color(11);
printf("%d", Scorce);
color(14);
if (Scorce >= HS)
{
gotoxy(29, 12);
printf("你的分数是最高分!!!");
File_out();
}
else
{
gotoxy(27, 12);
color(9);
printf("你的分数离最高分还差:%d", HS - Scorce);
}
color(13);
gotoxy(31, 15);
printf("按“F1”进入菜单");
color(15);
gotoxy(28, 18);
getch();
}

void Replay()//重新游戏
{
system("cls");
Scorce = 0, num = 0;
memset(g_szMat, 0, SIZE*SIZE*sizeof(int));
Youxi();
}

void WinUI()//打印胜利界面
{
system("cls");
gotoxy(28, 9);
ApiPrintMsg(11);
color(15);
gotoxy(28, 12);
system("pause");
system("cls");
}

void CaidanUI()//打印菜单界面
{
int i, j, e = 1;
system("cls");
gotoxy(37, 2);
color(12);
printf("菜 单");
color(11);
for (i = 4; i <= 20; i++)
{
for (j = 10; j <= 70; j++)
{
gotoxy(j, i);
if (i == 4 || i == 20) printf("=");
else if (j == 10 || j == 69) printf("||");
}
}
color(10);
gotoxy(20, 6);
printf("1.返回游戏");
gotoxy(49, 6);
printf("2.暂停游戏");
gotoxy(20, 9);
printf("3.重新游戏");
gotoxy(49, 9);
printf("4.退出游戏");
gotoxy(20, 12);
printf("5.查看分数");
gotoxy(49, 12);
printf("6.游戏帮助");
gotoxy(20, 15);
printf("7.游戏说明");
gotoxy(49, 15);
printf("8.关于游戏");
color(13);
gotoxy(23, 18);
printf("请在键盘中输入对应

序号以继续。。。");
while (e)
{
e = CaidanCommand(e);
}
}

void ZantingUI()//打印暂停界面
{
system("cls");
color(12);
gotoxy(37, 9);
printf("暂 停");
color(15);
gotoxy(32, 12);
system("pause");
system("cls");
PrintUI(g_szMat);
}

void Zuigaofen()//产生最高分
{
if (HS < Scorce) HS = Scorce;
}

void Chafen()//查询最高分
{
system("cls");
color(12);
gotoxy(35, 9);
printf("最高分是:");
color(11);
printf("%d", HS);
color(15);
gotoxy(30, 12);
printf("按任意键返回上一级。。。");
getch();
CaidanUI();
}

void Shuoming()//游戏说明
{
int i, j;
system("cls");
color(12);
gotoxy(37, 1);
printf("说 明");
color(11);
for (i = 3; i <= 21; i++)
{
for (j = 21; j <= 58; j++)
{
gotoxy(j, i);
if (i == 3 || i == 21) printf("=");
else if (j == 21 || j == 57) printf("||");
}
}
color(14);
gotoxy(25, 5);
printf("一开始方格内会出现2或者4等这两");
gotoxy(25, 7);
printf("个小数字,玩家只需要上下左右其");
gotoxy(25, 9);
printf("中一个方向来移动出现的数字,所");
gotoxy(25, 11);
printf("有的数字就会向滑动的方向靠拢,");
gotoxy(25, 13);
printf("而滑出的空白方块就会随机出现一");
gotoxy(25, 15);
printf("个数字,相同的数字相撞时会叠加");
gotoxy(25, 17);
printf("靠拢,然后一直这样,不断的叠加");
gotoxy(25, 19);
printf("最终拼凑出2048这个数字就算成功");
color(15);
gotoxy(29, 23);
printf("按任意键返回上一级。。。");
getch();
CaidanUI();
}

void Youxi()//执行游戏
{
Init();
while (E)
{
GetUserCommand();
}
}

void File_in()//在文件中读取最高分
{
FILE *fp;
fp = fopen("save.txt", "r");
fscanf(fp, "%d", &HS);
fclose(fp);
}

void File_out()//储存最高分进文件
{
FILE *fp;
fp = fopen("save.txt", "w");
fprintf(fp, "%d", Scorce);
fclose(fp);
}

int Tuichu(int e)//退出游戏
{
int c,i=1,m,n;
system("cls");
color(9);
for (m = 7; m <= 17; m++)
{
for (n = 25; n <= 54; n++)
{
gotoxy(n, m);
if (n % 2 != 0)
{
if (m == 7 || m == 17 || n == 25 || n == 53) printf("*");
}
}
}
gotoxy(33,9);
color(11);
printf("确定要退出吗?");
gotoxy(31, 12);
color(12);
printf("退出将丢失当前进度");
gotoxy(29, 15);
color(13);
printf("是:Enter 否:Space");
while (i)
{
c = getch();
if (Enter == c)
{
E = 0;
e = 0;
i = 0;
}
if (Space == c)
{
i = 0;
CaidanUI();
}
}
return e;
}

void Guanyu()//关于游戏
{
system("cls");
gotoxy(31, 9);
color(14);
printf("This Game Make By");
gotoxy(36, 11);
color(10);
printf("GrassGan");
getch();
CaidanUI();
}

相关主题