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
|
CC=gcc
|
||||||
CFLAGS=-Wall -g -std=c99
|
CFLAGS=-Wall -g -std=c99
|
||||||
CPPFLAGS=
|
CPPFLAGS=-I../include
|
||||||
|
|
||||||
all: utictactoe
|
all: utictactoe
|
||||||
|
|
||||||
utictactoe: utictactoe.c ## Compile utictactoe.c
|
utictactoe: utictactoe.c model.c## Compile utictactoe.c
|
||||||
|
|
||||||
# Nettoyage
|
# Nettoyage
|
||||||
.PHONY: clean help
|
.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 <stdlib.h>
|
||||||
#include <stdio.h>
|
//#include <stdio.h>
|
||||||
#include <getopt.h>
|
//#include <getopt.h>
|
||||||
#include <stdbool.h>
|
//#include <stdbool.h>
|
||||||
#include <assert.h>
|
//#include <assert.h>
|
||||||
#include <string.h>
|
//#include <string.h>
|
||||||
#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include "utictactoe.h"
|
#include "utictactoe.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
||||||
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
||||||
|
@ -26,6 +28,9 @@ void help(){
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_int_value ( char *value, int min, int max){
|
int check_int_value ( char *value, int min, int max){
|
||||||
|
struct a {
|
||||||
|
int b;
|
||||||
|
};
|
||||||
char * end_ptr;
|
char * end_ptr;
|
||||||
int result;
|
int result;
|
||||||
result = strtol(optarg, &end_ptr, 10);
|
result = strtol(optarg, &end_ptr, 10);
|
||||||
|
@ -135,6 +140,15 @@ int main(int argc, char* argv[]) {
|
||||||
exit (EXIT_FAILURE);
|
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;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue