此次共分为五个模块,其中.c文件三个(mian.c,draw.c.control.c)以及两个库函数(draw.h,control.h)。语言及思路均通俗易懂,部分函数过程较为冗杂,但思路简单。
实现环境为linux。
一、.c文件
1.mian.c //主函数
#include"draw.h"
int main()
{
int box[4][4]={0};
int score=0,steps=0;
int n;
srand(time(NULL));
put_Num(box);
put_Num(box);
ShowMenu(box,steps,score);
while(1){
n=inputCmd();
switch(n){
case 1:
Move_up(box,&score);
steps++;
put_Num(box);
ShowMenu(box,steps,score);
break;
case 2:
Move_down(box,&score);
steps++;
put_Num(box);
ShowMenu(box,steps,score);
break;
case 3:
Move_right(box,&score);
steps++;
put_Num(box);
ShowMenu(box,steps,score);
break;
case 4:
Move_left(box,&score);
steps++;
put_Num(box);
ShowMenu(box,steps,score);
break;
default:
continue;
}
}
return 0;
}
2.draw.c //界面实现
#include<stdio.h>
#include"control.h"
void ShowMenu(int box[4][4],int steps,int score) //界面设计
{
int i=0,j=0;
printf("\033[2J");//清屏
printf("\033[2H");//光标复位
printf("\033[?25l");//隐藏光标
printf("\n\t**********************************\n");
printf("\t\t欢迎进入2048!\n");
printf("\t 请使用方向键游戏\n");
printf("\tsteps:%8d score:%8d\n",steps,score);
printf("\t**********************************\n\n");
printf("\t ┌────┬────┬────┬────┐\n");
for (i= 0;i<4;i++){
printf("\t │");
for(j=0;j<4;j++)
{
if(box[i][j]==0)
printf(" │");
else{
printNum(box[i][j]);
printf("│");
}
}
if (i<3)
{
printf("\n\t ├────┼────┼────┼────┤\n");
}
}
printf("\n\t └────┴────┴────┴────┘\n");
printf("\n\t---------------------------------\n");
printf("\n\t\tCtrl+z 退出 \n");
if(GameOver(box)==0){
printf("\t\t很遗憾,再接再厉!\n");
exit(0);
}
if(game_won(box)==1){
printf("\t\t恭喜你,你真棒!\n");
exit(0);
}
}
3.control.c //游戏控制部分
#include"control.h"
#include"draw.h"
char my_getch()
{
int c=0; int res=0;
struct termios org_opts, new_opts;
res=tcgetattr(STDIN_FILENO, &org_opts);
assert(res==0);
memcpy(&new_opts, &org_opts, sizeof(new_opts));
new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
c=getchar();//
res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);
assert(res==0);
return c;
}
void printNum(int num)
{
if(num==0)
SPACE();
else if(num==2 || num==64)
RED(num);
else if(num==4 || num==128)
DEEPGREEN(num);
else if(num==8 || num==256)
GREEN(num);
else if(num==16 || num==1024)
YELLOW(num);
else if(num==32 || num==2048)
PURPLE(num);
}
int inputCmd()
{
char c=my_getch();
if(c==27)
{
c=my_getch();
if(c==91)
{
c=my_getch();
if(c==65)
return 1;
if(c==66)
return 2;
if(c==67)
return 3;
if(c==68)
return 4;
}
}
}
int get2or4()
{
int x=rand()%10;
return x<1?4:2;
}
void put_Num(int box[4][4])
{
int x=0,y = 0;
while(1)
{
x = rand()%4;
y = rand()%4;
if (box[x][y]==0)
{
box[x][y]=get2or4();
break;
}
}
return;
}
int Move_up(int box[4][4],int *score)
{
int i,j,k=3;
while(k>0){
for(i=0;i<4;i++){
for(j=0;j<3;j++){
if(box[j][i]==0){
box[j][i]=box[j+1][i];
box[j+1][i]=0;
}
}
}
k--;
}
for(i=0;i<4;i++){
for(j=0;j<3;j++){
if(box[j][i]==box[j+1][i]){
box[j][i]*=2;
*score+=box[j][i];
box[j+1][i]=0;
}
}
}
for(i=0;i<4;i++){
for(j=0;j<3;j++){
if(box[j][i]==0){
box[j][i]=box[j+1][i];
box[j+1][i]=0;
}
}
}
}
int Move_down(int box[4][4],int *score)
{
int i,j,k=3;
while(k>0){
for(j=0;j<4;j++){
for(i=3;i>0;i--){
if(box[i][j]==0){
box[i][j]=box[i-1][j];
box[i-1][j]=0;
}
}
}
k--;
}
for(j=0;j<4;j++){
for(i=3;i>0;i--){
if(box[i][j]==box[i-1][j]){
box[i][j]*=2;
*score+=box[i][j];
box[i-1][j]=0;
}
}
}
for(j=0;j<4;j++){
for(i=3;i>0;i--){
if(box[i][j]==0){
box[i][j]=box[i-1][j];
box[i-1][j]=0;
}
}
}
}
int Move_right(int box[4][4],int *score)
{
int i,j,k=3;
while(k>0){
for(i=0;i<4;i++){
for(j=3;j>0;j--){
if(box[i][j]==0){
box[i][j]=box[i][j-1];
box[i][j-1]=0;
}
}
}
k--;
}
for(i=0;i<4;i++){
for(j=3;j>0;j--){
if(box[i][j]==box[i][j-1]){
box[i][j]*=2;
*score+=box[i][j];
box[i][j-1]=0;
}
}
}
for(i=0;i<4;i++){
for(j=3;j>0;j--){
if(box[i][j]==0){
box[i][j]=box[i][j-1];
box[i][j-1]=0;
}
}
}
}
int Move_left(int box[4][4],int *score)
{
int i,j,k=3;
while(k>0){
for(i=0;i<4;i++){
for(j=0;j<3;j++){
if(box[i][j]==0){
box[i][j]=box[i][j+1];
box[i][j+1]=0;
}
}
}
k--;
}
for(i=0;i<4;i++){
for(j=0;j<3;j++){
if(box[i][j]==box[i][j+1]){
box[i][j]*=2;
*score+=box[i][j];
box[i][j+1]=0;
}
}
}
for(i=0;i<4;i++){
for(j=0;j<3;j++){
if(box[i][j]==0){
box[i][j]=box[i][j+1];
box[i][j+1]=0;
}
}
}
}
int GameOver(int box[4][4])
{
int i=0;
int j=0;
int flag=0;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(box[i][j]==0)
flag++;
}
}
if (flag!=0)
return 1;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if(box[i][j]==box[i][j+1]||box[i][j]==box[i+1][j])
return 1;
}
}
return 0;
}
int game_won(int box[4][4])
{
int i,j;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(box[i][j]==2048)
return 1;
}
}
return 0;
}
二、库函数
1.draw.c
#ifndef _DRAW_H_
#define _DRAW_H_
extern void ShowMenu(int box[4][4],int steps,int score);
#endif
2.control.h
#ifndef _CONTROL_H_
#define _CONTROL_H_
#include<termios.h>
#include<stdio.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#include<math.h>
#include<time.h>
#include<stdlib.h>
//字体颜色及字体背景色
#define SPACE() printf("\033[47;31m \033[0m")
#define RED(n) printf("\033[47;31m%-4d\033[0m",(n))
#define GREEN(n) printf("\033[47;32m%-4d\033[0m",(n))
#define BLUE(n) printf("\033[47;34m%-4d\033[0m",(n))
#define YELLOW(n) printf("\033[47;33m%-4d\033[0m",(n))
#define PURPLE(n) printf("\033[47;35m%-4d\033[0m",(n))
#define DEEPGREEN(n) printf("\033[47;36m%-4d\033[0m",(n))
extern char my_getch();
extern void printNum(int num);
extern int inputCmd();
extern int get2or4();
extern void put_Num(int box[4][4]);
extern int Move_up(int box[4][4],int *score);
extern int Move_down(int box[4][4],int *score);
extern int Move_right(int box[4][4],int *score);
extern int Move_left(int box[4][4],int *score);
extern int GameOver(int box[4][4]);
extern int game_won(int box[4][4]);
#endif
三、游戏截图
初始画面:
游戏画面:
失败画面:
ps:以上代码并非全部由本人原创,部分参考他人