当前位置: 首页 > 工具软件 > 2048.c > 使用案例 >

基于C的2048游戏

公胤运
2023-12-01

这游戏适合于喜欢用C语言写一些简易的游戏的朋友。

在最初的游戏, 它始于一个空4 x 4游戏板。

1)在空位置的游戏板上,每一轮游戏产生一个“2”或“4”随机的数字

2)接下来,玩家输入的上移,下移,左移或右移命令移动块。两个相邻块相同的号码,若是Q,可以组合成一个块数量2Q。

3)如果没有空间产生一个新的数字块,玩家则game over

4)想赢得游戏,玩家需要产生一块2048数字块。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include <conio.h>


//num
#define FALSE 0
#define TRUE 1

#define EMPTY_CELL     0

#define GMAE_ROW 4
#define GMAE_COL 4

//GameState
#define STATE_SELECT   0
#define STATE_PREPARE   1
#define STATE_PALYING   2
#define STATE_EXIT      3

//GameMode
#define MODE_NONE       0
#define MODE_NORMAL     1
#define MODE_DEBUG     2

//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_UP 0xe048
#define KEY_DOWN 0xe050
#define KEY_LEFT 0xe04b
#define KEY_RIGHT 0xe04d

#define ESC 0x1B
#define ENTER 0x0D

//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_PlayingCombine(void);

//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));
GM_SelectInit();
}


static void GM_End(void)
{
memset(&GM, 0, sizeof(GameInfo));
fflush(stdin);
system("pause");
}


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_PREPARE
if(STATE_SELECT == OldState)
{
if(MODE_NORMAL == GM.GameMode)
{
GM_RandAddOneNum();
GM_RandAddOneNum();
}
else
{
GM_FromFileAddNum();
}
}
//from STATE_PALYING -->  STATE_PREPARE
else
{
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]QUIT\n" );
printf( "Command : ");
    fflush(stdout);
}

static Uint GM_PlayingHandle(void)
{
fflush(stdin);
scanf("%c", &GM.PlayingCommand);

Uchar flag1,flag2;
switch(GM.PlayingCommand)
{
case COM_LEFT:
case COM_RIGHT:
case COM_UP:
case COM_DOWN:
flag1 = GM_PlayingPull();
flag2 = GM_PlayingCombine();
//printf("flag1:%d,flag2:%d\n",flag1, flag2);
if( FALSE == flag1 && FALSE == flag2)
{
printf("[Error] invalid direction\n");
printf( "Command : ");
}
else
{
GM_PlayingPull();
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){}

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("error\n");
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;

srand((int)time(NULL));
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 fail\n");
}
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 4\n");
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(" |    ");
else
printf(" |%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  列 4

int index;
int col, row;
Uchar PullFlag = FALSE;

if( COM_LEFT == GM.PlayingCommand)
for ( row = 0; row < GMAE_ROW; row++)
{
index = 0;
for ( col = 0; col < GMAE_COL; col++)
{
if(GM.Board[row][col] != 0)
{
if(GM.Board[row][index] != GM.Board[row][col])
{
PullFlag = TRUE;
GM.Board[row][index] = GM.Board[row][col];
}
index++;
}
}
while(index != GMAE_COL)
{
GM.Board[row][index] = 0;
index++;
}
}

else if( COM_RIGHT == GM.PlayingCommand)
for ( row = 0; row < GMAE_ROW; row++)
{
index = GMAE_COL - 1;
for ( col = GMAE_COL-1; col >= 0; col--)
{
if(GM.Board[row][col] != 0)
{
if(GM.Board[row][index] != GM.Board[row][col])
{
PullFlag = TRUE;
GM.Board[row][index] = GM.Board[row][col];
}
index--;
}
}
while(index != -1)
{
GM.Board[row][index] = 0;
index--;
}
}

else if( COM_UP == GM.PlayingCommand)
for ( col = 0; col < GMAE_COL; col++)
{
index = 0;
for ( row = 0; row < GMAE_ROW; row++)
{
if(GM.Board[row][col] != 0)
{
if( GM.Board[index][col] != GM.Board[row][col] )
{
PullFlag = TRUE;
GM.Board[index][col] = GM.Board[row][col];
}
index++;
}
}
while(index != GMAE_ROW)
{
GM.Board[index][col] = 0;
index++;
}
}

else if( COM_DOWN == GM.PlayingCommand)
for ( col = 0; col < GMAE_COL; col++)
{
index = GMAE_ROW - 1;
for ( row = GMAE_ROW - 1; row >= 0; row--)
{
if(GM.Board[row][col] != 0)
{
if( GM.Board[index][col] != GM.Board[row][col] )
{
PullFlag = TRUE;
GM.Board[index][col] = GM.Board[row][col];
}
index--;
}
}
while(index != -1)
{
GM.Board[index][col] = 0;
index--;
}
}

return PullFlag;
}

static Uchar GM_PlayingCombine(void)
{
//GMAE_ROW  行 4
//GMAE_COL  列 4
int col, row;
Uchar CombineFlag = FALSE;

if( COM_LEFT == GM.PlayingCommand )
for ( row = 0; row < GMAE_ROW; row++ )
{
for ( col = 0; col < GMAE_COL-1; col++ )
{
if( GM.Board[row][col] != 0 && GM.Board[row][col] == GM.Board[row][col+1] )
{
GM.Board[row][col]  *= 2;
GM.Board[row][col+1] = 0;
CombineFlag = TRUE;
}
}
}

else if( COM_RIGHT == GM.PlayingCommand )
for ( row = 0; row < GMAE_ROW; row++ )
{
for ( col = GMAE_COL-1; col > 0; col-- )
{
if( GM.Board[row][col] != 0 && GM.Board[row][col] == GM.Board[row][col-1] )
{
GM.Board[row][col]  *= 2;
GM.Board[row][col-1] = 0;
CombineFlag = TRUE;
}
}
}

else if( COM_UP == GM.PlayingCommand )
for ( col = 0; col < GMAE_COL; col++)
{
for ( row = 0; row < GMAE_ROW-1; row++ )
{
if(GM.Board[row][col] != 0 && GM.Board[row][col] == GM.Board[row+1][col])
{
GM.Board[row][col]  *= 2;
GM.Board[row+1][col] = 0;
CombineFlag = TRUE;
}
}
}

else if( COM_DOWN == GM.PlayingCommand )
for ( col = 0; col < GMAE_COL; col++)
{
for ( row = GMAE_ROW - 1; row > 0; row-- )
{
if(GM.Board[row][col] != 0 && GM.Board[row][col] == GM.Board[row-1][col])
{
GM.Board[row][col]  *= 2;
GM.Board[row-1][col] = 0;
CombineFlag = TRUE;
}
}
}

return CombineFlag;
}



 类似资料: