69,371
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#include <stdlib.h>
// Direction
enum DIR{
DIR_X = 0, // +X
DIR_Y, // +Y
DIR_NX, // -X
DIR_NY, // -Y
DIR_NUM
};
/*
Coordinates
O----------> X
|
|
|
|
Y v
*/
#define INIT_DIR DIR_X
// Commands
#define CMD_NODRAW 1
#define CMD_DRAW 2
#define CMD_TURN_RIGHT 3
#define CMD_TURN_LEFT 4
#define CMD_MOVE 5
#define CMD_PRINT 6
#define CMD_END 9
#define CMD_MOVE_STEPS(steps) (5 | ((int)steps << 8))
#define GET_CMD(data) (data & 0xFF)
#define GET_STEPS(data) (data >> 8)
// Grid
#define MAX_X 20
#define MAX_Y 10
// tortoise status
struct status
{
int x;
int y;
int dir;
int isDrawing;
};
static void init(struct status* status);
static void handler_move(struct status* status, int cmd);
static void handler_print(const struct status* status);
static void run(int* cmds);
// Global data
int g_grid[MAX_X][MAX_Y];
/*********************************************
* Main logic *
*********************************************/
static void init(struct status* status)
{
status->x = 0;
status->y = 0;
status->dir = INIT_DIR;
status->isDrawing = 0;
memset(g_grid, 0, sizeof(g_grid));
}
static void handler_move(struct status* status, int cmd)
{
int steps = GET_STEPS(cmd);
int xNew = status->x;
int yNew = status->y;
switch (status->dir){
case DIR_X: xNew += steps; break;
case DIR_NX: xNew -= steps; break;
case DIR_Y: yNew += steps; break;
case DIR_NY: yNew -= steps; break;
}
if (xNew < 0 || xNew >= MAX_X ||
yNew < 0 || yNew >= MAX_Y){
printf("invalid cmd:%d for status:x=%d,y=%d,dir=%d\n",
cmd, status->x, status->y, status->dir);
exit(-1);
}
// Track movement
if (status->isDrawing){
int i = 0;
switch (status->dir){
case DIR_X: {for (; i < steps; ++i) g_grid[status->x + i][status->y] = 1;} break;
case DIR_NX: {for (; i < steps; ++i) g_grid[status->x - i][status->y] = 1;} break;
case DIR_Y: {for (; i < steps; ++i) g_grid[status->x][status->y + i] = 1;} break;
case DIR_NY: {for (; i < steps; ++i) g_grid[status->x][status->y - i] = 1;} break;
}
}
// Update postion
status->x = xNew;
status->y = yNew;
}
static void handler_print(const struct status* status)
{
int i, j;
printf("====== print begin =====\n");
for (i = 0; i < MAX_Y; ++i){
for (j = 0; j < MAX_X; ++j)
printf("%d", g_grid[j][i]);
printf("\n");
}
printf("====== print end =====\n");
}
static void run(int* cmds)
{
int cmd;
struct status status;
init(&status);
while ( (cmd = GET_CMD(*cmds)) != CMD_END){
switch (cmd){
case CMD_NODRAW:
status.isDrawing = 0;
break;
case CMD_DRAW:
status.isDrawing = 1;
break;
case CMD_TURN_RIGHT:
status.dir = (status.dir + 1) % DIR_NUM;
break;
case CMD_TURN_LEFT:
status.dir = (status.dir + DIR_NUM - 1) % DIR_NUM;
break;
case CMD_MOVE:
handler_move(&status, *cmds);
break;
case CMD_PRINT:
handler_print(&status);
break;
}
cmds++;
}
}
/*********************************************
* Test case *
*********************************************/
void test1()
{
int cmds[] = {
CMD_DRAW,
CMD_MOVE_STEPS(5),
CMD_TURN_RIGHT,
CMD_MOVE_STEPS(4),
CMD_PRINT,
CMD_NODRAW,
CMD_TURN_LEFT,
CMD_MOVE_STEPS(10),
CMD_DRAW,
CMD_TURN_LEFT,
CMD_MOVE_STEPS(2),
CMD_PRINT,
CMD_END
};
run(cmds);
}
int main()
{
test1();
return 0;
}