I wrote this to test some networking routines. Experienced programmers may want to critique. Comments welcome. Beginning programmers might find something useful. Thanks, Chris -- /* tic_tac_toe.c * * (c) 2010 Chris Nystrom * * Public Domain * * Use this for whatever you want * * compiles with no errors on linux * * Start this server then telnet to the server using port 32662 ("telnet localhost 32662") to play. You must have 2 players. */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE !FALSE #endif /* the port users will be connecting to */ #define MYPORT 32662 /* how many pending connections queue will hold */ #define BACKLOG 10 /* listener socket */ int sockfd; void init_server(void) { /* my address information */ struct sockaddr_in my_addr; int yes = 1; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket() error"); exit(1); } else printf("socket() sockfd (listener) is: %d\n", sockfd); if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt() error"); exit(1); } else printf("setsockopt() is OK...\n"); /* host byte order */ my_addr.sin_family = AF_INET; /* short, network byte order */ my_addr.sin_port = htons(MYPORT); /* automatically fill with my IP */ my_addr.sin_addr.s_addr = INADDR_ANY; printf("Using %s and port %d...\n", inet_ntoa(my_addr.sin_addr), MYPORT); /* zero the rest of the struct */ memset(&(my_addr.sin_zero), '\0', 8); if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { perror("bind() error"); exit(1); } else printf("bind() is OK...\n"); if (listen(sockfd, BACKLOG) == -1) { perror("listen() error"); exit(1); } printf("listen() is OK...\n"); printf("Listening...\n"); } int new_connection(void) { int new_fd; socklen_t sin_size; /* connector’s address information */ struct sockaddr_in their_addr; sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -1) { perror("accept() error"); exit(1); } else printf("accept() is OK...\n"); printf("socket %d: Connection from %s\n", new_fd, inet_ntoa(their_addr.sin_addr)); return (new_fd); } void write_to_socket(int fd, char *s) { if (send(fd, s, strlen(s), 0) == -1) perror("send() error"); // else // printf ("send is OK...!\n"); } #define BUF_SIZE (1024) void printf_to_socket(int fd, const char *format, ...) { char s[BUF_SIZE]; va_list ap; va_start(ap, format); vsnprintf(s, BUF_SIZE, format, ap); va_end(ap); write_to_socket(fd, s); } int read_from_socket(int fd, char *buf) { int nbytes; if ((nbytes = recv(fd, buf, sizeof(buf), 0)) <= 0) { if (nbytes == 0) /* connection closed */ printf("socket %d hung up\n", fd); else perror("recv() error"); } return (nbytes); } void close_socket(int fd) { close(fd); printf("socket %d: closed...\n", fd); } #define NUM_OF_PLAYERS (2) int fd[NUM_OF_PLAYERS]; int num_players = NUM_OF_PLAYERS; void read_from_player(int player, char *s) { read_from_socket(fd[player - 1], s); } void write_to_player(int player, char *s) { write_to_socket(fd[player - 1], s); } void write_to_other_player(int player, char *s) { /* switch player */ if (1 == player) { player = 2; } else { player = 1; } write_to_player(player, s); } void write_to_all_players(char *s) { int i; for (i = 0; i < num_players; i++) { write_to_socket(fd[i], s); } } void printf_to_player(int player, const char *format, ...) { char s[BUF_SIZE]; va_list ap; va_start(ap, format); vsnprintf(s, BUF_SIZE, format, ap); va_end(ap); write_to_player(player, s); } void printf_to_other_player(int player, const char *format, ...) { char s[BUF_SIZE]; va_list ap; va_start(ap, format); vsnprintf(s, BUF_SIZE, format, ap); va_end(ap); write_to_other_player(player, s); } void printf_to_all_players(const char *format, ...) { char s[BUF_SIZE]; va_list ap; va_start(ap, format); vsnprintf(s, BUF_SIZE, format, ap); va_end(ap); write_to_all_players(s); } void init_game(void) { char sTitle[] = "\nTic Tac Toe Server v1.0\n\n"; init_server(); fd[0] = new_connection(); printf("Player 1 has joined.\n"); fd[1] = new_connection(); printf("Player 2 has joined.\n"); write_to_all_players(sTitle); } void print_guide(void) { write_to_all_players("Select moves from this grid:\n\n"); write_to_all_players(" 1 | 2 | 3\n"); write_to_all_players("----------\n"); write_to_all_players(" 4 | 5 | 6\n"); write_to_all_players("----------\n"); write_to_all_players(" 7 | 8 | 9\n"); } int board[9] = { 0 }; void reset_game(void) { int i; for (i = 0; i < 9; i++) { board[i] = 0; } } void print_board(void) { int i; int count = 0; write_to_all_players("\n"); for (i = 0; i < 9; i++) { if (1 == board[i]) { write_to_all_players(" X "); } else if (2 == board[i]) { write_to_all_players(" O "); } else { write_to_all_players(" . "); } count++; if (3 == count) { write_to_all_players("\n"); if (i < 8) { write_to_all_players("-----------\n"); } count = 0; } else { write_to_all_players("|"); } } write_to_all_players("\n"); } int get_move(int player) { int move = 0; char buf[1024]; printf_to_other_player(player, "Waiting on player %d...\n", player); while (move < 1 || move > 9) { printf_to_player(player, "Player %d move: ", player); read_from_player(player, buf); move = atoi(buf); if (board[move - 1] != 0) { write_to_player(player, "That spot already taken!\n"); move = 0; } } printf_to_other_player(player, "Player %d move: %d\n", player, move); return (move); } void process_move(int player, int move) { board[move - 1] = player; } int check_for_winner(void) { int winner = FALSE; /* across */ if ((board[0] != 0) && (board[0] == board[1]) && (board[1] == board[2])) { winner = board[0]; } if ((board[3] != 0) && (board[3] == board[4]) && (board[4] == board[5])) { winner = board[3]; } if ((board[6] != 0) && (board[6] == board[7]) && (board[7] == board[8])) { winner = board[6]; } /* down */ if ((board[0] != 0) && (board[0] == board[3]) && (board[3] == board[6])) { winner = board[0]; } if ((board[1] != 0) && (board[1] == board[4]) && (board[4] == board[7])) { winner = board[1]; } if ((board[2] != 0) && (board[2] == board[5]) && (board[5] == board[8])) { winner = board[2]; } /* diagonal */ if ((board[0] != 0) && (board[0] == board[4]) && (board[4] == board[8])) { winner = board[4]; } if ((board[2] != 0) && (board[2] == board[4]) && (board[4] == board[6])) { winner = board[4]; } return (winner); } void close_all_sockets(void) { int i; for (i = 0; i < num_players; i++) { close_socket(fd[i]); } } void play_game(void) { int player = 1; int winner = FALSE; int draw = FALSE; int move; int count = 0; reset_game(); print_guide(); print_board(); while (!winner && !draw) { move = get_move(player); printf_to_other_player(player, "%d\n", move); process_move(player, move); print_board(); winner = check_for_winner(); count++; if (!winner && 9 == count) { draw = TRUE; } /* switch player */ if (1 == player) { player = 2; } else { player = 1; } } write_to_all_players("\nGame over!\n\n"); if (winner) { printf_to_all_players("The winner is player %d!\n\n", winner); } if (draw) { write_to_all_players("The game was a draw! No winner!\n\n"); } } int main(int argc, char *argv[]) { init_game(); play_game(); close_all_sockets(); exit(0); } -- E-Mail: Chris Nystrom <cnystrom@xxxxxxxxx> Saving the world from web programming. http://www.newio.org - G-Talk: cnystrom --------------------- To unsubscribe go to http://gameprogrammer.com/mailinglist.html