基本要求
(1)实现游戏规则
(2)使用国形函数生成界面等。
(3)用文件存储用户的进度。
(4)用户开始新游戏时,先检测是否有历史记录,有的话可以继续未完成的游戏,也可以重新开始。
(5)实现用户排名功能
游戏规则:
2048游戏共有16个格子,初始时初始数字由2或者4构成。
1、手指向一个方向滑动,所有格子会向那个方向运动。
2、相同数字的两个格子,相撞时数字会相加。
3、每次滑动时,空白处会随机刷新出一个数字的格子。
4、当界面不可运动时(当界面全部被数字填满时),游戏结束;当界面中最大数字是2048时,游戏胜利。
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#define N 4//方阵边长
#define WIN 2048//游戏获胜目标
void output(int (*a)[N]){//输出4*4表格,
int i,j;
printf("\n");
printf("┏━━━━┳━━━━┳━━━━┳━━━━┓");//顶边框
printf("\n");
for(i=0;i<N;i++){printf("┃") ;
for(j=0;j<N;j++){
if(a[i][j]==0) printf(" ┃");//如果数值为零则输出空白
else printf("%4d┃",a[i][j]);
}
if(i!=3)
printf("\n┣━━━━╋━━━━╋━━━━╋━━━━┫\n");//层边框
else printf("\n┗━━━━┻━━━━┻━━━━┻━━━━┛\n");//底边框
}
}
int sj24(){//获取随机数2或4
int s[8]={2,2,2,2,2,2,2,4},i,j;//以概率7:1建立2和4的随机数种子
srand((unsigned)time(NULL));
i=(rand())%8;//以时间为种子得到0~7的随机数
return s[i];
}
int input(){//输入上下左右指令控制游戏
int m;
if(getch()==0xE0){ //对键入的命令进行识别
switch(getch()){//十位1表示水平移动2表示竖直移动,各位1表示向小坐标移动2表示向大坐标移动
case 72: return 21;break;//输入上
case 80: return 22;break;//输入下
case 75: return 11;break;//输入右
case 77: return 12;break;//输入左
default:{//若命令不符合要求,运用递归重新得到命令
printf("请输入正确的指令!(~ ̄(OO) ̄)ブ\n");
return input();
}
}
}
else {//若命令不符合要求,运用递归重新得到命令
printf("请输入正确的指令!(~ ̄(OO) ̄)ブ\n\n");
return input();
}
}
void move(int (*a)[N]){ //通过调用input函数得到正确的命令,根据命令移动数据
int x,i,j,k,s[N][N],t=0;
x=input();
for(i=0;i<N;i++){
for(j=0;j<N;j++) s[i][j]=a[i][j];//拷贝移动前方阵方便以后检查
}
if(x/10==1){//水平移动
if(x%10==1){//向小坐标移动
for(i=0;i<N;i++){for(k=0;k<3;k++){// 核心算法介绍
for(j=N-1;j>0;j--){ //第一步,先将一排数据重后往前一个个向前推(除去前面和中间的0)
if(a[i][j-1]==0) { //为确保移动完全经推理最多3次完成所有移动所有执行3次该算法
a[i][j-1]=a[i][j]; //第二步,将相邻两两相同的数相加赋值前者后者赋0
a[i][j]=0; // 第三部,重复第一步操作去除新产生的0,总操作完成
} //PS:所有方向算法原理相同
}
}
for(j=0;j<N-1;j++){
if(a[i][j]==a[i][j+1]) {
a[i][j]=a[i][j]+a[i][j+1];
a[i][j+1]=0;
}
}
for(k=0;k<3;k++){
for(j=N-1;j>0;j--){
if(a[i][j-1]==0) {
a[i][j-1]=a[i][j];
a[i][j]=0;
}
}
}
}
}
else{//向大坐标移动
for(i=0;i<N;i++){for(k=0;k<3;k++){
for(j=0;j<N-1;j++){
if(a[i][j+1]==0) {
a[i][j+1]=a[i][j];
a[i][j]=0;
}
}
}
for(j=N-1;j>0;j--){
if(a[i][j]==a[i][j-1]) {
a[i][j]=a[i][j]+a[i][j-1];
a[i][j-1]=0;
}
}
for(k=0;k<3;k++){
for(j=0;j<N-1;j++){
if(a[i][j+1]==0) {
a[i][j+1]=a[i][j];
a[i][j]=0;
}
}
}
}
}
}
else{//竖直移动
if(x%10==1){//向小坐标移动
for(i=0;i<N;i++){for(k=0;k<3;k++){
for(j=N-1;j>0;j--){
if(a[j-1][i]==0) {
a[j-1][i]=a[j][i];
a[j][i]=0;
}
}
}
for(j=0;j<N-1;j++){
if(a[j][i]==a[j+1][i]) {
a[j][i]=a[j][i]+a[j+1][i];
a[j+1][i]=0;
}
}
for(k=0;k<3;k++){
for(j=N-1;j>0;j--){
if(a[j-1][i]==0) {
a[j-1][i]=a[j][i];
a[j][i]=0;
}
}
}
}
}
else{//向大坐标移动
for(i=0;i<N;i++){for(k=0;k<3;k++){
for(j=0;j<N-1;j++){
if(a[j+1][i]==0) {
a[j+1][i]=a[j][i];
a[j][i]=0;
}
}
}
for(j=N-1;j>0;j--){
if(a[j][i]==a[j-1][i]) {
a[j][i]=a[j][i]+a[j-1][i];
a[j-1][i]=0;
}
}
for(k=0;k<3;k++){
for(j=0;j<N-1;j++){
if(a[j+1][i]==0) {
a[j+1][i]=a[j][i];
a[j][i]=0;
}
}
}
}
}
}
for(i=0;i<N;i++){//检查是否为有效移动
for(j=0;j<N;j++) {
if (s[i][j]!=a[i][j]) t=1;
}
}
if(t){
begin(a);
Sleep(60);//为让玩家知道移动后随机数出现位置,让其延迟出现
get(a);
begin(a);
}
else printf("选择其他方向试试(¬_¬)");
}
void get(int (*a)[N]){//在4*4表格中空板位置随机获得数字
int i,j;
srand((unsigned)time(NULL));
do{
i=(rand())%4;
j=(rand())%4;
} while(a[i][j]!=0);
a[i][j]=sj24();
}
void begin(int (*a)[N]){//清屏并打印开头
system("cls");
printf(" 小游戏2048\n\n ");
printf(" 键入上下左右控制\n");
output(a);
}
int test(int (*a)[N]){//判断是否游戏完成
int i,j,k=0,m=0,n=0;
printf("\n");
for(i=0;i<N;i++){
for(j=0;j<N;j++){
if(a[i][j]==0)m=1;//检查方阵中是否有0
if(a[i][j]==WIN)k=1; //检查方阵中是否有目标数字
}
}
if (k){//如果发现目标数字判定游戏获胜
printf("YOU WIN! \(^o^)/YES!");
return 0;
}
else{
if(!m){//如果方阵中无0且无相邻数字相等则判定游戏失败,反之游戏继续
for(i=0;i<N;i++){
for(j=0;j<N-1;j++)
if(a[i][j]==a[i][j+1]||a[j][i]==a[j+1][i]) n=1;
}
if(n) return 1;
else{
printf("GAME OVER!〒▽〒");
return 0;
}
}
else return 1;
}
}
void main(){
int a[N][N]={0};
get(a);get(a);begin(a);//起始时方阵有两个随机数
while(test(a)) move(a); //只有通过tset函数检查才能继续游戏
}