Add model
This commit is contained in:
parent
90508a3b3b
commit
f33b6c8acb
6 changed files with 467 additions and 10 deletions
27
include/common.h
Normal file
27
include/common.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
/*Status code to represent respectively,
|
||||
a negative answer,
|
||||
a positive answer,
|
||||
an almost positive answer
|
||||
*/
|
||||
typedef enum {
|
||||
NO,
|
||||
YES,
|
||||
ALMOST,
|
||||
} e_status;
|
||||
|
||||
#endif /*COMMON*/
|
195
include/model.h
Normal file
195
include/model.h
Normal file
|
@ -0,0 +1,195 @@
|
|||
#ifndef MODEL_H
|
||||
#define MODEL_H
|
||||
#include "common.h"
|
||||
|
||||
#define MIN_BOARD_LEVEL 1
|
||||
#define MAX_BOARD_LEVEL 2
|
||||
|
||||
// Constant character to represent the cross player, the round, none or both of
|
||||
// them (this last one is usefull for tie game)
|
||||
typedef enum {
|
||||
PLAYER_O = 'O',
|
||||
PLAYER_X = 'X',
|
||||
NOBODY = ' ',
|
||||
BOTH = '#'
|
||||
} e_player;
|
||||
|
||||
// Constant defining the 9 possible positions in a tic tac toe, any of this
|
||||
// position and none of this position
|
||||
typedef enum {
|
||||
TOPLEFT,
|
||||
TOPCENTER,
|
||||
TOPRIGHT,
|
||||
MIDLEFT,
|
||||
MIDCENTER,
|
||||
MIDRIGHT,
|
||||
BOTTOMLEFT,
|
||||
BOTTOMCENTER,
|
||||
BOTTOMRIGHT,
|
||||
FREE,
|
||||
NONE
|
||||
} e_location;
|
||||
|
||||
#define TICTACTOE_SIZE 9
|
||||
#define TICTACTOE_WIDTH 3
|
||||
|
||||
// The tic tac toe structure
|
||||
typedef struct {
|
||||
e_player *content; // array of TICTACTOE_SIZE e_player defining content of
|
||||
// each the TICTACTOE_SIZE cells of a tic tac toe defined
|
||||
// from top left to bottom right
|
||||
e_player winner; // player who have won the tic tac toe game; BOTH in case of
|
||||
// a tie game
|
||||
} s_tictactoe;
|
||||
|
||||
// A move structure
|
||||
typedef struct {
|
||||
e_location inner_position; // The position in the inner tic tac toe
|
||||
e_location outer_position; // The position in the outer tic tact toe
|
||||
e_player player; // The player who achieve the move
|
||||
} s_move;
|
||||
|
||||
// A simple linked list of s_move
|
||||
typedef struct list {
|
||||
s_move *last_move;
|
||||
struct list *next;
|
||||
} list_element_s_move;
|
||||
|
||||
// The ultimate tic tac toe structure
|
||||
typedef struct {
|
||||
uint inception_level; // inception level of the ultimate tictactoe
|
||||
s_tictactoe *
|
||||
*inner_tictactoes; // array of the TICTACTOE_SIZE inner tic tac
|
||||
// toes defining content of each the
|
||||
// TICTACTOE_SIZE cells of an ultimate tic tac
|
||||
// toe defined from top left to bottom right
|
||||
s_tictactoe *
|
||||
outer_tictactoe; // a tic tac toe representing the outer game which
|
||||
// allows to store the winners of each inner tic tac toe
|
||||
list_element_s_move *history; // full history of the played moves as a stack
|
||||
// of s_moves - LIFO ended by a NULL pointer.
|
||||
} s_utictactoe;
|
||||
/*
|
||||
* A uttt of inception-level 1 just correspond to the outer_tictactoe while
|
||||
* inner_tictactoes is NULL
|
||||
*
|
||||
* A uttt of inception-level 2 is an array of TICTACTOE_SIZE tictactoes from
|
||||
* TOP_LEFT to BOTTOM_RIGHT and outer_ticatactoe represent the overall game
|
||||
* Example of indices for a uttt of inception-level 1
|
||||
* 0|1|2
|
||||
* -----
|
||||
* 3|4|5
|
||||
* -----
|
||||
* 6|7|8
|
||||
*/
|
||||
|
||||
/*!
|
||||
* This function allocates an s_move structure corresponding to an empty move
|
||||
* (free positions and nobody as player).
|
||||
*
|
||||
* \return a reference to the s_move memory space allocated, NULL in case of
|
||||
* allocation problem.
|
||||
*/
|
||||
s_move *create_empty_move();
|
||||
|
||||
/*!
|
||||
* This function allocates an s_tictactoe structure corresponding to an empty
|
||||
* tictactoe ready to be played.
|
||||
*
|
||||
* \return a reference to the s_tictactoe memory space allocated, NULL in case
|
||||
* of allocation problem.
|
||||
*/
|
||||
s_tictactoe *create_empty_tictactoe();
|
||||
|
||||
/*!
|
||||
* This function allocates an s_utictactoe structure corresponding to an empty
|
||||
* utictactoe of the corresponding inception_level and ready to be played
|
||||
* starting by PLAYER_X player.
|
||||
*
|
||||
* \return a reference to the s_utictactoe memory space allocated, NULL in case
|
||||
* of allocation problem.
|
||||
*/
|
||||
s_utictactoe *create_empty_utictactoe(uint inception_level);
|
||||
|
||||
/*!
|
||||
* This function free all the memory used by a given s_move which reference is
|
||||
* given.
|
||||
*
|
||||
* \param p_move a pointer on a s_move to be freed.
|
||||
*/
|
||||
void free_move(s_move *p_move);
|
||||
|
||||
/*!
|
||||
* This function free all the memory used by a given tictactoe structure which
|
||||
* reference is given.
|
||||
*
|
||||
* \param p_ttt a pointer on a s_tictactoe to be freed.
|
||||
*/
|
||||
void free_tictactoe(s_tictactoe *p_ttt);
|
||||
|
||||
/*!
|
||||
* This function free all the memory used by a given ultimate tictactoe
|
||||
* structure which reference is given.
|
||||
*
|
||||
* \param p_uttt a pointer on a s_utictactoe to be freed.
|
||||
*/
|
||||
void free_utictactoe(s_utictactoe *p_uttt);
|
||||
|
||||
/*!
|
||||
* This function determines the e_player which should be the next player to play
|
||||
* in the corresponding p_uttt.
|
||||
*
|
||||
* \param p_uttt a pointer on a s_utictactoe.
|
||||
* \return a e_player (PLAYER_X - if last player who played was PLAYER_O or its
|
||||
* the first move, PLAYER_O - if last player who played was PLAYER_X, or NOBODY
|
||||
* if no move can be done anymore or if there is a winner).
|
||||
*/
|
||||
e_player get_next_player_to_play(s_utictactoe *p_uttt);
|
||||
|
||||
/*!
|
||||
* This function determines the next outer position where the current player
|
||||
* should play its next move in the corresponding p_uttt.
|
||||
*
|
||||
* \param p_uttt a pointer on a s_utictactoe.
|
||||
* \return a e_location corresponding to the next outer position induced by the
|
||||
* last move
|
||||
* - set to FREE if the next move is free of constraints
|
||||
*/
|
||||
e_location get_next_outer_position(s_utictactoe *p_uttt);
|
||||
|
||||
/*!
|
||||
* This function evaluate if a move is valid in the corresponding p_uttt.
|
||||
* A move is valid if its player and the inner and outer positions are
|
||||
* consistent with the current s_utictactoe: correct unused position, not a
|
||||
* tictactoe with already a winner and the correct player. It returns a boolean
|
||||
* corresponding to the success of the move.
|
||||
*
|
||||
* \param p_uttt a pointer on a s_utictactoe.
|
||||
* \param a_move an s_move to be played.
|
||||
* \return YES if playing a_move was possible - NO if impossible.
|
||||
*/
|
||||
e_status is_move_valid(s_utictactoe *p_uttt, s_move *p_move);
|
||||
|
||||
/*!
|
||||
* This function set the winner of the corresponding p_ttt.
|
||||
*
|
||||
* \param p_ttt a pointer on a s_tictactoe whose winner field will be updated.
|
||||
*/
|
||||
void set_tictactoe_winner(s_tictactoe *p_ttt);
|
||||
|
||||
/*!
|
||||
* This function tries to play a given move in the corresponding p_uttt.
|
||||
* It plays the corresponding move if possible and returns a boolean
|
||||
* corresponding to the success of the move. The function should set the
|
||||
* possible winner.
|
||||
*
|
||||
* \param p_uttt a pointer on a s_utictactoe.
|
||||
* \param p_move an s_move to be played.
|
||||
* \return YES if playing a_move was possible - NO if impossible.
|
||||
*/
|
||||
e_status play_move(s_utictactoe *p_uttt, s_move *p_move);
|
||||
|
||||
/*Given usefull functions*/
|
||||
void draw_utictactoe(s_utictactoe *p_uttt);
|
||||
void draw_utictactoe_history(s_utictactoe *p_uttt);
|
||||
#endif /* MODEL_H */
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -std=c99
|
||||
CPPFLAGS=
|
||||
CPPFLAGS=-I../include
|
||||
|
||||
all: utictactoe
|
||||
|
||||
utictactoe: utictactoe.c ## Compile utictactoe.c
|
||||
utictactoe: utictactoe.c model.c## Compile utictactoe.c
|
||||
|
||||
# Nettoyage
|
||||
.PHONY: clean help
|
||||
|
|
221
src/model.c
Normal file
221
src/model.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
#include "model.h"
|
||||
|
||||
|
||||
/*
|
||||
* Create empty move
|
||||
*/
|
||||
|
||||
s_move *create_empty_move(){
|
||||
s_move * value = (s_move*) malloc(sizeof(s_move));
|
||||
if ( value ) {
|
||||
value->inner_position = FREE;
|
||||
value->outer_position = FREE;
|
||||
value->player = NOBODY;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an empty tictactoe
|
||||
*/
|
||||
s_tictactoe *create_empty_tictactoe() {
|
||||
|
||||
// Create s_tictactoe structure
|
||||
s_tictactoe * value = (s_tictactoe*) malloc(sizeof(s_tictactoe));
|
||||
if ( value ) {
|
||||
// create player
|
||||
value->winner = NOBODY;
|
||||
value->content = (e_player*) malloc(sizeof(e_player) * TICTACTOE_SIZE);
|
||||
if ( ! value->content ) {
|
||||
return value->content;
|
||||
}
|
||||
for ( int i=0;i<TICTACTOE_SIZE; i++){
|
||||
value->content[i] = NOBODY;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create empty uTicTacToe
|
||||
*/
|
||||
|
||||
s_utictactoe *create_empty_utictactoe (uint inception_level) {
|
||||
s_utictactoe * value = (s_utictactoe*) malloc(sizeof(s_utictactoe));
|
||||
if ( value ) {
|
||||
|
||||
// then initiate outer_tictactoe amd inception_level
|
||||
value->outer_tictactoe = create_empty_tictactoe();
|
||||
value->inception_level = inception_level;
|
||||
value->history = NULL; // no history for now
|
||||
|
||||
// initialize inner TTT
|
||||
if (inception_level == 1){
|
||||
value->inner_tictactoes = NULL;
|
||||
}
|
||||
else {
|
||||
// As inception level can't be more than 2 (for now), inner_ttts
|
||||
// should be 9 simple ttt
|
||||
|
||||
value->inner_tictactoes = (s_tictactoe**)
|
||||
malloc(sizeof(s_tictactoe));
|
||||
|
||||
if ( ! value->inner_tictactoes ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ( int i=0; i<TICTACTOE_SIZE; i++) {
|
||||
value->inner_tictactoes[i] = create_empty_tictactoe();
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void free_move(s_move *p_move){
|
||||
if ( p_move == NULL ) {
|
||||
free(p_move);
|
||||
}
|
||||
}
|
||||
|
||||
void free_tictactoe(s_tictactoe *p_ttt){
|
||||
if ( p_ttt) {
|
||||
free(p_ttt->content);
|
||||
free(p_ttt);
|
||||
p_ttt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void free_utictactoe(s_utictactoe *p_uttt){
|
||||
if ( p_uttt ) {
|
||||
// if we have inner_ttt we need to remove inet
|
||||
if ( p_uttt->inner_tictactoes != NULL ) {
|
||||
for ( int i=0; i<TICTACTOE_SIZE; i++) {
|
||||
free_tictactoe(p_uttt->inner_tictactoes[i]);
|
||||
}
|
||||
free(p_uttt->inner_tictactoes);
|
||||
}
|
||||
free_tictactoe(p_uttt->outer_tictactoe);
|
||||
free(p_uttt);
|
||||
p_uttt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
e_player get_next_player_to_play(s_utictactoe *p_uttt) {
|
||||
if ( p_uttt->history->last_move->player == PLAYER_O ) {
|
||||
return PLAYER_X;
|
||||
}
|
||||
else {
|
||||
return PLAYER_O;
|
||||
}
|
||||
}
|
||||
|
||||
e_location get_next_outer_position(s_utictactoe *p_uttt) {
|
||||
if ( p_uttt->inner_tictactoes != NULL ) {
|
||||
e_location pos = p_uttt->history->last_move->inner_position;
|
||||
if ( p_uttt->inner_tictactoes->content[pos]->winner == NOBODY ) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return FREE;
|
||||
}
|
||||
|
||||
e_status is_move_valid(s_utictactoe *p_uttt, s_move *p_move){
|
||||
if ( get_next_player_to_play(p_uttt) != p_move->player ) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
void set_tictactoe_winner(s_tictactoe *p_ttt){
|
||||
bool find;
|
||||
int next;
|
||||
|
||||
if ( p_ttt->winner == NOBODY ) {
|
||||
for(int i = 0; i < TICTACTOE_WIDTH; i++){
|
||||
|
||||
/*
|
||||
* Test for first diagonale
|
||||
*/
|
||||
if ( p_ttt->content[i] != NOBODY ) {
|
||||
// if case 0 we need to test diagonale
|
||||
if ( i == 0 ){
|
||||
int next;
|
||||
find = true;
|
||||
for (int l = 1; l < TICTACTOE_WIDTH; l++) {
|
||||
// Maybe it is overkill to test diagonal but...
|
||||
// ... no need to rewrite if we update TICTACTOE_WIDTH
|
||||
next = l * TICTACTOE_WIDTH + l;
|
||||
if ( p_ttt->content[i] != p_ttt ->content[next]) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (find == true) {
|
||||
p_ttt->winner = p_ttt->content[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* second diagonal, from the end of line
|
||||
*/
|
||||
if ( i == TICTACTOE_WIDTH - 1 ) {
|
||||
find = true;
|
||||
for ( int l = 1; l < TICTACTOE_WIDTH; l++){
|
||||
next = (TICTACTOE_WIDTH - 1) * l;
|
||||
if ( p_ttt->content[i] == p_ttt->content[next] ) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( find == true ){
|
||||
p_ttt->winner = p_ttt->content[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* column
|
||||
*/
|
||||
find = true;
|
||||
for (int c = 1; c < TICTACTOE_WIDTH; c++ ) {
|
||||
next = TICTACTOE_WIDTH * c + i;
|
||||
if ( p_ttt->content[i] != p_ttt->content[next] ) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
if ( find == true ){
|
||||
p_ttt->winner = p_ttt->content[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* line
|
||||
*/
|
||||
int line = i * TICTACTOE_WIDTH;
|
||||
if (p_ttt->content[line] != NOBODY){
|
||||
find = true;
|
||||
for ( int l = 1; l < TICTACTOE_WIDTH; l++ ) {
|
||||
next = line + l;
|
||||
if ( p_ttt->content[line] != p_ttt->content[next] ) {
|
||||
find = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( find == true ) {
|
||||
p_ttt->winner = p_ttt->content[line];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e_status play_move(s_utictactoe *p_ttt, s_move *p_move) {
|
||||
return YES;
|
||||
}
|
BIN
src/utictactoe
Executable file
BIN
src/utictactoe
Executable file
Binary file not shown.
|
@ -1,11 +1,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <stdio.h>
|
||||
//#include <getopt.h>
|
||||
//#include <stdbool.h>
|
||||
//#include <assert.h>
|
||||
//#include <string.h>
|
||||
//#include <unistd.h>
|
||||
#include "utictactoe.h"
|
||||
#include "common.h"
|
||||
#include "model.h"
|
||||
|
||||
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
||||
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
||||
|
@ -26,6 +28,9 @@ void help(){
|
|||
}
|
||||
|
||||
int check_int_value ( char *value, int min, int max){
|
||||
struct a {
|
||||
int b;
|
||||
};
|
||||
char * end_ptr;
|
||||
int result;
|
||||
result = strtol(optarg, &end_ptr, 10);
|
||||
|
@ -135,6 +140,15 @@ int main(int argc, char* argv[]) {
|
|||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
printf("Hello World!\n");
|
||||
s_move *test_move = create_empty_move();
|
||||
free_move(test_move);
|
||||
s_tictactoe *test_ttt = create_empty_tictactoe();
|
||||
free_tictactoe(test_ttt);
|
||||
s_utictactoe *test_uttt = create_empty_utictactoe(1);
|
||||
free_utictactoe(test_uttt);
|
||||
test_uttt = create_empty_utictactoe(2);
|
||||
free_utictactoe(test_uttt);
|
||||
test_uttt = create_empty_utictactoe(3);
|
||||
free_utictactoe(test_uttt);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue