diff --git a/battleships.c b/battleships.c index 7f8b38e..29bdedf 100644 --- a/battleships.c +++ b/battleships.c @@ -1,10 +1,15 @@ #include #include +#include +#include enum { - N_SHIPS, - WIDTH = 8, - HEIGHT = 8, + BOARD_SIZE = 10, +}; + +struct state { + char board[BOARD_SIZE][BOARD_SIZE]; + int game_over; }; struct position { @@ -12,69 +17,163 @@ struct position { int y; }; -struct ship { - int length; +enum orientation { + O_VERTICAL, + O_HORIZONTAL +}; + +struct boat { + enum orientation orientation; + + /** left upper corner */ struct position position; - char sunken; - char alignment; - char *hits; + + int length; }; -struct game_state { - char running; - char board[WIDTH][HEIGHT]; - struct ship ships[N_SHIPS]; +struct position read_position(void); + +struct boat generate_boat(int length); + +struct state generate_state(void); + +void display_state(struct state state); + +int valid_position(struct position p); + +/** + * Simulates one step of battleship. + * + * Performs the following steps: + * + * - apply hit to board + * - check sunken ships + * - check game over + */ +void update_state(struct state * state, struct position hit); + +enum target { + T_WATER, + T_BOAT, }; -struct ship create_ship(int length, struct position position); -void delete_ship(struct ship ship); - -void hit(struct game_state *game_state, struct position position); - -struct game_state init_game_state(); -void deinit_game_state(struct game_state *game_state); -char check_win_condition(struct game_state *game_state); - -struct position read_position(); +enum target check_hit(struct state state, struct position hit); int main(void) { - struct game_state game_state = init_game_state(); - while (game_state.running) { - struct position hit_position = read_position(); - hit(&game_state, hit_position); - if (check_win_condition(&game_state)) { - game_state.running = 0; - printf("You win!"); + struct state state = generate_state(); + + while (!state.game_over) { + display_state(state); + + struct position hit = read_position(); + + /* game logic */ + update_state(&state, hit); + } +} + +struct position read_position(void) { + printf("enter coordinate: "); + while (1) { + char* line = NULL; + size_t size = 0; + getline(&line, &size, stdin); + fflush(stdout); + + struct position position; + char col; + sscanf("%c%d", &col, &position.y); + free(line); + + position.x = tolower(col) - 'a'; + if (valid_position(position)) { + return position; } - } - deinit_game_state(&game_state); - return 0; -} -struct ship create_ship(int length, struct position position) { - struct ship ship = {.length = length, .position = position, .sunken = 0}; - ship.hits = calloc(length, sizeof *ship.hits); - return ship; -} -void delete_ship(struct ship ship) { - free(ship.hits); -} - -void hit(struct game_state *game_state, struct position position); - -struct game_state init_game_state() { - struct game_state game_state; - for (int i = 0; i < N_SHIPS; ++i) { - /* generate ship */ + puts("invalid input!"); } } -void deinit_game_state(struct game_state *game_state) { - for (int i = 0; i < N_SHIPS; ++i) { - delete_ship(game_state->ships[i]); - } +struct position random_position(void) { + struct position p; + p.x = rand() % BOARD_SIZE; + p.y = rand() % BOARD_SIZE; + return p; } -char check_win_condition(struct game_state *game_state); +enum orientation random_orientation(void) { + return (rand() % 2); +} -struct position read_position(); +struct boat generate_boat(int length) { + struct boat b; + b.length = length; + b.position = random_position(); + b.orientation = random_orientation(); + return b; +} + +int valid_position(struct position p) { + return (p.x >= 0) && (p.x < BOARD_SIZE) && (p.y >= 0) && (p.y < BOARD_SIZE); +} + +int place_boat(struct state * state, struct boat boat, char c) { + int dx = (boat.orientation == O_VERTICAL) ? 1 : 0; + int dy = (boat.orientation == O_HORIZONTAL) ? 1 : 0; + + struct position curpos = boat.position; + for (int i = 0; i < boat.length; ++i) { + if (!valid_position(curpos)) return 0; + if (state->board[curpos.y][curpos.x] != 0) return 0; + + if (c) { + state->board[curpos.y][curpos.x] = c; + } + + curpos.x += dx; + curpos.y += dy; + } + + return 1; +} + +const int BOAT_LENGTHS[] = { 5, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; + +struct state generate_state(void) { + struct state state; + + memset(state.board, 0, BOARD_SIZE*BOARD_SIZE); + state.game_over = 0; + + // generate some boats + char boat_char = 'A'; + for (size_t i = 0; i < sizeof(BOAT_LENGTHS) / sizeof(BOAT_LENGTHS[0]); ++i) { + int length = BOAT_LENGTHS[i]; + struct boat boat; + do { + boat = generate_boat(length); + } while(!place_boat(&state, boat, '\0')); + place_boat(&state, boat, boat_char); + boat_char++; + } + + return state; +} + +void display_state(struct state state) { + for (int y = 0; y < BOARD_SIZE; ++y) { + for (int x = 0; x < BOARD_SIZE; ++x) { + if (state.board[y][x]) { + printf("%c", state.board[y][x]); + } else { + printf("~"); + } + } + printf("\n"); + } + puts("---"); +} + +void update_state(struct state * state, struct position hit) { + +} diff --git a/battleships_manuel.c b/battleships_manuel.c new file mode 100644 index 0000000..7f8b38e --- /dev/null +++ b/battleships_manuel.c @@ -0,0 +1,80 @@ +#include +#include + +enum { + N_SHIPS, + WIDTH = 8, + HEIGHT = 8, +}; + +struct position { + int x; + int y; +}; + +struct ship { + int length; + struct position position; + char sunken; + char alignment; + char *hits; +}; + +struct game_state { + char running; + char board[WIDTH][HEIGHT]; + struct ship ships[N_SHIPS]; +}; + +struct ship create_ship(int length, struct position position); +void delete_ship(struct ship ship); + +void hit(struct game_state *game_state, struct position position); + +struct game_state init_game_state(); +void deinit_game_state(struct game_state *game_state); +char check_win_condition(struct game_state *game_state); + +struct position read_position(); + +int main(void) { + struct game_state game_state = init_game_state(); + while (game_state.running) { + struct position hit_position = read_position(); + hit(&game_state, hit_position); + if (check_win_condition(&game_state)) { + game_state.running = 0; + printf("You win!"); + } + } + deinit_game_state(&game_state); + return 0; +} + +struct ship create_ship(int length, struct position position) { + struct ship ship = {.length = length, .position = position, .sunken = 0}; + ship.hits = calloc(length, sizeof *ship.hits); + return ship; +} +void delete_ship(struct ship ship) { + free(ship.hits); +} + +void hit(struct game_state *game_state, struct position position); + +struct game_state init_game_state() { + struct game_state game_state; + for (int i = 0; i < N_SHIPS; ++i) { + /* generate ship */ + } +} + +void deinit_game_state(struct game_state *game_state) { + for (int i = 0; i < N_SHIPS; ++i) { + delete_ship(game_state->ships[i]); + } +} + +char check_win_condition(struct game_state *game_state); + +struct position read_position();