#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
#include<conio.h> //getch
#include<string.h>
#include<math.h>
#define SIZE 4
typedef struct intormation {
char username[100];//用户名
char cryptography[100];//密码
char name[100];//用户的真实姓名
char sex;//用户的性别
long int phone;//用户的号码
}users;
int high = 0;
int score = 0;
void help(int a[][SIZE]);
void begin(int a[][SIZE]);
void savescore(int score) {
FILE* fp;
fp = fopen("tscore.txt", "w");
if (!fp) {
printf("分数存入失败\n");
return;
}
fprintf(fp, "%d", score);
fclose(fp);
}
int loadscore() {
FILE* fp;
int a;
fp = fopen("tscore.txt", "r");//以只读的形式打开文件,
if (fp == NULL) {
printf("ERROR,分数读取失败");
return 0;
}
fscanf(fp, "%d", &a);//从历史记录中读出来最高分
fclose(fp);
return a;
}
void loadgame(int(*a)[SIZE]) {
FILE* fp;
int i, j;
fp = fopen("tgame.txt", "r");
if (fp == NULL) {
printf("ERROR!内存读取失败");
return;
}
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
fscanf(fp, "%d", &a[i][j]);
}
}
fclose(fp);
}
void search() {
FILE* fp;
users a;
int p = 0;
fp = fopen("user.txt", "r");
fread(&a, sizeof(users), 1, fp);
for (p = 1;!feof(fp);p++) {
printf("第%d位: %s\n", p, a.username);
fread(&a, sizeof(users), 1, fp);
}
printf("以上就是全部啦!\n");
fclose(fp);
}
void begin(int(*a)[SIZE]) {
system("CLS");
char n;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
printf("Welcome to:");
printf("2048\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
printf("菜单:\n");
printf("1:新游戏\n");
printf("2:继续游戏\n");
printf("3:历史最高分:%d\n", high);
printf("4:帮助\n");
printf("5:查看全球用户\n");
printf("\n");
fflush(stdin);
do {
printf("请键入你想要的操作的对应数字\n");
scanf("%c", &n);
fflush(stdin);
} while (n != '1' && n != '2' && n != '3' && n != '4' && n != '5');
switch (n) {
case '1':break;
case '2':loadgame(a);break;
case '4':help(a);break;
case '5':search();break;
}
}
void help(int(*a)[SIZE]) {
system("CLS");
int n = 0;
printf("帮助界面\n");
printf("1:操作说明:\n");
printf("\t\t本款游戏以方向键来代表上下左右的移动\n"
"同时,用户也可以用WASD来分别代表上左下右\n");
printf("2:游戏规则\n");
printf("\t\t用户通过键入上下左右\n"
"来控制数字在该方向上的移动,移动的范围不局限于一格,\n"
"可以多格移动,遇到数字相同的就相加,以最终加出2048为胜利\n");
printf("3:游戏结束的计算:\n");
printf("\t\t如果方格内输满了数\n"
"并且方格中没有相邻的可以进行相加的项,那么就视为游戏失败\n");
printf("分数的计算:\n");
printf("\t\t按照当前表格内的最大的数来计分\n");
printf(" ->按下1返回主列表\n");
do {
scanf("%d", &n);
} while (n != 1);
begin(a);
}
int check(int(*a)[SIZE]) {
int i, j, m = 0, t = 0;
//检查是否所有的格子都被填满
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
if (*(*(a + i) + j) == 0)
m = 1;
}
}
if (m == 1)
return 1;
else {
//检查同一行是否还有可加项
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE - 1;j++) {
if (*(*(a + i) + j) == *(*(a + i) + j + 1))
t = 1;
}
}
//检查同一列是否还有可加项
for (j = 0;j < SIZE;j++) {
for (i = 0;i < SIZE - 1;i++) {
if (*(*(a + i) + j) == *(*(a + i + 1) + j))
t = 1;
}
}
if (t == 1) {
return 1;
}
}
return 0;
}
void print(int(*a)[SIZE]) {
int i, j;
system("CLS");
//输出打印游戏界面
printf("\n\n");
printf("\n\n");
printf("\n\n");
printf("\n\n");
printf("\t\t\t\t\tGame: 2048 score:%5d high score:%5d\n", score, high);
printf("\t\t\t\t\t------------------------------------------------------------");
printf("\n\n");
printf("\t\t\t\t\t\t---------------------------------\n");
// printf("\t|");
for (i = 0;i < SIZE;i++) {
printf("\t\t\t\t\t\t|");
for (j = 0;j < SIZE;j++) {
if (*(*(a + i) + j) == 0)
printf(" |");
else
printf("%7d|", *(*(a + i) + j));
}
printf("\n");
printf("\t\t\t\t\t\t---------------------------------\n");
}
printf("\n");
printf("\n");
printf("\t\t\t\t\t\t-----------------------------------------------------------\n");
printf("\t\t\t[W]:UP\t[S]:DOWN\t[A]:LEFT\t[D]:RIGHT\t[1]:NEXT\t[2]:SAVE AND QUIT\n");
}
int SUMscore(int(*a)[SIZE]) {
int highest = 0;
int i, j;
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
if (*(*(a + i) + j) > highest)
highest = *(*(a + i) + j);
}
}
return highest;
}
void product(int(*a)[SIZE]) {
int i, j, t, w;
//判断是否还有为0的点,防止函数持续产生,无法终止 ***
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
if (*(*(a + i) + j) == 0)
w = 0;
}
}
if (w == 0) {
do {
i = rand() % SIZE;
j = rand() % SIZE;
} while (*(*(a + i) + j) != 0);
t = rand() % 2;
if (t == 1)
*(*(a + i) + j) = 2;
else if (t == 0)
*(*(a + i) + j) = 4;
}
}
void saveGame(int(*a)[SIZE]) {
FILE* fp;
int i, j;
fp = fopen("tgame.txt", "w");
if (!fp) {
printf("ERROR!读取内存失败\n");
return;
}
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
fprintf(fp, "%d\n", a[i][j]);//文件读取的时候注意
}
}
fclose(fp);
}
void left(int(*a)[SIZE]) {
//为水平向左移
int i, j, k;
for (i = 0;i < SIZE;i++) {
for (k = 1;k <= SIZE - 1;k++) {//通过数学推演得出,至少要令其循环3次
for (j = 1;j < SIZE;j++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i) + j - 1) == 0) {
*(*(a + i) + j - 1) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
//检查是否有相同的项,此时只在乎水平方向上的
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE - 1;j++) {
if (*(*(a + i) + j) != 0 && *(*(a + i) + j) == *(*(a + i) + j + 1)) {
*(*(a + i) + j) = *(*(a + i) + j) * 2;
*(*(a + i) + j + 1) = 0;
}
}
}
for (i = 0;i < SIZE;i++) {
for (k = 1;k <= SIZE - 1;k++) {//通过数学推演得出,至少要令其循环3次
for (j = 1;j < SIZE;j++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i) + j - 1) == 0) {
*(*(a + i) + j - 1) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
}
void down(int(*a)[SIZE]) {
//向下移动,此时则应该是以列为基准
int i, j, k;
for (j = 0;j < SIZE;j++) {
for (k = 1;k <= SIZE - 1;k++) {
for (i = 0;i < SIZE - 1;i++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i + 1) + j) == 0) {
*(*(a + i + 1) + j) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
//检查是否有相同项
for (j = 0;j < SIZE;j++) {
for (i = SIZE - 1;i > 0;i--) {
if (*(*(a + i) + j) != 0 && *(*(a + i - 1) + j) == *(*(a + i) + j)) {
*(*(a + i) + j) *= 2;
*(*(a + i - 1) + j) = 0;
}
}
}
//再次向下移
for (j = 0;j < SIZE;j++) {
for (k = 1;k <= SIZE - 1;k++) {
for (i = 0;i < SIZE - 1;i++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i + 1) + j) == 0) {
*(*(a + i + 1) + j) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
}
void up(int(*a)[SIZE]) {
int i, j, k;
for (j = 0;j < SIZE;j++) {
for (k = 1;k <= SIZE - 1;k++) {
for (i = 1;i < SIZE;i++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i - 1) + j) == 0) {
*(*(a + i - 1) + j) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
//检查是否有相同项
for (j = 0;j < SIZE;j++) {
for (i = 0;i < SIZE - 1;i++) {
if (*(*(a + i) + j) != 0 && *(*(a + i) + j) == *(*(a + i + 1) + j)) {
*(*(a + i) + j) *= 2;
*(*(a + i + 1) + j) = 0;
}
}
}
//再次向上移
for (j = 0;j < SIZE;j++) {
for (k = 1;k <= SIZE - 1;k++) {
for (i = 1;i < SIZE;i++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i - 1) + j) == 0) {
*(*(a + i - 1) + j) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
}
void right(int(*a)[SIZE]) {
int i, j, k;
for (i = 0;i < SIZE;i++) {
for (k = 1;k <= SIZE - 1;k++) {
for (j = 0;j < SIZE - 1;j++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i) + j + 1) == 0) {
*(*(a + i) + j + 1) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
//检查是否有相同项
for (i = 0;i < SIZE;i++) {
for (j = SIZE - 1;j > 0;j--) {
if (*(*(a + i) + j) != 0 && *(*(a + i) + j) == *(*(a + i) + j - 1)) {
*(*(a + i) + j) *= 2;
*(*(a + i) + j - 1) = 0;
}
}
}
//再次右移
for (i = 0;i < SIZE;i++) {
for (k = 1;k <= SIZE - 1;k++) {
for (j = 0;j < SIZE - 1;j++) {
if (*(*(a + i) + j) != 0) {
if (*(*(a + i) + j + 1) == 0) {
*(*(a + i) + j + 1) = *(*(a + i) + j);
*(*(a + i) + j) = 0;
}
}
}
}
}
}
void win(int(*a)[SIZE]) {
int i, j;
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
if (a[i][j] == 2048) {
savescore(score);
system("CLS");
printf("Congratulations!!!\n");
printf("You have winned the game!\n");
printf("本局游戏分数为%d,历史最高分为%d\n", score, high);
score = 0;
savescore(score);
exit(0);
}
}
}
}
//找回密码
void find(users a) {
users c;
char t;
system("CLS");
printf("\n\n\t\t\t欢迎来到找回密码界面\n\n");
printf("请输入你的姓名\n");
scanf("%s", c.name);
fflush(stdin);
if (strcmp(c.name, a.name) == 0) {
printf("请输入你的性别\n");
c.sex = getchar();
fflush(stdin);
if (c.sex == a.sex) {
printf("请输入你的号码\n");
scanf("%d", &c.phone);
if (c.phone == a.phone) {
printf("您的密码是:\n");
printf("\t\t\t%s\n", a.cryptography);
while (1) {
fflush(stdin);
printf("按1返回登录界面\n");
t = getchar();
if (t == '1') {
load();
break;
}
}
}
else {
printf("号码输入错误,请重新输入\n");
Sleep(500);
find(a);
}
}
else {
printf("性别输入错误,请重新输入\n");
find(a);
}
}
else {
printf("姓名输入错误,请重新输入\n");
find(a);
}
}
//注册一个账号
void get() {
FILE* fp;
users a, b;
char attempt[100];
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 1);
printf("\n\n\n\n\t\t\t\t\t欢迎来到注册界面\n");
Sleep(500);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
printf("\t\t\t\t请输入你要注册的用户名,用户名不支持空白符\n");
scanf("%s", a.username);
fflush(stdin);
fp = fopen("user.txt", "a+");
fread(&b, sizeof(users), 1, fp);//从定义的用户名库中读取一个用户名
//比较注册时输入的用户名与实际的用户名是否相同
while (1) {
if (strcmp(a.username, b.username) == 0) {
printf("\t\t\t\t用户名已存在,请再输入其他用户名\n");
Sleep(500);
fclose(fp);
fflush(stdin);
get();
return;
}
else {
if (!feof(fp))
fread(&b, sizeof(users), 1, fp);
else {
printf("\t\t\t\t用户名创建成功\n");
break;
}
}
}
//fclose(fp);
//fp=fopen("user.txt","a");
while (1) {
printf("\t\t\t\t请输入密码\n");
scanf("%s", a.cryptography);
printf("\t\t\t\t请再次输入密码\n");
scanf("%s", attempt);
if (strcmp(attempt, a.cryptography) == 0) {
printf("\t\t\t\t输入密码成功\n");
break;
}
else
printf("\t\t\t\t两次密码不相同,请再次输入密码\n");
}
printf("\t\t\t\t请输入您的姓名\n");
scanf("%s", a.name);
fflush(stdin);
while (1) {
printf("\t\t\t\t请输入您的性别,以m代表男性,f代表女性\n");
scanf("%c", &a.sex);
fflush(stdin);
if (a.sex == 'f' || a.sex == 'm')
break;
}
printf("\t\t\t\t请输入你的电话号码\n");
scanf("%d", &a.phone);
printf("\t\t\t\t账号创建成功\n");
Sleep(500);
fwrite(&a, sizeof(users), 1, fp);
fclose(fp);
}
float load() {
FILE* fp;
users a, b;
int i = 0, m, n;
fp = fopen("user.txt", "r");
if (feof(fp)) {
printf("\t\t\t\t该用户名不存在,您将返回注册界面\n");
get();
return;
}
fread(&b, sizeof(users), 1, fp);
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
printf("\n\n\n\n\t\t\t\t\t请输入你的账号\n");
scanf("%s", a.username);
fflush(stdin);
while (1) {
if (strcmp(a.username, b.username) == 0)
break;
else {
if (!feof(fp))//如果文件没有读到结尾处***
fread(&b, sizeof(users), 1, fp);
else {
do {
printf("\t\t\t\t该用户名不存在,请选择注册一个新的账号或者重新输入\n");
printf("\t\t\t\t注册新账号请输入1\n");
printf("\t\t\t\t重新输入请按2\n");
scanf("%d", &n);
fflush(stdin);
} while (n != 1 && n != 2);
if (n == 1) {
fclose(fp);
get();
load();
return;
}
else if (n == 2) {
Sleep(500);
fclose(fp);
load();
return;
}
}
}
}
while (i < 3) {
printf("\t\t\t\t请输入密码\n");
scanf("%s", a.cryptography);
i++;
if (strcmp(a.cryptography, b.cryptography) == 0) {
fclose(fp);
system("CLS");
printf("\t\t\t\t登录成功\n");
printf("\t\t\t\t欢迎来到2048小游戏\n");
system("CLS");
return;
}
else {
fclose(fp);
printf("密码错误!\n");
do {
printf("请选择再次输入密码或找回密码\n");
printf("再次输入密码请按1,找回密码请按2\n");
scanf("%d", &m);
fflush(stdin);
} while (m != 1 && m != 2);
if (m == 2) {
find(b);
}
}
}
printf("密码输入错误!\n");
access();
}
int access() {
system("CLS");
char t;
do {
printf("新用户注册请按1\n");
printf("登录请按2\n");
fflush(stdin);
scanf("%c", &t);
fflush(stdin);
} while (t != '1' && t != '2');
if (t == '1') {
get();
return;
}
else if (t == '2') {
load();
return;
}
// else
// access();//返回函数开头
}
void kaitou() {
int i;
printf("\n\n\n\n\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
printf("\n\n\n\n\n\n\t\t\t\t\t\t\t欢迎来到2048!\n");
Sleep(500);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
printf("\n\n\n\n\n\n\t\t\t\t\t\t\t欢迎来到2048!\n");
Sleep(500);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
printf("\n\n\n\n\n\n\t\t\t\t\t\t\t欢迎来到2048!\n");
Sleep(500);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 1);
printf("\n\n\n\n\n\n\t\t\t\t\t\t\t欢迎来到2048!\n");
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 1);
printf("\n\n\n\n\n\n\t\t\t\t本游戏本着做出一款高端的2048游戏原则\n");
Sleep(500);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2);
printf("\n\n\n\n\n\n\t\t\t\t现在\n");
Sleep(500);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 3);
printf("\n\n\n\n\n\n\t\t\t\t开启你的奇妙之旅吧!\n");
for (i = 1;i <= 4;i++) {
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), i);
printf(" * * * * * * *\n");
printf(" * * * * * * * *\n");
printf(" * * * * * * * * * * * * * * * *\n");
printf(" * * * * * *\n");
printf(" * * * * * *\n");
printf(" * * * * * * \n");
printf(" * * * * * * *\n");
printf(" * * * * * * * * * * * \n");
Sleep(200);
}
sleep(1);
}
int main() {
int t, i, j, num = 0, o = 0;
char c, h;
int a[SIZE][SIZE];
//打开界面
kaitou();
//用户登录注册系统
access();
//读取历史最高分记录
high = loadscore();
srand(time(NULL));//播撒随机数种子
start:SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);//设置颜色
printf("欢迎来到2048小游戏:\n");
for (i = 0;i < SIZE;i++) {
for (j = 0;j < SIZE;j++) {
a[i][j] = 0;
}
}//将框内的元素都定义为0,即赋初值操作
begin(a);//菜单
printf("请键入你想要哪种输入方式\n");
do {
fflush(stdin);
printf("如果你想要用字母盘上的,则输入1;如果你想要用方向键,则键入2\n");
scanf("%c", &h);
fflush(stdin);
} while (h != '1' && h != '2');
product(a);
//进入游戏
do {
t = check(a);//返回1为未结束,返回0为结束
if (t == 0) {
if (score > high)
savescore(score);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
printf("\n\n\n\n\n\nTry again! I`m sure you will get better scores!\n");
Sleep(500);
system("CLS");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 1);
printf("\n\n\n\n\n\t\t\t本局得分为%d,历史最高分为%d\n", score, high);
Sleep(500);
system("CLS");
printf("\n\n\n\n\n\n\t\t\t\t是否要再来一次:\n");
printf("\t\t\t\t\t\t\t按下1表示再来一局,其余键表示结束游戏\n");
score = 0;
fflush(stdin);
if (getchar() == '1') {
goto start;
}
else
exit(0);
}
if (o != 0) {
num = SUMscore(a);
score += num;
}
o = 1;//防止第一次的分数被算入
product(a);//在表内产生一个随机数2或者4
if (score > high)
savescore(score);
high = loadscore();
print(a);//显示当前界面
//选择键盘输入方式
if (h == '2') {
getch();
switch (getch()) {
case 72:
case 'w':up(a);break;
case 80:
case 's':down(a);break;
case 75:
case 'a':left(a);break;
case 77:
case 'd':right(a);break;
case '2':saveGame(a);
Sleep(500);
exit(0);
}
}
else if (h == '1') {
switch (getch()) {
case 72:
case 'w':up(a);break;
case 80:
case 's':down(a);break;
case 75:
case 'a':left(a);break;
case 77:
case 'd':right(a);break;
case '2':saveGame(a);
Sleep(500);
exit(0);
}
}
win(a);
} while (1);
system("PAUSE");
return 0;
}