写代码容易,构思难啊。为了写这还专门玩了玩2048小游戏,将里面的步骤分解,变成一个一个的函数,才慢慢写完这个小游戏。写加上改代码,测差不多4个多晚上啊。
先说自己遇到的一些问题:
最大的一个问题便是getchar();当输入一个字符时,它会接收回车键,导致程序多跑一边。
1.使用了 fflush(stdin)用了清空缓存区但不知道为什莫不管用。
2.想了一个笨办法:ch=getchar(); getchar()
或是:scanf("%c\\n", &ch);
反正是搞定了。
查的相关的知识点:
1.产生一定范围的随机数:
C语言的获取随机数的函数为rand(), 可以获得一个非负整数的随机数。要调用rand需要引用头文件
stdlib.h
。
要让随机数限定在一个范围,可以采用模除加加法的方式。
要产生随机数r, 其范围为 m<=r<=n,可以使用如下公式:
rand()%(n-m+1)+m
其原理为,对于任意数,
0<=rand()%(n-m+1)<=n-m
于是
0+m<=rand()%(n-m+1)+m<=n-m+m
即
m<=rand()%(n-m+1)+m<=n
要让随机数限定在一个范围,可以采用模除加加法的方式。
要产生随机数r, 其范围为 m<=r<=n,可以使用如下公式:
rand()%(n-m+1)+m
其原理为,对于任意数,
0<=rand()%(n-m+1)<=n-m
于是
0+m<=rand()%(n-m+1)+m<=n-m+m
即
m<=rand()%(n-m+1)+m<=n
2.
exit() 是电脑函数
3。getchar()
如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键.
具体代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define OK 1
#define ERRORY 0
int times = 0;
int pane[9][9];
typedef struct Head
{
int order;
int data1;
int data2;
struct Head *next;
}Pane_number, *Pane;
//功能函数
void grid();//打印4*4格子
void init_pane();//初始化二维数组
void move_up();//格子向上移动
void move_down();//格子向下移动
void move_left();//向左移动
void move_right();//向右移动
Pane ergodic_gane(Pane head);//遍历所有的格子存在链表里
void delete_other(Pane head);//删除除过表头以外的链表节点
void new_number(Pane head);//移动一次产生一个新数
int judge_end(Pane head);//判断是否结束
int score();//显示分数
void select();//方向选择;
void play(Pane head);
void menu(Pane head);//界面初始化
//函数实现
//打印4*4格子
void grid()
{
int i = 0, j = 0, k = 0;
for (k = 0; k<21; k++)
{
printf("*");
}
printf("\n");
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
printf("* ");
}
printf("*\n");
for (j = 0; j<4; j++)
{
if (pane[i][j] == 0)
{
printf("* ");
}
else
{
if (pane[i][j] < 10)
{
printf("*%d ", pane[i][j]);
}
if (pane[i][j] >= 10 && pane[i][j] < 100)
{
printf("*%d ", pane[i][j]);
}
if (pane[i][j] >= 100 && pane[i][j] < 1000)
{
printf("*%d ", pane[i][j]);
}
if (pane[i][j] >= 1000)
{
printf("%d", pane[i][j]);
}
}
}
printf("*\n");
for (k = 0; k<21; k++)
{
printf("*");
}
printf("\n");
}
}
//初始化二维数组
void init_pane()
{
int i = 0, j = 0;
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
pane[i][j] = 0;
}
}
srand(time(NULL));
i = rand() % 4;
j = rand() % 4;
if (i == 0 || i == 2)
{
pane[i][j] = 2;
}
else
{
pane[i][j] = 4;
}
}
//格子向上移动
void move_up()
{
//遍历每个格子,合并相同的数字
int k = 0, i = 0, j = 0;
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[j][i] == 0)
;
else
{
for (k = j + 1; k<4; k++)
{
if (pane[k][i] == 0)
;
else
{
if (pane[j][i] == pane[k][i])
{
pane[j][i] = pane[j][i] * 2;
pane[k][i] = 0;
break;
}
}
}
}
}
}
//向上来移动格子,使得其没有空格
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[j][i] == 0)
{
for (k = j + 1; k<4; k++)
{
if (pane[k][i] == 0)
;
else
{
pane[j][i] = pane[k][i];
pane[k][i] = 0;
break;
}
}
}
}
}
}
//格子向下移动
void move_down()
{
//遍历每个格子,合并相同的数字
int k = 0, i = 0, j = 0;
for (i = 3; i >= 0; i--)
{
for (j = 3; j >= 0; j--)
{
if (pane[j][i] == 0)
;
else
{
for (k = j - 1; k >= 0; k--)
{
if (pane[k][i] == 0)
;
else
{
if (pane[k][i] == pane[j][i])
{
pane[j][i] = pane[j][i] * 2;
pane[k][i] = 0;
break;
}
}
}
}
}
}
//向下来移动格子,使得其没有空格
for (i = 3; i >= 0; i--)
{
for (j = 3; j >= 0; j--)
{
if (pane[j][i] == 0)
{
for (k = j - 1; k >= 0; k--)
{
if (pane[k][i] == 0)
;
else
{
pane[j][i] = pane[k][i];
pane[k][i] = 0;
break;
}
}
}
}
}
}
//向左移动
void move_left()
{
//遍历每个格子,合并相同的数字
int k = 0, i = 0, j = 0;
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[i][j] == 0)
;
else
{
for (k = j + 1; k<4; k++)
{
if (pane[i][k] == 0)
;
else
{
if (pane[i][k] == pane[i][k])
{
pane[i][j] = pane[i][j] * 2;
pane[i][k] = 0;
break;
}
}
}
}
}
}
//向左来移动格子,使得其没有空格
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[i][j] == 0)
{
for (k = j + 1; k<4; k++)
{
if (pane[i][k] == 0)
;
else
{
pane[i][j] = pane[i][k];
pane[i][k] = 0;
break;
}
}
}
}
}
}
//向右移动
void move_right()
{
//遍历每个格子,合并相同的数字
int k = 0, i = 0, j = 0;
for (i = 3; i >= 0; i--)
{
for (j = 3; j >= 0; j--)
{
if (pane[i][j] == 0)
;
else
{
for (k = j - 1; k >= 0; k--)
{
if (pane[i][k] == 0)
;
else
{
if (pane[i][k] == pane[i][j])
{
pane[i][j] = pane[i][j] * 2;
pane[i][k] = 0;
break;
}
}
}
}
}
}
//向右来移动格子,使得其没有空格
for (i = 3; i >= 0; i--)
{
for (j = 3; j >= 0; j--)
{
if (pane[i][j] == 0)
{
for (k = j - 1; k >= 0; k--)
{
if (pane[i][k] == 0)
;
else
{
pane[i][j] = pane[i][k];
pane[i][k] = 0;
break;
}
}
}
}
}
}
//产生一个新数
void new_number(Pane head)
{
int i = 0, k = 0;
Pane sign, re;
sign = ergodic_gane(head);
re = ergodic_gane(head);
//随机选择一个空格子,赋值给2
srand(time(NULL));
k = rand() % sign->order + 1;
//printf("空个数:%d\n", re->order);
//printf("被选择的格子:%d\n", k);
for (i = 0; i <= re->order; i++)
{
sign = sign->next;
if (sign->order == k)
{
pane[sign->data1][sign->data2] = 2;
//printf("坐标是:%d %d\n", sign->data1, sign->data2);
}
}
}
//显示分数
int score()
{
int i = 0, j = 0, total = 0;
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[i][j] != 0)
total = pane[i][j] + total;
}
}
printf("The score: %d\n", total);
return (0);
}
//遍历所有的格子将信息存在链表里
Pane ergodic_gane(Pane head)
{
int i = 0, j = 0, sum = 0;
//现遍历所有的格子
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[i][j] == 0)
{
Pane p = (Pane)malloc(sizeof(Pane_number));
p->data1 = i;
p->data2 = j;
sum = sum++;
p->order = sum;
p->next = head->next;
head->next = p;
}
}
}
if (head->next == NULL)
{
head->order = 0;
}
else
{
head->order = head->next->order;
}
return (head);
}
//删除除过表头以外的链表节点
void delete_other(Pane head)
{
Pane p, q;
p = head->next;
if (head->next == NULL)
;
else
{
q = p->next;
free(p);
p = q;
}
head->order = 0;
head->next = 0;
}
//判断是否结束
int judge_end(Pane head)
{
int i = 0, j = 0, k = 0;
Pane mm;
mm = ergodic_gane(head);
for (i = 0; i<4; i++)
{
for (j = 0; j<4; j++)
{
if (pane[i][j] == 2048)
k = 1;
}
}
//printf("判断已调用\n");
if (mm->order == 0 || k == 1)
return ERRORY;
else
return OK;
}
//选择移动方向
void select()
{
char ch = 0;
//fflush(stdin);
printf("Please import control key !\n");
scanf("%c\\n", &ch); //接收了回车键,消除回车键的影响
if (ch <= 'z' && ch >= 'a')
ch -= 32;
while (ch != 'A' && ch != 'D' && ch != 'S' && ch != 'W' && ch != 'Q')
{
printf("caution! caution! \n");
printf("please enter again !\n");
scanf("%c\\n", &ch);
if (ch <= 'z' && ch >= 'a')
ch -= 32;
}
switch (ch)
{
case 'A': move_left(); break;
case 'D': move_right(); break;
case 'S': move_down(); break;
case 'W': move_up(); break;
case 'Q': exit(0);
default: break;
}
}
void play(Pane head)
{
new_number(head);
score();
grid();
delete_other(head);
}
//界面初始化
void menu(Pane head)
{
system("color 05");
printf("****************************\n");
printf(" 2048 \n\n");
printf("Control by:\n"
" w/s/a/d or W/S/A/D\n");
printf("press q or Q quit game!\n");
printf("****************************\n");
printf("Press any key to continue . . .\n");
getchar();
system("cls");
init_pane();
new_number(head);
grid();
system("pause");
}
int main()
{
Pane head;
head = (Pane)malloc(sizeof(Pane_number));
head->next = NULL;
menu(head);
while (judge_end(head))
{
select();
system("cls");
play(head);
}
return 0;
}