1.利用循环结构实现游戏基本功能,例如:重新开始,退出游戏,上下左右移动等。
2.采用文件流相关操作记录历史最高分,若玩家从未玩过,则默认最高分为0。
3.使用贴图操作完成相关界面(如下图所示,较为简陋)。
#include
#include
#include
#include
#include
int shuzi[4][4] = { 0 };
int shifoujieshu = 1;//判断是否结束
int change = 1;//判断数组是否改变
long fenshu = 0;//本轮游戏分数
long lishizuijia = 0;//历史最高分
long zuidahechen;//最大合成数
int n;
IMAGE img[20];
void tupianxianshi(int i,int j,int n) {// 设置贴图
int x = j * 106 + (j + 1) * 15;
int y = i * 106 + (i + 1) * 15+160;// 坐标
switch (n) {// 根据数值显示对应贴图
case 2:
loadimage(&img[1], "block_2.jpg");
putimage(x, y, &img[1]);
break;
case 4:
loadimage(&img[2], "block_4.jpg");
putimage(x, y, &img[2]);
break;
case 8:
loadimage(&img[3], "block_8.jpg");
putimage(x, y, &img[3]);
break;
case 16:
loadimage(&img[4], "block_16.jpg");
putimage(x, y, &img[4]);
break;
case 32:
loadimage(&img[5], "block_32.jpg");
putimage(x, y, &img[5]);
break;
case 64:
loadimage(&img[6], "block_64.jpg");
putimage(x, y, &img[6]);
break;
case 128:
loadimage(&img[7], "block_128.jpg");
putimage(x, y, &img[7]);
break;
case 256:
loadimage(&img[8], "block_256.jpg");
putimage(x, y, &img[8]);
break;
case 512:
loadimage(&img[9], "block_512.jpg");
putimage(x, y, &img[9]);
break;
case 1024:
loadimage(&img[10], "block_1024.jpg");
putimage(x, y, &img[10]);
break;
case 2048:
loadimage(&img[11], "block_2048.jpg");
putimage(x, y, &img[11]);
break;
case 4096:
loadimage(&img[12], "block_4096.jpg");
putimage(x, y, &img[12]);
break;
case 8192:
loadimage(&img[13], "block_8192.jpg");
putimage(x, y, &img[13]);
break;
case 16384:
loadimage(&img[14], "block_16384.jpg");
putimage(x, y, &img[14]);
break;
case 32768:
loadimage(&img[15], "block_32768.jpg");
putimage(x, y, &img[15]);
break;
case 65536:
loadimage(&img[16], "block_65536.jpg");
putimage(x, y, &img[16]);
break;
case 131072:
loadimage(&img[17], "block_131072.jpg");
putimage(x, y, &img[17]);
break;
}
}
int lishizuigao(long* lishizuijia) {
FILE* fp; //文件指针
fopen_s(&fp, "fenshu.txt", "r");//打开文件,以只读的方式r
if (fp == NULL)//如果文件不存在,打开文件,以写入的方式w
{
fopen_s(&fp, "fenshu.txt", "w");
fprintf(fp, "%-10d", *lishizuijia);
}
else
fscanf_s(fp, "%10d", lishizuijia);
fclose(fp);//关闭文件
return 0;
}
int zuidahech(long* zuidahechen) {
FILE* fp1 ;
fopen_s(&fp1, "zuidahechen.txt", "r");
if (fp1 == NULL)
{
fopen_s(&fp1, "zuidahechen.txt", "w");
fprintf(fp1, "%-10d", *zuidahechen);
}
else
fscanf_s(fp1, "%10d", zuidahechen);
fclose(fp1);//关闭文件
return 0;
}
void storeHighScore(long lishizuijia)
{
FILE* fp;
fopen_s(&fp, "fenshu.txt", "w");
fprintf(fp, "%-10d", lishizuijia);
fclose(fp);
}
void store(long zuidahechen)
{
FILE* fp1;
fopen_s(&fp1, "zuidahechen.txt", "w");
fprintf(fp1, "%-10d", zuidahechen);
fclose(fp1);
}
void jiemian() {
system("CLS");
int i, j, nn;
initgraph(500, 660);// 设置界面
loadimage(&img[18], "gamelogo.jpg", 239, 162);
putimage(0, 0, &img[18]);
loadimage(&img[19], "scorebg.jpg");
putimage(239, 0, &img[19]);
loadimage(&img[0], "background.jpg", 500, 500);
putimage(0, 160, &img[0]);
if (change == 1) {//生成随机数(2或4),且仅当数组改变时生成
do {
i = (unsigned)rand() % 4;
j = (unsigned)rand() % 4;
} while (shuzi[i][j] != 0);
nn = (unsigned)rand() % 2;
if (nn == 0)
shuzi[i][j] = 2;
else
shuzi[i][j] = 4;
}
lishizuigao(&lishizuijia);
if (fenshu > lishizuijia) {//判断分数是否超过历史最佳
lishizuijia = fenshu;
storeHighScore(lishizuijia);
}
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (shuzi[i][j]) //遍历数组,显示不为0的数字
tupianxianshi(i, j, shuzi[i][j]);
zuidahech(&zuidahechen);
if (shuzi[i][j] > zuidahechen) {//寻找当前最大合成数
zuidahechen = shuzi[i][j];
store(zuidahechen);
}
}
}
char str[10], str1[15],str2[10];//在画布上显示分数
setbkmode(TRANSPARENT);//设置背景为透明
settextstyle(30, 0, _T("楷体"));
sprintf_s(str, _T("%ld"), lishizuijia);
outtextxy(350, 15, str);
sprintf_s(str1, _T("%ld"), fenshu);
outtextxy(350, 62, str1);
sprintf_s(str2, _T("%ld"), zuidahechen);
outtextxy(350, 110, str2);
}
int up() {//上移
int i, j, k;
for (j = 0; j < 4; j++) {// 判断上下数字是否相同,且中间是否存在间隔
for (i = 0; i < 3; i++) {
k = i + 1;
while (shuzi[i][j] != 0) {//元素不为零时进行比较
if (shuzi[i][j] == shuzi[k][j]) {
change = 1;
fenshu += shuzi[k][j]*2;
shuzi[i][j] = shuzi[i][j] * 2;
shuzi[k][j] = 0;
break;
}
else {
if (shuzi[k][j] != 0)//判断相同元素间是否存在间隔
break;
if (++k == 4)//判断完一行后,直接退出当前循环
break;
}
}
}
}
for (i = 0; i < 3; i++) {//合并数字后,上移
for (j = 0; j < 4; j++) {
k = i + 1;
while(shuzi[i][j] == 0) {
if (shuzi[k][j] != 0) {
change = 1;
shuzi[i][j] = shuzi[k][j];
shuzi[k][j] = 0;
break;
}
else {
if (++k == 4)
break;
}
}
}
}
return change;
}
int down() {//下移
int i, j, k;
for (j = 0; j < 4; j++) {
for (i = 3; i > 0; i--) {
k = i - 1;
while (shuzi[i][j] != 0) {
if (shuzi[i][j] == shuzi[k][j]) {
change = 1;
fenshu += shuzi[k][j]*2;
shuzi[i][j] = shuzi[i][j] * 2;
shuzi[k][j] = 0;
break;
}
else {
if (shuzi[k][j] != 0)
break;
if (--k == -1)
break;
}
}
}
}
for (i = 3; i > 0; i--) {//合并数字后,下移
for (j = 0; j < 4; j++) {
k = i - 1;
while (shuzi[i][j] == 0) {
if (shuzi[k][j] != 0) {
change = 1;
shuzi[i][j] = shuzi[k][j];
shuzi[k][j] = 0;
break;
}
else {
if (--k == -1)
break;
}
}
}
}
return change;
}
int left() {//左移
int i, j, k;
for (i = 0; i < 4; i++) {//判断左右数字是否相同,且中间是否存在间隔
for (j = 0; j < 3; j++) {
k = j + 1;
while (shuzi[i][j] != 0) {
if (shuzi[i][j] == shuzi[i][k]) {
change = 1;
fenshu += shuzi[i][k]*2;
shuzi[i][j] = shuzi[i][j] * 2;
shuzi[i][k] = 0;
break;
}
else {
if (shuzi[i][k] != 0)
break;
if (++k == 4)
break;
}
}
}
}
for (j = 0; j < 3; j++) {//数字合并后,左移
for (i = 0; i < 4; i++) {
k = j + 1;
while (shuzi[i][j] == 0) {
if (shuzi[i][k] != 0) {
change = 1;
shuzi[i][j] = shuzi[i][k];
shuzi[i][k] = 0;
break;
}
else {
if (++k == 4)
break;
}
}
}
}
return change;
}
int right() {//右移
int i, j, k;
for (i = 0; i < 4; i++) {
for (j = 3; j > 0; j--) {
k = j - 1;
while (shuzi[i][j] != 0) {
if (shuzi[i][j] == shuzi[i][k]) {
change = 1;
fenshu += shuzi[i][k]*2;
shuzi[i][j] = shuzi[i][j] * 2;
shuzi[i][k] = 0;
break;
}
else {
if (shuzi[i][k] != 0)
break;
if (--k == -1)
break;
}
}
}
}
for (j = 3; j > 0; j--) {//数字合并后,右移
for (i = 0; i < 4; i++) {
k = j - 1;
while (shuzi[i][j] == 0) {
if (shuzi[i][k] != 0) {
change = 1;
shuzi[i][j] = shuzi[i][k];
shuzi[i][k] = 0;
break;
}
else {
if (--k == -1)
break;
}
}
}
}
return change;
}
int cs() {//键盘操作移动
char ch; change = 0;//int n=0; //n用于判断是否退出游戏
ch = _getch();
switch (ch) {
case 'w':
case 'W':up();
break;
case'a':
case'A':left();
break;
case's':
case'S':down();
break;
case'd':
case'D':right();
break;
case'n'://直接退出
n = 1;
shifoujieshu = 0;
break;
case'y'://重新开始
n = 2;
break;
}
return n;
}
int jieshu() {//判断是否结束
int i, j;
shifoujieshu = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (shuzi[i][j] == 0) {//判断是否有空余位置
shifoujieshu = 1;
}
if (i > 1) {
if (shuzi[i][j] == shuzi[i - 1][j]) {//判断上下是否有相同的数相连
shifoujieshu = 1;
}
}
if (j > 1) {
if (shuzi[i][j] == shuzi[i][j - 1]) {//判断左右是否有相同的数相连
shifoujieshu = 1;
}
}
}
}
if (shifoujieshu == 0) {
loadimage(&img[12], "gameOver.jpg");
putimage(100, 230, &img[12]);
}
return 0;
}
int main() {
//int n;
srand((unsigned)time(NULL));
while (shifoujieshu == 1) {
jiemian();
if (n != 1) {
n = cs();
}
if (n == 0) {
jieshu();
if (shifoujieshu == 0) {//判断是否进入下一局
char ch = _getch();
if (ch == 'y') {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
shuzi[i][j] = 0;
}
}
shifoujieshu = 1;
change = 1;
fenshu = 0;
}
}
}
else if(n == 1) {//判断是否直接结束
break;
}
else if (n == 2) {//判断是否重新开始
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
shuzi[i][j] = 0;
}
}
change = 1;
fenshu = 0;
}
}
return 0;
}