大部分同学学习C语言编程以后不知道能通过什么样的项目才可以锻炼自己的思维功力,2048相信大家都应该熟悉,不管是手机上还是网页版的相信大家都玩过,这个简单的控制台版本的游戏是我曾经在伟易达上班时一个嵌入式应用游戏部门的大佬设计的,适合于喜欢用C语言写一些简易的游戏的朋友,逻辑性很强。
一、2048游戏原理
在最初的游戏, 它始于一个空4 x 4游戏板。
1)在空位置的游戏板上,每一轮游戏产生一个“2”或“4”随机的数字。
2)接下来,玩家输入的上移,下移,左移或右移命令移动块。两个相邻块相同的号码,若是Q,可以组合成一个块数量2Q。
3)如果没有空间产生一个新的数字块,玩家则game over。
4)想赢得游戏,玩家需要产生一块2048数字块。
二、2048游戏文档
当然,这些游戏的逻辑不是大家闷着脑子就能空想出来的,它一定有很规范的说明文档,由专业的人来书写,最后软件工程师参考对应的文档编写自己的代码
原版本如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <conio.h> //num #define FALSE0 #define TRUE1 #define EMPTY_CELL0 #define GMAE_ROW4 #define GMAE_COL4 //GameState #define STATE_SELECT0 #define STATE_PREPARE1 #define STATE_PALYING2 #define STATE_EXIT 3 //GameMode #define MODE_NONE0 #define MODE_NORMAL1 #define MODE_DEBUG2 //Select Index #define INDEX_MAXNUM 3 #define INDEX_NORMAL 0 #define INDEX_DEBUG 1 #define INDEX_EXIT 2 //Command #define COM_LEFT'a' #define COM_RIGHT'd' #define COM_UP'w' #define COM_DOWN's' #define COM_QUIT'q' //direction #define DIR_HEAD 0xe0 #define KEY_UP0xe048 #define KEY_DOWN0xe050 #define KEY_LEFT0xe04b #define KEY_RIGHT0xe04d #define ESC0x1B #define ENTER0x0D //type typedef unsigned int Uint; typedef unsigned short Ushort; typedef unsigned char Uchar; //declaration static void GM_Init(void); static void GM_End(void); static Uint GM_SelectInit(void); static Uint GM_SelectHandle(void); static Uint GM_SelectEnd(void); static Uint GM_PrepareInit(void); static Uint GM_PrepareHandle(void); static Uint GM_PrepareEnd(void); static Uint GM_PlayingInit(void); static Uint GM_PlayingHandle(void); static Uint GM_PlayingEnd(void); static Uint GM_SelectHandleEnter(void); static Uint GM_SelectHandleEsc(void); static void GM_PrintSelectMode(void); static void GM_RandAddOneNum(void); static Uchar GM_FromFileAddNum(void); static Uchar GM_InputAddOneNum(void); static Uchar GM_NotMoreMove(void); static void GM_PrintBoard(void); static Uchar GM_CheckWin2048(void); static Uchar GM_PlayingPull(void); static Uchar GM_CombineRight(Uint *array, int num); static Uchar GM_CombineLeft(Uint *array, int num); static Uchar GM_MoveRight(Uint *array, int num); static Uchar GM_MoveLeft (Uint *array, int num); //struct typedef struct gameinfo {Uint Board[GMAE_ROW][GMAE_COL];Uchar GameState;Uchar GameMode;Uchar StateSelectIndex;Uint PlayingCommand; }GameInfo, *P_GameInfo; GameInfo GM; int main(void) {GM_Init();while(1){switch(GM.GameState){case STATE_SELECT:GM_SelectHandle();break;case STATE_PREPARE:GM_PrepareHandle();break;case STATE_PALYING:GM_PlayingHandle();break;case STATE_EXIT: goto GAME_EXIT;default:break;} } GAME_EXIT: GM_End(); return 0; } static void GM_Init(void) {memset(&GM, 0, sizeof(GameInfo));srand((int)time(NULL));GM_SelectInit(); } static void GM_End(void) {memset(&GM, 0, sizeof(GameInfo));fflush(stdin);printf("nCommand [q] can quitn");while('q' != getch()); } static Uint GM_SelectInit(void) {GM.GameState = STATE_SELECT; GM.StateSelectIndex = INDEX_NORMAL;GM_PrintSelectMode(); } static Uint GM_SelectHandle(void) {GM_PrintSelectMode(); fflush(stdin); Uchar ch1 = getch();if( ENTER == ch1){GM_SelectHandleEnter();}else if( ESC == ch1 ){GM_SelectEnd();GM.GameState = STATE_EXIT;}else if ( DIR_HEAD == ch1){Uchar ch2 = getch();Ushort Key = (ch1 << 8)&0xff00 | ch2;switch(Key){case KEY_UP:GM.StateSelectIndex = (GM.StateSelectIndex + INDEX_MAXNUM - 1) % INDEX_MAXNUM;break;case KEY_DOWN:GM.StateSelectIndex = (GM.StateSelectIndex + 1) % INDEX_MAXNUM;break;default:break;}} } static Uint GM_SelectEnd(void){} static Uint GM_PrepareInit(void) {Uchar OldState = GM.GameState; GM.GameState = STATE_PREPARE;//from STATE_SELECT --> STATE_PREPAREif(STATE_SELECT == OldState){if(MODE_NORMAL == GM.GameMode){GM_RandAddOneNum();GM_RandAddOneNum();}else{GM_FromFileAddNum();}}//from STATE_PALYING --> STATE_PREPAREelse{if(MODE_NORMAL == GM.GameMode){GM_RandAddOneNum();}else{GM_PrintBoard();while(FALSE == GM_InputAddOneNum());}}GM_PrintBoard(); } static Uint GM_PrepareHandle(void) {if(TRUE != GM_NotMoreMove()){ GM_PrepareEnd();GM_PlayingInit();}else{printf("Game Over!n");GM.GameState = STATE_EXIT;} } static Uint GM_PrepareEnd(void){} static Uint GM_PlayingInit(void) {GM.GameState = STATE_PALYING;printf( "PULL: [a]LEFT [d]RIGHT [w]UP [s]DOWN [q]QUITn" );printf( "Command: "); fflush(stdout); } static Uint GM_PlayingHandle(void) {fflush(stdin);GM.PlayingCommand = getch();switch(GM.PlayingCommand){case COM_LEFT:case COM_RIGHT:case COM_UP:case COM_DOWN:if( FALSE == GM_PlayingPull()){printf("[Error] invalid directionn");printf( "Command: ");}else{if( TRUE == GM_CheckWin2048() ){GM_PrintBoard();printf("you win !n");GM.GameState = STATE_EXIT;}else{GM_PlayingEnd();GM_PrepareInit();}}break;case COM_QUIT:printf("Bye !n");GM.GameState = STATE_EXIT;break;default:printf("[Error] Command is a, d, w, s, q n");printf( "Command: ");fflush(stdout);break;}//GM_PrintBoard(); } static Uint GM_PlayingEnd(void) {GM.PlayingCommand = 0; } static Uint GM_SelectHandleEnter(void) {switch(GM.StateSelectIndex){case INDEX_NORMAL:case INDEX_DEBUG: if(INDEX_NORMAL == GM.StateSelectIndex){GM.GameMode = MODE_NORMAL;} else{GM.GameMode = MODE_DEBUG;}GM_SelectEnd();GM_PrepareInit();break;case INDEX_EXIT:GM_SelectEnd();GM.GameState = STATE_EXIT;break;default:printf("errorn");break;} } static Uint GM_SelectHandleEsc(void){} static void GM_PrintSelectMode(void) {system("cls");printf("# - - - - - - - - #n");printf("# welcome to 2048 #n");printf("# - - - - - - - - #n");printf(" MODU SELECT n");printf("n ");printf(GM.StateSelectIndex==INDEX_NORMAL?"-->NORMAL":" NORMAL"); printf("n ");printf(GM.StateSelectIndex==INDEX_DEBUG? "-->DEBUG ":" DEBUG ");printf("n ");printf(GM.StateSelectIndex==INDEX_EXIT? "-->EXIT ":" EXIT "); } static void GM_RandAddOneNum(void) {int row, col;while (1){row = rand() % GMAE_ROW;col = rand() % GMAE_COL;if ( GM.Board[row][col] == EMPTY_CELL ){GM.Board[row][col] = ((rand() % 2) + 1) * 2;break;}} } static Uchar GM_FromFileAddNum(void) {FILE *infp;Uchar tmp[6],tmp1;Uchar ret = 0;Uchar i,j;if(infp = fopen("map.txt", "rb")){ for(i = 0; i < GMAE_ROW * GMAE_COL; i++){j = 0;memset(tmp, 0, sizeof(tmp));while(1){if(!fread(&tmp[j], 1, 1, infp))ret |= 0x02;if(tmp[j] == ' ' || tmp[j] == 'n' || tmp[j] == 0)break;j++;}*(&GM.Board[0][0]+i) = atoi((const char *)tmp);}}else{ret |= 0x01;}if(NULL != infp){fclose(infp);}if(ret != 0){printf("read map txt failn");}return ret; } static Uchar GM_InputAddOneNum(void) {int row, col, value;int ret = TRUE;printf("please input add one num!n");printf("Row,Col,Value :");fflush(stdout);fflush(stdin);scanf("%d,%d,%d", &row, &col, &value);if(row >= GMAE_ROW || row < 0){printf("[Error] Row is between 0 and %d !n", GMAE_ROW-1);ret = FALSE;}if(col >= GMAE_COL || col < 0){printf("[Error] Col is between 0 and %d !n", GMAE_COL-1);ret = FALSE;}if(ret == TRUE && GM.Board[row][col] != 0){printf("[Error] ( %d , %d ) is occupied!n", row, col);ret = FALSE;}if(value != 2 && value != 4){printf("[Error] Cell Value is either 2 or 4n");ret = FALSE;}if(ret == TRUE){GM.Board[row][col] = value;}return ret; } static Uchar GM_NotMoreMove(void) {int NotMoreMove = TRUE;int row, col;for ( row = 0; row < GMAE_ROW; row++){for ( col = 0; col < GMAE_COL; col++){if(GM.Board[row][col] == 0){NotMoreMove = FALSE;break;}if( col+1 < GMAE_COL && GM.Board[row][col] == GM.Board[row][col+1]){NotMoreMove = FALSE;break;}if( row+1 < GMAE_ROW && GM.Board[row][col] == GM.Board[row+1][col]){NotMoreMove = FALSE; break;}}if(FALSE == NotMoreMove)break;}return NotMoreMove; } static void GM_PrintBoard(void) {int row, col;system("cls");printf("# - - - - - - - - #n");printf("# welcome to 2048 #n");printf("# - - - - - - - - #n");for ( row = 0; row < GMAE_ROW; row++){for ( col = 0; col < GMAE_COL; col++){printf(" + - -", GM.Board[row][col]);}printf(" +n");for ( col = 0; col < GMAE_COL; col++){if(0 == GM.Board[row][col])printf(" | ");elseprintf(" |%4d", GM.Board[row][col]);}printf(" |n");}printf(" + + + + + + + + + + + + + n"); } static Uchar GM_CheckWin2048(void) {int row,col;for ( row = 0; row < GMAE_ROW; row++){for ( col = 0; col < GMAE_COL; col++){if( GM.Board[row][col] == 2048 ){return TRUE;}}}return FALSE; } static Uchar GM_PlayingPull(void) {//GMAE_ROW 行 4//GMAE_COL 列 4int index;int col, row;Uchar PullFlag = FALSE;Uint array[GMAE_ROW > GMAE_COL? GMAE_ROW:GMAE_COL];//******************COM_LEFT*******************if( COM_LEFT == GM.PlayingCommand)for ( row = 0; row < GMAE_ROW; row++){PullFlag |= GM_MoveLeft( (Uint *)GM.Board[row], GMAE_COL );PullFlag |= GM_CombineLeft( (Uint *)GM.Board[row], GMAE_COL );PullFlag |= GM_MoveLeft( (Uint *)GM.Board[row], GMAE_COL );}//******************COM_RIGHT******************else if( COM_RIGHT == GM.PlayingCommand)for ( row = 0; row < GMAE_ROW; row++){PullFlag |= GM_MoveRight( (Uint *)GM.Board[row], GMAE_COL );PullFlag |= GM_CombineRight( (Uint *)GM.Board[row], GMAE_COL );PullFlag |= GM_MoveRight( (Uint *)GM.Board[row], GMAE_COL );}//******************COM_UP*********************else if( COM_UP == GM.PlayingCommand)for ( col = 0; col < GMAE_COL; col++){for ( row = 0; row < GMAE_ROW; row++){array[row] = GM.Board[row][col];}//a col move LeftPullFlag |= GM_MoveLeft( (Uint *)array, GMAE_ROW );PullFlag |= GM_CombineLeft( (Uint *)array, GMAE_ROW );PullFlag |=GM_MoveLeft( (Uint *)array, GMAE_ROW );//write a colfor ( row = 0; row < GMAE_ROW; row++){GM.Board[row][col] = array[row];}}//******************COM_DOWN******************else if( COM_DOWN == GM.PlayingCommand)for ( col = 0; col < GMAE_COL; col++){//read a colfor ( row = 0; row < GMAE_ROW; row++){array[row] = GM.Board[row][col];}//a col move rightPullFlag |= GM_MoveRight( (Uint *)array, GMAE_ROW );PullFlag |= GM_CombineRight( (Uint *)array, GMAE_ROW );PullFlag |=GM_MoveRight( (Uint *)array, GMAE_ROW );//write a colfor ( row = 0; row < GMAE_ROW; row++){GM.Board[row][col] = array[row];}}returnPullFlag; } static Uchar GM_CombineLeft(Uint *array, int num) {int i;Uchar CombineFlag = FALSE;for ( i = 0; i < num-1; i++ ){if( array[i] != 0 && array[i] == array[i+1] ){array[i] *= 2;array[i+1] = 0;CombineFlag = TRUE;}}return CombineFlag; } static Uchar GM_CombineRight(Uint *array, int num) {int i;Uchar CombineFlag = FALSE;for ( i = num-1; i >= 1; i-- ){if( array[i] != 0 && array[i] == array[i-1] ){array[i] *= 2;array[i-1] = 0;CombineFlag = TRUE;}}return CombineFlag; } static Uchar GM_MoveRight(Uint *array, int num) {int i;int index = num - 1;Uchar moveflg = FALSE;for(i = num-1; i >= 0; i--){if(array[i] != 0){if(array[i] != array[index]){array[index] = array[i];moveflg = TRUE;}index--;}}while(index != -1){array[index] = 0;index--;}return moveflg; } static Uchar GM_MoveLeft(Uint *array, int num) {int i;int index = 0;Uchar moveflg = FALSE;for(i = 0; i < num; i++){if(array[i] != 0){if(array[i] != array[index]){array[index] = array[i];moveflg = TRUE;}index++;}}while(index != num){array[index] = 0;index++;}return moveflg; } 四、运行结果游戏主菜单界面,通过方向键选择,分别有NORMAL(正常进行游戏)、DEBUG(调试模式)、EXIT(退出游戏)按回车键进入对应的模式。用字母a、d、w、s、q分别代替左右上下以及退出键。如果最后游戏成功了,则会提示成功,如果失败则会退出程序。详细的游戏逻辑可通过代码以及文档进行了解。1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.74.75.76.77.78.79.80.81.82.83.84.85.86.87.88.89.90.91.92.93.94.95.96.97.98.99.100.101.102.103.104.105.106.107.108.109.110.111.112.113.114.115.116.117.118.119.120.121.122.123.124.125.126.127.128.129.130.131.132.133.134.135.136.137.138.139.140.141.142.143.144.145.146.147.148.149.150.151.152.153.154.155.156.157.158.159.160.161.162.163.164.165.166.167.168.169.170.171.172.173.174.175.176.177.178.179.180.181.182.183.184.185.186.187.188.189.190.191.192.193.194.195.196.197.198.199.200.201.202.203.204.205.206.207.208.209.210.211.212.213.214.215.216.217.218.219.220.221.222.223.224.225.226.227.228.229.230.231.232.233.234.235.236.237.238.239.240.241.242.243.244.245.246.247.248.249.250.251.252.253.254.255.256.257.258.259.260.261.262.263.264.265.266.267.268.269.270.271.272.273.274.275.276.277.278.279.280.281.282.283.284.285.286.287.288.289.290.291.292.293.294.295.296.297.298.299.300.301.302.303.304.305.306.307.308.309.310.311.312.313.314.315.316.317.318.319.320.321.322.323.324.325.326.327.328.329.330.331.332.333.334.335.336.337.338.339.340.341.342.343.344.345.346.347.348.349.350.351.352.353.354.355.356.357.358.359.360.361.362.363.364.365.366.367.368.369.370.371.372.373.374.375.376.377.378.379.380.381.382.383.384.385.386.387.388.389.390.391.392.393.394.395.396.397.398.399.400.401.402.403.404.405.406.407.408.409.410.411.412.413.414.415.416.417.418.419.420.421.422.423.424.425.426.427.428.429.430.431.432.433.434.435.436.437.438.439.440.441.442.443.444.445.446.447.448.449.450.451.452.453.454.455.456.457.458.459.460.461.462.463.464.465.466.467.468.469.470.471.472.473.474.475.476.477.478.479.480.481.482.483.484.485.486.487.488.489.490.491.492.493.494.495.496.497.498.499.500.501.502.503.504.505.506.507.508.509.510.511.512.513.514.515.516.517.518.519.520.521.522.523.524.525.526.527.528.529.530.531.532.533.534.535.536.537.538.539.540.541.542.543.544.545.546.547.548.549.550.551.552.553.554.555.556.557.558.559.560.561.562.563.564.565.566.567.568.569.570.571.572.573.574.575.576.577.578.579.580.581.582.583.584.585.586.587.588.589.590.591.592.593.594.595.596.597.598.599.600.601.602.603.604.605.606.607.608.609.610.611.612.613.614.615.616.617.618.619.620.621.622.623.624.625.626.627.628.629.630.631.632.633.634.635.636.637.638.639.640.641.642.643.644.645.646.647.648.649.650.651.652.653.654.655.656.657.658.659.660.661.662.663.664.665.666.667.668.669.670.671.672.673.674.675.676.677.678.679.680.681.682.683.684.685.686.687.688.689.690.691.692.693.694.695.696.697.698.699.700.701.
本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
赞 收藏 评论 举报
相关文章