Skip to content
Permalink
Browse files

P05 lab code added

  • Loading branch information
giei committed Mar 22, 2020
1 parent 6f959c9 commit 2f61cf20b1a110a7e72c08ddcd2fa262a9334838
@@ -0,0 +1,9 @@
SNP_SHARED_MAKEFILE := $(if $(SNP_SHARED_MAKEFILE),$(SNP_SHARED_MAKEFILE),"~/snp/shared.mk")

TARGET := bin/tic-tac-toe
MODULES := src/model.c src/view.c src/control.c
SOURCES := src/main.c $(MODULES)
TSTSOURCES := tests/tests.c $(MODULES)

include $(SNP_SHARED_MAKEFILE)

@@ -0,0 +1,8 @@
/**
* @mainpage SNP - P05 Tic Tac Toe Game
*
* @section Purpose
*
* This is a lab on usage of arrays.
*
*/
@@ -0,0 +1,154 @@
/**
* @file
* @brief Implementation
*/
#include "control.h"
#include "model.h"
#include <assert.h>

/**
* @brief Conversion from control field number (1...9) to 0-based model position (row, col).
* @param cell [IN] Field number (1...9).
* @return Returns the position of the field.
* @remark Asserts proper field range.
*/
static model_pos_t get_pos(size_t cell)
{
assert(1 <= cell && cell <= 9);
model_pos_t pos = { (cell - 1) / 3, (cell - 1) % 3 };
return pos;
}

/**
* @brief Conversion from control player to model state.
* @param player [IN] Control player value to convert.
* @return Returns the matching model state.
* @remark No assertion is done - defaults to model_state_none.
*/
static model_state_t get_state(control_player_t player)
{
switch(player) {
case control_player_a: return model_state_a;
case control_player_b: return model_state_b;
default: return model_state_none;
}
}

/**
* @brief Conversion from 0-based model position (row, col) to control field number (1...9).
* @param pos [IN] 0-based model position (row,col).
* @return The control filed number (1...9)
* @remark Asserts proper position range.
*/
static size_t get_cell(model_pos_t pos)
{
assert(pos.row < 3);
assert(pos.col < 3);
return 1 + pos.row * 3 + pos.col;
}

/**
* @brief Conversion from model state to control player.
* @param state [IN] Model state to convert
* @return Returns the matching control player value.
* @remark No assertion is done - defaults to control_no_player.
*/
static control_player_t get_player(model_state_t state)
{
switch(state) {
case model_state_a: return control_player_a;
case model_state_b: return control_player_b;
default: return control_no_player;
}
}

/**
* @brief Queries if a move is possible.
* @param instance [INOUT] The instance which holds the state.
* @return Returns 0 if no move is possible any more, otherwise 1.
*/
static int control_can_move(control_t *instance)
{
assert(instance);
return model_can_move(instance->model);
}

// public API function which is documented in the header file.
void control_init(control_t *instance, model_t *model)
{
assert(instance);
assert(model);
instance->player = control_player_a;
instance->model = model;
}

// public API function which is documented in the header file.
void control_move(control_t *instance, size_t cell)
{
assert(instance);
if (model_move(instance->model, get_pos(cell), get_state(instance->player))) {
if (control_can_move(instance)) {
switch(instance->player) {
case control_player_a:
instance->player = control_player_b;
break;
case control_player_b:
instance->player = control_player_a;
break;
default:
break;
}
} else {
instance->player = control_no_player;
}
}
}

// public API function which is documented in the header file.
control_player_t control_get_winner(control_t *instance)
{
assert(instance);
return get_player(model_get_winner(instance->model));
}

// public API function which is documented in the header file.
control_player_t control_get_player(control_t *instance)
{
assert(instance);
return instance->player;
}

// public API function which is documented in the header file.
control_player_t control_get_state(control_t *instance, size_t cell)
{
assert(instance);
return get_player(model_get_state(instance->model, get_pos(cell)));
}

// public API function which is documented in the header file.
control_line_t control_get_win(control_t *instance)
{
assert(instance);
if (control_get_winner(instance) == control_no_player) {
control_line_t no_win = { 0 };
return no_win;
}

model_line_t line = model_get_win_line(instance->model);
assert(line.dir != model_dir_none);
size_t start_cell = get_cell(line.start);
switch(line.dir) {
case model_dir_h:
return (control_line_t) { { start_cell, start_cell + 1, start_cell + 2 } };
case model_dir_v:
return (control_line_t) { { start_cell, start_cell + 3, start_cell + 6 } };
case model_dir_d:
if (start_cell == 1) {
return (control_line_t) { { start_cell, start_cell + 4, start_cell + 8 } };
} else {
return (control_line_t) { { start_cell, start_cell + 2, start_cell + 6 } };
}
default:
return (control_line_t) { { 1, 1, 1 } };
}
}
@@ -0,0 +1,80 @@
/**
* @file
* @brief MVC - agent between model and view
*/
#ifndef _CONTROL_H_
#define _CONTROL_H_

#include "model.h"

/**
* @brief The selection of possible players.
*/
typedef enum {
control_no_player, ///< none of the players
control_player_a, ///< first player
control_player_b, ///< second player
} control_player_t;

/**
* @brief Sequence of winning cell numbers in increasing cell numbers.
*/
typedef struct {
size_t line[3]; ///< the sequence of cells (1...9) or 0 in the first element if no win
} control_line_t;

/**
* @brief The instance type.
*/
typedef struct {
control_player_t player; ///< the current player
model_t *model; ///< the reference to the model
} control_t;

/**
* @brief Constructor: initialize the instance memory.
* @param instance [INOUT] The instance which holds the state.
* @param model [IN] Dependency Injection of the model instance.
*/
void control_init(control_t *instance, model_t *model);

/**
* @brief Performs a move on the board.
* @param instance [INOUT] The instance which holds the state.
* @param cell [IN] The affected field (1...9)
* @remark Silently ignores a move if it is not allowed (e.g. if already completed or the field is already played, etc.).
*/
void control_move(control_t *instance, size_t cell);

/**
* @brief Queries the winning player.
* @param instance [INOUT] The instance which holds the state.
* @returns Returns the winning player (if any).
*/
control_player_t control_get_winner(control_t *instance);

/**
* @brief Queries the next player.
* @param instance [INOUT] The instance which holds the state.
* @returns Returns the next player (if any).
* @remark This is updated by the control_move() function.
*/
control_player_t control_get_player(control_t *instance);

/**
* @brief Queries the state of a field.
* @param instance [INOUT] The instance which holds the state.
* @param cell [IN] The affected field of the board (1...9).
* @returns Returns the player which played this field (if any).
*/
control_player_t control_get_state(control_t *instance, size_t cell);

/**
* @brief Gets the winning fields (if any).
* @param instance [INOUT] The instance which holds the state.
* @returns Returns the field numbers in increasing order (1...9) which win the game (if any).
* @remark If there is no winner (yet), the first entry in the result is 0.
*/
control_line_t control_get_win(control_t *instance);

#endif // _CONTROL_H_
@@ -0,0 +1,39 @@
/* ----------------------------------------------------------------------------
* -- _____ ______ _____ -
* -- |_ _| | ____|/ ____| -
* -- | | _ __ | |__ | (___ Institute of Embedded Systems -
* -- | | | '_ \| __| \___ \ Zuercher Hochschule Winterthur -
* -- _| |_| | | | |____ ____) | (University of Applied Sciences) -
* -- |_____|_| |_|______|_____/ 8401 Winterthur, Switzerland -
* ----------------------------------------------------------------------------
*/
/**
* @file
* @brief Lab P04 dep2dot
*/
#include <stdio.h>
#include <stdlib.h>

#include "view.h"
#include "model.h"
#include "control.h"

/**
* @brief main function
* @param argc [in] number of entries in argv
* @param argv [in] program name plus command line arguments
* @returns returns success if valid date is given, failure otherwise
*/
int main(int argc, const char *argv[])
{
view_t view;
control_t control;
model_t model;

model_init(&model);
control_init(&control, &model);
view_init(&view, &control);
view_run(&view);

return EXIT_SUCCESS;
}

0 comments on commit 2f61cf2

Please sign in to comment.
You can’t perform that action at this time.