最近简直超级无聊……
code blocks win7 64编译运行无问题,应该其他编译器也不会有问题。
w:上
s:下
a:左
d:右
CS标准方向控制,AK47和M4这种高级货是没有滴……
废话不多说,直接上代码。
#include "stdio.h"
#include "stdlib.h"
#include "windows.h"
#include "time.h"
// ----------------------------------------------------------------------------
// definition
// ----------------------------------------------------------------------------
// basic char node
#define _FOOD "#"
#define _SNAKE_NODE "O"
#define _SNAKE_END "+"
#define _SNAKE_HEAD "@"
#define _MAP_NODE " "
#define _MAP_EDGE "O"
// area pos and range
#define _AREA_X_OFFSET 10
#define _AREA_Y_OFFSET 5
#define _AREA_X_LINE_MAX 30 // max line num in x direction
#define _AREA_Y_LINE_MAX 20 // max line num in y direction
#define _SNAKE_LENGTH_MAX 30
// key val defintion
#define _KEY_UP 'w'
#define _KEY_DOWN 's'
#define _KEY_LEFT 'a'
#define _KEY_RIGHT 'd'
// default snake speed
#define _DEFAULT_SNAKE_SPEED 300 // 1 step per second
// ----------------------------------------------------------------------------
// type
// ----------------------------------------------------------------------------
// basic type
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned char * PBYTE;
typedef unsigned short * PWORD;
typedef unsigned long * PDWORD;
// element type
typedef enum
{
_ET_MAP_NODE,
_ET_MAP_EDGE,
_ET_FOOD,
_ET_SNAKE_HEAD,
_ET_SNAKE_NODE,
_ET_SNAKE_END
}E_ET;
// snake node type
typedef enum
{
_ESNT_HEAD = _ET_SNAKE_HEAD,
_ESNT_NODE = _ET_SNAKE_NODE,
_ESNT_END = _ET_SNAKE_END
}E_SNT;
// node pos
typedef struct
{
BYTE by_x;
BYTE by_y;
}T_Pos, *PT_Pos;
// snake node
typedef struct
{
E_SNT e_type;
T_Pos t_pos;
//BOOL b_valid;
}T_Snake_Node;
// direction
typedef enum
{
_UP,
_DOWN,
_LEFT,
_RIGHT
}E_DRCT;
// snake
typedef struct
{
DWORD dw_speed;
E_DRCT e_direction;
BYTE by_node_num;
T_Snake_Node at_node[_SNAKE_LENGTH_MAX];
}T_Snake;
// food
typedef struct
{
BOOL b_eaten;
T_Pos t_pos;
}T_Food;
// key type
typedef enum
{
_E_KT_NONE,
_E_KT_UP,
_E_KT_DOWN,
_E_KT_LEFT,
_E_KT_RIGHT,
_E_KT_SIZE
}E_KEY_TYPE;
// ----------------------------------------------------------------------------
// local para
// ----------------------------------------------------------------------------
// range buffer
E_ET l_ae_area[_AREA_Y_LINE_MAX][_AREA_X_LINE_MAX];
// snake
T_Snake l_t_snake;
BOOL l_b_key_lock = FALSE;
T_Food l_t_food = {.b_eaten = TRUE};
// ----------------------------------------------------------------------------
// function
// ----------------------------------------------------------------------------
// ------------------------------------
// pos jump
// ------------------------------------
void Pos_Jump(int x, int y)
{
COORD pos = {_AREA_X_OFFSET + x, _AREA_Y_OFFSET + y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, pos);
}
// ------------------------------------
// draw rect element
// ------------------------------------
void Rect_Elem_Draw(E_ET e_et)
{
switch(e_et)
{
case _ET_FOOD:
printf(_FOOD);
break;
case _ET_SNAKE_NODE:
printf(_SNAKE_NODE);
break;
case _ET_SNAKE_HEAD:
printf(_SNAKE_HEAD);
break;
case _ET_SNAKE_END:
printf(_SNAKE_END);
break;
case _ET_MAP_EDGE:
printf(_MAP_EDGE);
break;
case _ET_MAP_NODE:
default:
printf(_MAP_NODE);
break;
}
}
// ------------------------------------
// draw map
// ------------------------------------
void Area_Refresh( void )
{
BYTE i, j, k;
// make Y offset
for(i=0 ; i<_AREA_Y_OFFSET ; i++)
{
printf("\r\n");
}
// refresh rect line by line
for(i=0 ; i<_AREA_Y_LINE_MAX ; i++)
{
// make X offset
for(k=0 ; k<_AREA_X_OFFSET ; k++)
{
printf(" ");
}
// draw line
for(j=0 ; j<_AREA_X_LINE_MAX ; j++)
{
Rect_Elem_Draw(l_ae_area[i][j]);
}
printf("\r\n");
}
}
// ------------------------------------
// snake init
// ------------------------------------
void Snake_Init()
{
l_t_snake.dw_speed = _DEFAULT_SNAKE_SPEED;
l_t_snake.e_direction = _RIGHT;
l_t_snake.by_node_num = 3;
//l_t_snake.at_node[0].b_valid = TRUE;
l_t_snake.at_node[0].e_type = _ESNT_END;
l_t_snake.at_node[0].t_pos.by_x = 2;
l_t_snake.at_node[0].t_pos.by_y = 1;
//l_t_snake.at_node[0].b_valid = TRUE;
l_t_snake.at_node[1].e_type = _ESNT_NODE;
l_t_snake.at_node[1].t_pos.by_x = 2;
l_t_snake.at_node[1].t_pos.by_y = 2;
//l_t_snake.at_node[0].b_valid = TRUE;
l_t_snake.at_node[2].e_type = _ESNT_HEAD;
l_t_snake.at_node[2].t_pos.by_x = 2;
l_t_snake.at_node[2].t_pos.by_y = 3;
}
// ------------------------------------
// area init
// notice: should be called after snake
// init
// ------------------------------------
void Area_Init()
{
BYTE by_i, by_j;
// set area default value
for(by_i=0 ; by_i<_AREA_X_LINE_MAX ; by_i++)
{
for(by_j=0 ; by_j<_AREA_Y_LINE_MAX ; by_j++)
{
l_ae_area[by_i][by_j] = _ET_MAP_NODE;
}
}
// set area edge value
for(by_i=0 ; by_i<_AREA_X_LINE_MAX ; by_i++)
{
l_ae_area[0][by_i] = _ET_MAP_EDGE;
l_ae_area[_AREA_Y_LINE_MAX - 1][by_i] = _ET_MAP_EDGE;
}
for(by_j=0 ; by_j<_AREA_Y_LINE_MAX ; by_j++)
{
l_ae_area[by_j][0] = _ET_MAP_EDGE;
l_ae_area[by_j][_AREA_X_LINE_MAX - 1] = _ET_MAP_EDGE;
}
}
void Show_Game_Over()
{
Pos_Jump(_AREA_X_LINE_MAX/4, _AREA_X_LINE_MAX+1);
printf("Game Over!");
Pos_Jump(_AREA_X_LINE_MAX/4, _AREA_X_LINE_MAX+2);
printf("Press Anykey to Exit...");
}
BOOL Snake_Is_Dead()
{
T_Pos t_head_pos = l_t_snake.at_node[l_t_snake.by_node_num-1].t_pos;
BYTE i;
// touch area ----------------
if( t_head_pos.by_x == 0
|| t_head_pos.by_x >= _AREA_X_LINE_MAX-1
|| t_head_pos.by_y == 0
|| t_head_pos.by_y >= _AREA_Y_LINE_MAX-1)
{
Show_Game_Over();
return TRUE;
}
// touch body --------
for(i=0 ; i<l_t_snake.by_node_num-1 ; i++)
{
if( t_head_pos.by_x == l_t_snake.at_node[i].t_pos.by_x
&&t_head_pos.by_y == l_t_snake.at_node[i].t_pos.by_y)
{
return TRUE;
}
}
return FALSE;
}
// ------------------------------------
// on snake moving
// ------------------------------------
On_Snake_Moving()
{
static DWORD dw_time_cur = 0;
static DWORD dw_time_last = 0;
BYTE by_i = 0;
T_Pos t_end_pos_before_moving;
BYTE by_neck_index, by_head_index;
// check speed
dw_time_cur = GetTickCount();
if(dw_time_cur < dw_time_last + l_t_snake.dw_speed)
{
return;
}
l_b_key_lock = FALSE;
dw_time_last = dw_time_cur;
// move
by_head_index = l_t_snake.by_node_num - 1;
by_neck_index = l_t_snake.by_node_num - 2;
if( l_t_snake.at_node[by_neck_index].t_pos.by_x != l_t_snake.at_node[by_head_index].t_pos.by_x
||l_t_snake.at_node[by_neck_index].t_pos.by_y != l_t_snake.at_node[by_head_index].t_pos.by_y) // last step not eat food
{
t_end_pos_before_moving = l_t_snake.at_node[0].t_pos;
for(by_i=1 ; by_i<l_t_snake.by_node_num ; by_i++)
{
l_t_snake.at_node[by_i - 1].t_pos = l_t_snake.at_node[by_i].t_pos;
}
// refresh snake
Pos_Jump(t_end_pos_before_moving.by_x,
t_end_pos_before_moving.by_y);
Rect_Elem_Draw(_ET_MAP_NODE);
}
switch(l_t_snake.e_direction)
{
case _UP:
l_t_snake.at_node[by_head_index].t_pos.by_y--;
break;
case _DOWN:
l_t_snake.at_node[by_head_index].t_pos.by_y++;
break;
case _LEFT:
l_t_snake.at_node[by_head_index].t_pos.by_x--;
break;
case _RIGHT:
l_t_snake.at_node[by_head_index].t_pos.by_x++;
break;
}
for(by_i=0 ; by_i<l_t_snake.by_node_num ; by_i++)
{
Pos_Jump(l_t_snake.at_node[by_i].t_pos.by_x,
l_t_snake.at_node[by_i].t_pos.by_y);
Rect_Elem_Draw(l_t_snake.at_node[by_i].e_type);
}
// eat food
if( l_t_snake.at_node[by_head_index].t_pos.by_x == l_t_food.t_pos.by_x
&&l_t_snake.at_node[by_head_index].t_pos.by_y == l_t_food.t_pos.by_y)
{
l_t_snake.at_node[by_head_index+1] = l_t_snake.at_node[by_head_index];
l_t_snake.at_node[by_head_index].e_type = _ESNT_NODE;
l_t_snake.by_node_num++;
l_t_food.b_eaten = TRUE;
}
}
// ------------------------------------
// key detect
// ------------------------------------
E_KEY_TYPE Key_Detect()
{
BYTE by_key_value;
E_KEY_TYPE e_kt;
if(0 == kbhit())
{
return _E_KT_NONE;
}
by_key_value = (BYTE)(getch());
if(l_b_key_lock)
{
return _E_KT_NONE;
}
switch(by_key_value)
{
case _KEY_UP:
e_kt = _E_KT_UP;
break;
case _KEY_DOWN:
e_kt = _E_KT_DOWN;
break;
case _KEY_LEFT:
e_kt = _E_KT_LEFT;
break;
case _KEY_RIGHT:
e_kt = _E_KT_RIGHT;
break;
default:
e_kt = _E_KT_NONE;
break;
}
return e_kt;
}
// ------------------------------------
// changing snake direction
// ------------------------------------
void On_Changing_Snake_Drctn(E_KEY_TYPE e_kt)
{
switch(e_kt)
{
case _E_KT_UP:
if( (_LEFT == l_t_snake.e_direction)
||(_RIGHT == l_t_snake.e_direction))
{
l_t_snake.e_direction = _UP;
}
break;
case _E_KT_DOWN:
if( (_LEFT == l_t_snake.e_direction)
||(_RIGHT == l_t_snake.e_direction))
{
l_t_snake.e_direction = _DOWN;
}
break;
case _E_KT_LEFT:
if( (_UP == l_t_snake.e_direction)
||(_DOWN == l_t_snake.e_direction))
{
l_t_snake.e_direction = _LEFT;
}
break;
case _E_KT_RIGHT:
if( (_UP == l_t_snake.e_direction)
||(_DOWN == l_t_snake.e_direction))
{
l_t_snake.e_direction = _RIGHT;
}
break;
}
}
// ------------------------------------
// On key down
// ------------------------------------
void On_Key_Down()
{
E_KEY_TYPE e_kt;
e_kt = Key_Detect();
if(_E_KT_NONE != e_kt)
{
// lock keyboard
l_b_key_lock = TRUE;
// changing snake direction
On_Changing_Snake_Drctn(e_kt);
// system operation
}
}
void Refresh_Food()
{
T_Pos t_food_pos;
if(l_t_food.b_eaten)
{
srand(time(0));
t_food_pos.by_x = rand()%(_AREA_X_LINE_MAX-1-1)+1;
t_food_pos.by_y = rand()%(_AREA_Y_LINE_MAX-1-1)+1;
l_t_food.t_pos = t_food_pos;
Pos_Jump(l_t_food.t_pos.by_x, l_t_food.t_pos.by_y);
Rect_Elem_Draw(_ET_FOOD);
l_t_food.b_eaten = FALSE;
}
}
// ------------------------------------
// main
// ------------------------------------
int main()
{
int i_tmp = 0;
Area_Init();
Area_Refresh();
Snake_Init();
while(1)
{
On_Key_Down();
On_Snake_Moving();
Refresh_Food();
if(TRUE == Snake_Is_Dead())
{
break;
}
}
getch();
return 0;
}
上张截图