linux下2048小游戏

来源:互联网 发布:数据库数据库系统 编辑:程序博客网 时间:2024/06/03 21:54
在学习 标C之后,试着做的一个小游戏
   
    设计思路:
          1、  打印界面
               (界面初始化,采用二维数组)
           2、操作控制
                (上下左右操作时数组计算)
           3、判断以及重打印
                 (判断是否操作有效以及游戏结束)
           4、文件保存

    缺点:
            1、 文件代码不够精简,很多地方都可以优化
           
             2、初次用多文件处理,文件管理有点混乱

            3、注释不够

界面如下:

      


-----------------------------------------------------------------------------------------------
代码如下:

头文件
headfile.h
#ifndef __HEADFILE_H__#define __HEADFILE_H__#include <stdio.h>#include <stdlib.h>#include <time.h>#define SIZE 4int arr[SIZE][SIZE];int score;int best;int if_game_over;extern same[SIZE][SIZE];// linux_getch.cchar my_getch();// show.cvoid refresh_show();void start_game();// file.cvoid read_file();void save_file(int, int);// main.cvoid game_operate();// opertate.cvoid assign(void);int same_judge(void);int game_judge(void);void add_number(void);void move_up(void);void move_left(void);void move_down(void);void move_right(void);void restart(void);#endif//__HEADFILE_H__


游戏入口
2048.c
#include "headfile.h"int main(void){srand((unsigned)time(0));read_file();start_game();return 0;}

主操作面板
main.c
#include "headfile.h"int same[SIZE][SIZE] = {};void start_game(){int judge = 0;char quit =0;char move =0;while(1){refresh_show();assign();          //记录数组,对比可知操作后数字是否有移动move = my_getch();switch(move){case 'w':case 'W':move_up();break;case 'a':case 'A':move_left();break;case 's':case 'S':move_down();break;case 'd':case 'D':move_right();break;case 'q':case 'Q':printf("Are you sure? Y/N\n");quit = getchar();if (quit == 'y' || quit == 'Y'){save_file(score, best);return;}elsecontinue;case 'r':case 'R':restart();score = 0;continue;default:continue;}save_file(score, best);switch (game_judge()){case 2:printf("YOU WIN !!!\n");printf("Do you want to play again (Y/N)\n");restart();score = 0;save_file(score, best);quit = getchar();if (quit == 'y' || quit == 'Y'){continue;}else{return;}case 1:break;default:printf("\e[31mYOU FAIL !!!\e[m\n");printf("Do you want to restart (Y/N)\n");restart();score = 0;save_file(score, best);quit = getchar();if (quit == 'y' || quit == 'Y'){continue;}else{return;}}if (same_judge()){continue;}add_number();}}

界面显示
show.c
#include "headfile.h"void line(void){int i = 0;for (i =0; i <SIZE; i++){printf("-----");}}void set_number(int row, int vol){switch(arr[row][vol]){case 0:printf("|\e[1;47m    \e[m");break;case 2:printf("|\e[0;43;37m 2  \e[m");break;case 4:printf("|\e[0;44;37m 4  \e[m");break;case 8:printf("|\e[0;45;37m 8  \e[m");break;case 16:printf("|\e[0;45;37m 16 \e[m");break;case 32:printf("|\e[0;47;34m 32 \e[m");break;case 64:printf("|\e[1;47;34m 64 \e[m");break;case 128:printf("|\e[1;47;35m 128\e[m");break;case 256:printf("|\e[1;47;31m 256\e[m");break;case 512:printf("|\e[1;47;31m 512\e[m");break;case 1024:printf("|\e[1;47m1024\e[m");break;case 2048:printf("|\e[1;47m2048\e[m");break;default:break;}}void refresh_show(void){int i =0, j =0;system("clear");printf("\n\n");printf("    GAME: 2048\n");printf(" SCORE      BEST    \n");printf("  %-4d     \e[31m %d\e[m  \n", score, best);line();printf("\n");for(i =0; i <SIZE; i++){for(j =0; j <SIZE; j++){set_number(i, j);}printf("|");printf("\n");line();printf("\n");}printf("Q(exit)   R(restart)\n");}

移动与判断
operate.c
#include "headfile.h"void move_up(void){int i =0, j =0;//循环变量int point = 0;//定位作用for (i =0; i <SIZE; i++){point = 0;for(j =1; j <SIZE; j++){//如果没这个if,则要在两者相等处做个同为O的分支if (arr[j][i] > 0){// 定位点要不为0,不为0则有可能与对比数相等或不相等`if (arr[point][i] == arr[j][i]){arr[point][i] *= 2;score += arr[point][i];arr[j][i] = 0;point++;}else if(arr[point][i] == 0){arr[point][i] = arr[j][i];arr[j][i] = 0;}else{arr[++point][i] = arr[j][i];if (point != j){arr[j][i] = 0;}}}}}}void move_down(void){int i =0, j =0;//循环变量int point = 0;//定位作用for (i =0; i <SIZE; i++){point = SIZE-1;for(j =SIZE-2; j >=0; j--){//如果没这个if,则要在两者相等处做个同为O的分支if (arr[j][i] > 0){// 定位点要不为0,不为0则有可能与对比数相等或不相等`if (arr[point][i] == arr[j][i]){arr[point][i] *= 2;score += arr[point][i];arr[j][i] = 0;point--;}else if(arr[point][i] == 0){arr[point][i] = arr[j][i];arr[j][i] = 0;}else{arr[--point][i] = arr[j][i];if (point != j){arr[j][i] = 0;}}}}}}void move_left(void){int i =0, j =0;//循环变量int point = 0;//定位作用for (i =0; i <SIZE; i++){point = 0;for(j =1; j <SIZE; j++){//如果没这个if,则要在两者相等处做个同为O的分支if (arr[i][j] > 0){// 定位点要不为0,不为0则有可能与对比数相等或不相等`if (arr[i][point] == arr[i][j]){arr[i][point] *= 2;score += arr[i][point];arr[i][j] = 0;point++;}else if(arr[i][point] == 0){arr[i][point] = arr[i][j];arr[i][j] = 0;}else{arr[i][++point] = arr[i][j];if (point != j){arr[i][j] = 0;}}}}}}void move_right(void){int i =0, j =0;//循环变量int point = 0;//定位作用for (i =0; i <SIZE; i++){point = SIZE-1;for(j =SIZE-2; j >=0; j--){//如果没这个if,则要在两者相等处做个同为O的分支if (arr[i][j] > 0){// 定位点要不为0,不为0则有可能与对比数相等或不相等`if (arr[i][point] == arr[i][j]){arr[i][point] *= 2;score += arr[i][point];arr[i][j] = 0;point--;}else if(arr[i][point] == 0){arr[i][point] = arr[i][j];arr[i][j] = 0;}else{arr[i][--point] = arr[i][j];if (point != j){arr[i][j] = 0;}}}}}}int game_judge(void){int i = 0, j = 0;// 判断是否胜利for (i =0; i <SIZE; i++)for(j =0; j <SIZE; j++){if (arr[i][j] == 2048){return 2;}}//判断是否有空格,有则继续for (i =0; i <SIZE; i++)for(j =0; j <SIZE; j++){if(arr[i][j] == 0){return 1;}}//判断是否相邻有重复,有则游戏继续for (i =0; i <SIZE; i++)for(j =0; j <SIZE-1; j++){if ((arr[i][j] == arr[i][j+1]) || (arr[j][i] == arr[j+1][i])){return 1;}}//没地可走,则game overreturn 0;}void add_number(void){int num = rand() % 3 ? 2 : 4;// 生成2的概率是4的2倍int un[SIZE * SIZE] = {};// 记录没有被占据的位置int i = 0, j =0, cnt = 0;int loc = 0;for (i =0; i <SIZE; i++)for (j =0; j <SIZE; j++){//if (arr[i][j] == 0 && loc-- == 0 )if (arr[i][j] == 0){un[cnt] = i * 10 + j;cnt++;}}loc = rand() % cnt;//随机挑选未被占据的位置// 复原数组存放数字对应的序列i = un[loc] / 10;j = un[loc] % 10;arr[i][j] = num;}void restart(void){int i = 0, j = 0;int row = 0, vol = 0;for (i =0; i <SIZE; i++)for(j =0; j <SIZE; j++){arr[i][j] = 0;}row = rand() % SIZE;vol = rand() % SIZE;arr[row][vol] = 2;add_number();}void assign(void){int i =0, j =0;for (i =0; i <SIZE; i++)for (j =0; j <SIZE; j++){same[i][j] = arr[i][j];}}int same_judge(){int i = 0, j =0;for (i =0; i <SIZE; i++)for (j =0; j <SIZE; j++){if (same[i][j] != arr[i][j]){return 0;}}return 1;}

实现键盘输入不回显,不用按回车(网上摘录)
my_getch.h
#include <stdio.h>#include <stdlib.h>#include <termios.h>#include <unistd.h>char my_getch(){   struct termios tm, tm_old;   int fd = STDIN_FILENO;char c =0;   if (tcgetattr(fd, &tm) < 0)   {      return -1;   }   tm_old = tm;   cfmakeraw(&tm);   if (tcsetattr(fd, TCSANOW, &tm) < 0)   {      return -1;   }   c = fgetc(stdin);   if (tcsetattr(fd,TCSANOW,&tm_old) < 0)   {      return -1;   }   return c;}

文件处理
file.c
#include "headfile.h"void read_file(void){FILE *fp;// 打开记录上次游戏的位置if (!(fp = fopen("location.txt", "rb"))){printf("Fail to read the file\n");return;}if(!(fread(arr, sizeof(arr), 1, fp))){printf("fail to open the record!");}fclose(fp);// 打开记录分数文档if (!(fp = fopen("score.txt", "rb"))){printf("Fail to read the file");return;}if(!(fread(&score, sizeof(int), 1, fp))){printf("Not record the score last time!");}fclose(fp);// 打开记录最高分文档if (!(fp = fopen("best.txt", "rb"))){printf("Fail to read the file");return;}if(!(fread(&best, sizeof(int), 1, fp))){printf("Need you to do the best!");}fclose(fp);}void save_file(int score, int best){FILE *fp;// 记录上次游戏的位置if (!(fp = fopen("location.txt", "wb"))){printf("Fail to read the file");return;}if(!(fwrite(arr, sizeof(arr), 1, fp))){printf("fail to save the record!");}fclose(fp);// 记录分数if (!(fp = fopen("score.txt", "wb"))){printf("Fail to read the file");return;}if(!(fwrite(&score, sizeof(int), 1, fp))){printf("fail to save the record!");}fclose(fp);// 记录最高分if (score > best){best = score;}if (!(fp = fopen("best.txt", "wb"))){printf("Fail to read the file");return;}if(!(fwrite(&best, sizeof(int), 1, fp))){printf("fail to save the record!");}}




























0 0