Gli eseguibili (Linux 32/64 bit e OS X) sono disponibili al seguente link. Le istruzioni vengono mostrate quando eseguite il programma.
Una possibile soluzione (commentata) della verifica è la seguente:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#define WR_PIPE "ticPipeIn"
#define RD_PIPE "ticPipeOut"
#define BUFSIZE 5
#define VICTORIES 100
#define SIZE 3
#define START "g"
#define END '$'
/*
* La verifica richiede la realizzazione di un programma che vinca
* 100 partite (non necessariamente consecutive) a tris contro il
* computer.
*
* Una partita viene avviata scrivendo il carattere 'g' nella pipe
* "ticPipeIn". Il programma riceve in "ticPipeOut" la posizione
* occupata dalla pedina dell'avversario nel formato "R,C#", dove R
* e C corrispondono al numero di riga e colonna. Riceve inoltre un
* carattere di controllo per determinare lo stato della partita:
* '$' indica che è terminata, '&' che non lo è. Nel secondo caso,
* il programma scrive in "ticPipeIn" la mossa da fare, usando il
* medesimo formato, e legge da "ticPipeOut" lo stato della partita
* in seguito alla sua mossa.
*/
int main(int argc, char *argv[]) {
int rp, wp, win, i, row, col;
char board[SIZE][SIZE], buffer[BUFSIZE], status;
/* Apri le pipe: termina il programma in caso di errore. */
wp = open(WR_PIPE, O_WRONLY);
if (wp < 0) {
perror("Errore apertura pipe in scrittura");
exit(EXIT_FAILURE);
}
rp = open(RD_PIPE, O_RDONLY);
if (rp < 0) {
perror("Errore apertura pipe in lettura");
exit(EXIT_FAILURE);
}
/* Imposta il seed per il generatore di numeri casuali. */
srand(time(NULL));
win = 0;
while (win < VICTORIES) {
/* Pulisci il campo ed inizia una nuova partita! */
memset(board, 0, SIZE * SIZE);
write(wp, START, strlen(START));
do {
/* Leggi la posizione dell'avversario e segnala come occupata. */
i = 0;
while (read(rp, buffer + i, 1) && buffer[i] != '#')
i++;
buffer[i + 1] = '\0';
sscanf(buffer, "%d,%d#", &row, &col);
board[row][col] = 1;
/* Leggi lo stato della partita. Se è terminata, abbiamo una sconfitta o
* un pareggio. Altrimenti facciamo la nostra mossa! */
read(rp, &status, 1);
if (status != END) {
/* La miglior strategia del mondo! Scegliamo in maniera casuale riga
* e colonna finché non viene trovata una posizione libera. */
do {
row = rand() % SIZE;
col = rand() % SIZE;
} while (board[row][col] != 0);
/* Scrivi la posizione sulla pipe e segnala come occupata. */
snprintf(buffer, BUFSIZE, "%d,%d#", row, col);
write(wp, buffer, strlen(buffer));
board[row][col] = 1;
/* Leggi lo stato della partita. Incrementa il contatore in
* caso di vittoria. */
read(rp, &status, 1);
if (status == END)
win++;
}
} while (status != END);
}
/* Ok, abbiamo vinto! Possiamo chiudere le pipe! */
close(wp);
close(rp);
return EXIT_SUCCESS;
}