关于2048小游戏项目的一些心得

这是我学习完标C和Unix C以后做的一个小游戏,只能支持字符终端界面。在此将其贴出来,希望能够跟大家分享一些心得。以下是我当时写的一个项目文档

==========================2048 by Phoenix游戏开发手册==========================

1.游戏在终端中的显示:
关于2048小游戏项目的一些心得_第1张图片
游戏按键设置:
     w
a   s   d
游戏规则:
用户通过按键移动方格中的数字,相邻格子中的数字如果相同,则可以通过移动
相应的方向来实现相加并将这两个数字合并,率先达到2048则获得胜利。如果方格已
经被充满,既无法相加也无法移动,则游戏失败
***************************************************************************
2.技术支持:
操作系统: Ubuntu
开发工具: vim,gcc,makefile
***************************************************************************
3.游戏中包含的文件:
头文件: color.h,myheadfile.h
存储文件: SaveMap.bin,SaveScore.bin,HistoryHightscore.bin
界面创建: MapPrinter.c
逻辑判定: JudgeLogic.c
事件响应: GameLogic.c
文件操作: FileOperate.c
主文件(程序入口): 2048.c
***************************************************************************
3.游戏的逻辑功能实现(将相应功能模块独立出来并形成相应的文件):
a.游戏逻辑:GameLogic.c(已实现)
  所包含的功能(函数)有move_top,move_down,move_lef,move_right,insert_num,
  run_map;
  move_*函数实现当用户使用按键的时候,相应的移动效果的实现
  insert_num函数用于在移动后的空位中插入随机的2或4
  run_map函数用于获得用户的操作并作出相应的逻辑实现

b.打印地图:MapPrinter.c(已实现)
  所包含的功能(函数)有map_print,init_map,print,print_color;
  map_print用于打印出地图
  init_map用于在游戏开始时且用户上次游戏并未保存的情况下,初始化地图
  print用于打印地图的“-----”
  print_color用于打印出不同颜色的数字

c.判定逻辑:JudgeLogic.c(已实现)
  所包含的功能(函数)有success_judge,fail_judge;
  success_judge如果满足胜利条件则在屏幕上打印"You Win!!",并终止游戏
  fail_judge如果满足失败判定条件,则终止游戏,并在屏幕上打印“You Lose!!”
  
d.文件操作:FileOperate.c(已实现)
  所包含的功能(函数)有open,save_hightscore,save_game;
  open:打开文件SaveMap.txt,查看用户是否有保存上次游戏的结果,如果有则将地
  图加载进来,否则直接初始化地图。
  save_hightscore:当检测到用户的成绩高于历史最高分时,将成绩保存下来
  save_game:用户输入q的时候,将地图写入到SaveMap.bin文件中

e.程序入口:2048.c
  所包含的功能(函数)有:main
  实现功能:为程序的运行提供一个入口
****************************************************************************
4.函数原型设定:
GameLogic.c:
void move_top(int (*)[],int,int*,int*,int*);
void move_down(int (*)[],int,int*,int*,int*);
void move_left(int (*)[],int,int*,int*,int*);
void move_right(int (*)[],int,int*,int*,int*);
void run_map(int (*)[],int,int*,int*,int*,int*);
void insert_num(int (*)[],int);

MapPrinter.c:
static void print(int);
static void print_color(int (*)[],int,int);
void init_map(int (*)[],int);
void map_printer(int (*)[],int,int*,int*);

JudgeLogic.c:
int success_judge(int (*)[],int);
int fail_judge(int (*)[],int,int,int);

FileOperate.c:
int open(int (*)[],int,int*,int*);
int save_hightscore(int);
int save_game(int (*)[],int,int);

2048.c
int main(void);

****************************************************************************

以下是相应的文件实现代码:

头文件:

color.h(定义了Linux中终端颜色显示字段)

#ifndef __COLOR__H
#define __COLOR__H
//定义字体颜色
#define NONE "\033[m" //取消打印的颜色,打印完数字后就要取消掉颜色打印
#define RED_2 "\033[0;40;31m"					//黑底红色	2
#define GREEN_4 "\033[0;40;32m"					//黑底绿色	4
#define DARKYELLOW_8 "\033[0;40;33m"			//黑底土黄	8	
#define BLUE_16 "\033[0;40;36m"					//黑底蓝色	16	
#define PURPLE_32 "\033[0;40;35m"				//黑底紫红	32
#define LIGHT_ORANGE_64 "\033[1;40;31m"			//黑底浅橘  64
#define ORANGE_128 "\033[1;40;32m"				//黑底橘红	128
#define YELLOW_256 "\033[1;40;33m"				//黑底黄色	256
#define LIGHT_PURPLE_512 "\033[1;40;34m"		//黑底浅紫	512
#define PINK_1024 "\033[1;40;35m"				//黑底粉字	1024
#define CAYN_2048 "\033[1;40;36m"				//黑底青色	2048
#define BACKGROUND "\033[1;40m"					//黑色背景
#endif //__COLOR__H
myheadfile.h(声明了整个2048游戏中的函数及其共享宏变量)

#ifndef __MYHEADFILE__H
#define __MYHEADFILE__H
//共享的宏变量定义
#include 
#include 
#include 
#define SIZE 4
#define FILENAME map.txt
#define FILESCORE score.bin
//函数声明
//GameLogic.c
void move_top(int (*)[],int,int*,int*,int*);
void move_down(int (*)[],int,int*,int*,int*);
void move_left(int (*)[],int,int*,int*,int*);
void move_right(int (*)[],int,int*,int*,int*);
void insert_num(int (*)[],int);
void run_map(int (*)[],int,int*,int*,int*,int*);
//FileOperate.c
int open(int (*)[],int,int*,int*);
int save_hightscore(int);
int save_game(int (*)[],int,int);
//MapPrinter.c
void init_map(int (*)[],int);
void map_printer(int (*)[],int,int*,int*);
//JudgeLogic.c
int success_judge(int (*)[],int);
int fail_judge(int (*)[],int,int,int);
#endif

C文件:

2048,c(游戏入口文件)

#include "myheadfile.h"
int main(void){
	srand(time(0));
	int arr[SIZE][SIZE] = {};
	int IsMove,IsPlus,score = 0,hightscore = 0;
	if(open(arr,4,&score,&hightscore)){
		map_printer(arr,4,&score,&hightscore);
	}
	else{
		init_map(arr,4);
		map_printer(arr,4,&score,&hightscore);
	}
	run_map(arr,4,&score,&hightscore,&IsMove,&IsPlus);
	return 0;
}

MapPrinter.c(负责打印游戏界面)

#include "color.h"
#include "myheadfile.h"
static void print(int size){
	int i;
	for(i = 0;i < size;i++){
		printf("-----");
	}
	printf("\n");
}
void init_map(int (*arr)[SIZE],int size){
	int randone = rand()%size;
	int randtwo = rand()%size;
	int randthree = rand()%size;
	int randfour = rand()%size;
	arr[randone][randtwo]=2;
	arr[randthree][randfour]=4;
}
static void print_color(int (*arr)[SIZE],int size,int row,int col){
	switch(arr[row][col]){
		case 0:
			printf("|"BACKGROUND"    "NONE);
			break;
		case 2:
			printf("|"RED_2"2   "NONE);
			break;
		case 4:
			printf("|"GREEN_4"4   "NONE);
			break;
		case 8:
			printf("|"DARKYELLOW_8"8   "NONE);
			break;
		case 16:
			printf("|"BLUE_16"16  "NONE);
			break;
		case 32:
			printf("|"PURPLE_32"32  "NONE);
			break;
		case 64:
			printf("|"LIGHT_ORANGE_64"64  "NONE);
			break;
		case 128:
			printf("|"ORANGE_128"128 "NONE);
			break;
		case 256:
			printf("|"YELLOW_256"256 "NONE);
			break;
		case 512:
			printf("|"LIGHT_PURPLE_512"512 "NONE);
			break;
		case 1024:
			printf("|"PINK_1024"1024"NONE);
			break;
		case 2048:
			printf("|"CAYN_2048"2048"NONE);
			break;
		default:
			break;
	}
}
void map_printer(int (*arr)[SIZE],int size,int *score,int *hightscore){
	int i,j;
	system("clear");
	printf("2048 by Phoenix\n");
	printf("Score:%d\tHightScore:%d\n",*score,*hightscore);
	print(size);
	for(i = 0;i < size;i++){
		for(j = 0;j < size;j++){
				print_color(arr,size,i,j);
		}
		printf("|\n");
		print(size);
	}
}

GameLogic.c(实现游戏的相应操作)

#include "myheadfile.h"
//向上移动
void move_top(int (*arr)[SIZE],int size,int* score,int* IsPlus,int *IsMove){
	int i,j,k;
	for(i = 0;i < size;i++){
		k=0;
		while(arr[k][i]&&k=0){	//找到同列不同行中值为0的数并得到行号
			k--;
		}
		for(j = k-1;j >= 0;j--){
			if(arr[j][i]!=0){
				arr[k][i] = arr[j][i];
				arr[j][i] = 0;
				k--;
				*IsMove = 1;
			}
		}
		for(k=size-1;k>0;k--){
			if(arr[k][i] == arr[k-1][i]&&arr[k][i]!=0){
				arr[k][i] *= 2;
				*score += arr[k][i];
				arr[k-1][i] = 0;
				*IsPlus = 1;
				*IsMove = 1;
			}
		}
	}
	for(i = 0;i < size;i++){
		k=size-1;
		while(arr[k][i]&&k>=0){
			k--;
		}
		for(j = k-1;j >= 0;j--){
			if(arr[j][i]!=0){
				arr[k][i] = arr[j][i];
				arr[j][i] = 0;
				k--;
				*IsMove = 1;
			}
		}
	}
}
//向左移动
void move_left(int (*arr)[SIZE],int size,int* score,int* IsPlus,int* IsMove){
	int i,j,k;
	for(i = 0;i < size;i++){
		k = 0;
		while(arr[i][k]&&k=0){	//找到同列不同行中值为0的数并得到行号
			k--;
		}
		//向右移动
		for(j = k-1;j >= 0;j--){
			if(arr[i][j]!=0){
				arr[i][k] = arr[i][j];
				arr[i][j] = 0;
				k--;
				*IsMove = 1;
			}
		}
		/****************************************************************/
		//判断相加
		for(k=size-1;k>0;k--){
			if(arr[i][k] == arr[i][k-1]&&arr[i][k]!=0){
				arr[i][k] *= 2;
				*score += arr[i][k];
				arr[i][k-1] = 0;
				*IsPlus = 1;
				*IsMove = 1;
			}
		}
		/******************************************************************/
	}
	//移动
	for(i = 0;i < size;i++){
		k=size-1;
		while(arr[i][k]&&k>=0){
			k--;
		}
		for(j = k-1;j >= 0;j--){
			if(arr[i][j]!=0){
				arr[i][k] = arr[i][j];
				arr[i][j] = 0;
				k--;
				*IsMove = 1;
			}
		}
	}
}
/************************************************************************/
void insert_num(int (*arr)[SIZE],int size){
	int randX,randY,randnum;
	randnum = rand()%2;			//randnum的值为0或1,0表示在,1表示4
	do{
		randX=rand()%size;
		randY=rand()%size;
		if(arr[randX][randY] == 0){
			if(randnum == 0){
				arr[randX][randY] = 2;
				break;
			}
			else{
				arr[randX][randY] = 4;
				break;
			}
		}
	}while(1);
}
void run_map(int (*arr)[SIZE],int size,int *score,int *hightscore,int *IsMove,int *IsPlus){
	char input;
	int i,j;
	int save = 0;
	while(1){
		*IsMove = 0;
		*IsPlus = 0;
		scanf("%c",&input);
		scanf("%*[^\n]");
		scanf("%*c");
		switch(input){
			case 'w':
				move_top(arr,4,score,IsPlus,IsMove);
				break;
			case 's':
				move_down(arr,4,score,IsPlus,IsMove);
				break;
			case 'a':
				move_left(arr,4,score,IsPlus,IsMove);
				break;
			case 'd':
				move_right(arr,4,score,IsPlus,IsMove);
				break;
			case 'q':
				printf("Saving……,Please wait!!\n");
				save = save_game(arr,size,*score);
				sleep(1);
				if(save){
					printf("The game has been saved\n");
					exit(0);
				}
				else{
					printf("Save failed!!\n");
				}
				break;
			default:
				printf("Input error!!\n");
				break;
		}
		if(*IsMove){
			insert_num(arr,4);
		}
		map_printer(arr,4,score,hightscore);
		if(success_judge(arr,4)){
			printf("You Win!!\n");
			for(i=0;i
JudgeLogic.c(实现对游戏输赢的判定)
#include "myheadfile.h"
int success_judge(int (*arr)[SIZE],int size){
	int i,j,success = 0;
	for(i = 0;i < size;i++){
		for(j = 0;j < size;j++){
			if(arr[i][j] == 2048){
				success = 1;	
			}
		}
	}
	return success;
}
int fail_judge(int (*arr)[SIZE],int size,int IsMove,int IsPlus){
	int i,j,tmp = 0,fail = 0,col = 0,row = 0;
	//循环判断数组中是否还有空位,有则tmp=1,无则tmp=0
	for(i = 0;i < size;i++)
		for(j = 0;j < size;j++){
			if(!arr[i][j])
				tmp = 1;
		}
	for(i = 0;i < size;i++)
		for(j = 0;j < size-1;j++){
			if(arr[i][j] == arr[i][j+1] && arr[i][j] != 0){
				col = 1;
			}
			if(arr[j][i] == arr[j+1][i] && arr[j][i] != 0){
				row = 1;
			}
		}
	if(!IsMove && !IsPlus && !tmp && !col && !row){
		fail = 1;
	}
	return fail;
}

FileOperate.c(通过文件来保存相应的玩家信息及历史最高分)

#include "myheadfile.h"
int open(int (*arr)[SIZE],int size,int *score,int *hightscore){
	FILE *p_file = fopen("SaveMap.bin","r");
	int i,j,failed = 0;
	if(NULL == p_file){
		printf("File open error!!\n");
		return 0;
	}
	else{
		for(i = 0;i < size;i++){
			failed = fread(arr[i],sizeof(int),size,p_file);
		}
		for(i = 0;i < size;i++){
			for(j = 0;j < size-1;j++){
				if(arr[i][j] == arr[i][j-1] && !arr[i][j]){
					failed = 0;
				}
				else{
					failed = 1;
				}
			}
		}
		fclose(p_file);
		p_file = fopen("SaveScore.bin","r");
		if(NULL == p_file){
			printf("ERROR:Can not read SaveScore.bin\n");
			return 0;
		}
		else{
			fread(score,sizeof(int),1,p_file);
			fclose(p_file);
			p_file = fopen("HistoryHightscore.bin","r");
			if(NULL == p_file){
				printf("ERROR:Can not read HistoryHightscore.bin\n");
				return 0;
			}
			else{
				fread(hightscore,sizeof(int),1,p_file);
				printf("11111111111111111:%d\n",*hightscore);
				fclose(p_file);
				p_file = NULL;
			}
		}
		return failed;
	}
}
int save_hightscore(int score){
	FILE *p_file = fopen("HistoryHightscore.bin","r+");
	int hightscore;
	if(NULL == p_file){
		printf("ERROR:Can not open HistoryHightscore.c!!\n");
		return 0;
	}
	else{
		fread(&hightscore,sizeof(int),1,p_file);
		if(score > hightscore){
			rewind(p_file);
			fwrite(&score,sizeof(int),1,p_file);
		}
		fclose(p_file);
		p_file = NULL;
		return 1;
	}
}
int save_game(int (*arr)[SIZE],int size,int score){
	FILE *p_file = fopen("SaveMap.bin","w");
	int i;
	if(NULL == p_file){
		printf("ERROR:Can not open SaveMap.bin!!\n");
		return 0;
	}
	else{
		for(i = 0;i < size;i++){
			fwrite(arr[i],sizeof(int),size,p_file);
		}
		fclose(p_file);
		p_file = fopen("SaveScore.bin","w");
		if(NULL == p_file){
			printf("ERROR:Can not open SaveScore.bin!!\n");
			return 0;
		}
		else{
			fwrite(&score,sizeof(int),1,p_file);
			fclose(p_file);
			p_file = NULL;
			return 1;
		}
	}
}

最终的程序运行结果:

关于2048小游戏项目的一些心得_第2张图片



你可能感兴趣的:(关于2048小游戏项目的一些心得)