Skip to content

Commit 7de42a2

Browse files
committed
lab10 end
1 parent 76f618b commit 7de42a2

File tree

4 files changed

+752
-0
lines changed

4 files changed

+752
-0
lines changed

lab10/src/client.c

+329
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
#include "common.h"
2+
int server_socket;
3+
int is_client_O;
4+
char buffer[MAX_MSG_LEN + 1];
5+
char *name, *command, *arg;
6+
game_board g_board;
7+
state current_state = START;
8+
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
9+
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
10+
int move(game_board *board, int position)
11+
{
12+
if (position < 0 || position > 9 || board->objects[position] != FREE)
13+
return 0;
14+
15+
board->objects[position] = board->move ? O : X;
16+
board->move = !board->move;
17+
return 1;
18+
}
19+
sign check_winner(game_board *board)
20+
{
21+
sign column = FREE;
22+
23+
for (int x = 0; x < 3; x++)
24+
{
25+
sign first = board->objects[x];
26+
sign second = board->objects[x + 3];
27+
sign third = board->objects[x + 6];
28+
29+
if (first == second && first == third && first != FREE)
30+
column = first;
31+
}
32+
33+
if (column != FREE)
34+
return column;
35+
36+
sign row = FREE;
37+
for (int y = 0; y < 3; y++)
38+
{
39+
sign first = board->objects[3 * y];
40+
sign second = board->objects[3 * y + 1];
41+
sign third = board->objects[3 * y + 2];
42+
if (first == second && first == third && first != FREE)
43+
row = first;
44+
}
45+
46+
if (row != FREE)
47+
return row;
48+
49+
sign lower_diagonal = FREE;
50+
51+
sign first = board->objects[0];
52+
sign second = board->objects[4];
53+
sign third = board->objects[8];
54+
55+
if (first == second && first == third && first != FREE)
56+
lower_diagonal = first;
57+
if (lower_diagonal != FREE)
58+
return lower_diagonal;
59+
sign upper_diagonal = FREE;
60+
first = board->objects[2];
61+
second = board->objects[4];
62+
third = board->objects[6];
63+
if (first == second && first == third && first != FREE)
64+
upper_diagonal = first;
65+
66+
return upper_diagonal;
67+
}
68+
void end()
69+
{
70+
char buffer[MAX_MSG_LEN + 1];
71+
sprintf(buffer, "end: :%s", name);
72+
send(server_socket, buffer, MAX_MSG_LEN, 0);
73+
exit(0);
74+
}
75+
void check_game_status()
76+
{
77+
bool win = false;
78+
sign winner = check_winner(&g_board);
79+
80+
if (winner != FREE)
81+
{
82+
if ((is_client_O && winner == O) || (!is_client_O && winner == X))
83+
printf("You won!\n");
84+
else
85+
printf("You lost!\n");
86+
87+
win = true;
88+
}
89+
bool draw = true;
90+
for (int i = 0; i < 9; i++)
91+
{
92+
if (g_board.objects[i] == FREE)
93+
{
94+
draw = false;
95+
break;
96+
}
97+
}
98+
if (draw && !win)
99+
printf("It's a draw!\n");
100+
101+
if (win || draw)
102+
current_state = QUIT;
103+
}
104+
void parse_command(char *msg)
105+
{
106+
command = strtok(msg, ":");
107+
arg = strtok(NULL, ":");
108+
}
109+
game_board create_board()
110+
{
111+
game_board board = {1, {FREE}};
112+
return board;
113+
}
114+
void draw()
115+
{
116+
char symbol;
117+
for (int y = 0; y < 3; y++)
118+
{
119+
for (int x = 0; x < 3; x++)
120+
{
121+
if (g_board.objects[y * 3 + x] == FREE)
122+
symbol = y * 3 + x + 1 + '0';
123+
else if (g_board.objects[y * 3 + x] == O)
124+
symbol = 'O';
125+
else
126+
symbol = 'X';
127+
128+
printf(" %c ", symbol);
129+
}
130+
printf("\n_________________________\n");
131+
}
132+
}
133+
void play_game()
134+
{
135+
while (true)
136+
{
137+
if (current_state == START)
138+
{
139+
if (strcmp(arg, "name_taken") == 0)
140+
exit(1);
141+
else if (strcmp(arg, "no_enemy") == 0)
142+
current_state = WAIT_FOR_OPPONENT;
143+
else
144+
{
145+
g_board = create_board();
146+
is_client_O = arg[0] == 'O';
147+
current_state = is_client_O ? MOVE : WAIT_FOR_MOVE;
148+
}
149+
}
150+
151+
else if (current_state == WAIT_FOR_OPPONENT)
152+
{
153+
154+
pthread_mutex_lock(&mutex);
155+
156+
while (current_state != START && current_state != QUIT)
157+
pthread_cond_wait(&cond, &mutex);
158+
159+
pthread_mutex_unlock(&mutex);
160+
161+
g_board = create_board();
162+
is_client_O = arg[0] == 'O';
163+
current_state = is_client_O ? MOVE : WAIT_FOR_MOVE;
164+
}
165+
else if (current_state == WAIT_FOR_MOVE)
166+
{
167+
printf("Waiting for rivals move\n");
168+
169+
pthread_mutex_lock(&mutex);
170+
while (current_state != OPPONENT_MOVE && current_state != QUIT)
171+
{
172+
pthread_cond_wait(&cond, &mutex);
173+
}
174+
pthread_mutex_unlock(&mutex);
175+
}
176+
else if (current_state == OPPONENT_MOVE)
177+
{
178+
int pos = atoi(arg);
179+
move(&g_board, pos);
180+
check_game_status();
181+
if (current_state != QUIT)
182+
{
183+
current_state = MOVE;
184+
}
185+
}
186+
else if (current_state == MOVE)
187+
{
188+
draw();
189+
190+
int pos;
191+
do
192+
{
193+
printf("Next move (%c): ", is_client_O ? 'O' : 'X');
194+
scanf("%d", &pos);
195+
pos--;
196+
} while (!move(&g_board, pos));
197+
198+
draw();
199+
200+
char buffer[MAX_MSG_LEN + 1];
201+
sprintf(buffer, "move:%d:%s", pos, name);
202+
send(server_socket, buffer, MAX_MSG_LEN, 0);
203+
204+
check_game_status();
205+
if (current_state != QUIT)
206+
{
207+
current_state = WAIT_FOR_MOVE;
208+
}
209+
}
210+
else if (current_state == QUIT)
211+
end();
212+
}
213+
}
214+
void connect_local(char *path)
215+
{
216+
server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
217+
218+
struct sockaddr_un sock_addr;
219+
memset(&sock_addr, 0, sizeof(struct sockaddr_un));
220+
sock_addr.sun_family = AF_UNIX;
221+
strcpy(sock_addr.sun_path, path);
222+
223+
if (connect(server_socket, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == -1)
224+
{
225+
printf("Error while connecting to LOCAL socket (%s)\n", strerror(errno));
226+
exit(1);
227+
}
228+
}
229+
void connect_inet(char *port)
230+
{
231+
232+
struct addrinfo *info;
233+
struct addrinfo hints;
234+
memset(&hints, 0, sizeof(struct addrinfo));
235+
hints.ai_family = AF_UNSPEC;
236+
hints.ai_socktype = SOCK_STREAM;
237+
238+
getaddrinfo("localhost", port, &hints, &info);
239+
240+
server_socket = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
241+
242+
if (connect(server_socket, info->ai_addr, info->ai_addrlen) == -1)
243+
{
244+
printf("Error while connecting to INET socket (%s)\n", strerror(errno));
245+
exit(1);
246+
}
247+
248+
freeaddrinfo(info);
249+
}
250+
void listen_server()
251+
{
252+
int game_thread_running = 0;
253+
while (1)
254+
{
255+
recv(server_socket, buffer, MAX_MSG_LEN, 0);
256+
parse_command(buffer);
257+
258+
pthread_mutex_lock(&mutex);
259+
if (strcmp(command, "add") == 0)
260+
{
261+
current_state = START;
262+
if (!game_thread_running)
263+
{
264+
pthread_t t;
265+
pthread_create(&t, NULL, (void *(*)(void *))play_game, NULL);
266+
game_thread_running = 1;
267+
}
268+
}
269+
else if (strcmp(command, "move") == 0)
270+
{
271+
current_state = OPPONENT_MOVE;
272+
}
273+
else if (strcmp(command, "end") == 0)
274+
{
275+
current_state = QUIT;
276+
exit(0);
277+
}
278+
else if (strcmp(command, "ping") == 0)
279+
{
280+
sprintf(buffer, "pong: :%s", name);
281+
send(server_socket, buffer, MAX_MSG_LEN, 0);
282+
}
283+
pthread_cond_signal(&cond);
284+
pthread_mutex_unlock(&mutex);
285+
}
286+
}
287+
288+
int main(int argc, char *argv[])
289+
{
290+
291+
if (argc < 4)
292+
{
293+
printf("Wrong number of arguments!\n");
294+
exit(1);
295+
}
296+
297+
name = argv[1];
298+
299+
// handle SIGINT
300+
signal(SIGINT, end);
301+
302+
// connection method - inet/unix
303+
if (strcmp(argv[2], "unix") == 0)
304+
{
305+
char *path = argv[3];
306+
connect_local(path);
307+
}
308+
309+
else if (strcmp(argv[2], "inet") == 0)
310+
{
311+
char *port = argv[3];
312+
connect_inet(port);
313+
}
314+
315+
else
316+
{
317+
printf("Wrong method - choose [inet] or [unix]!\n");
318+
exit(1);
319+
}
320+
321+
char msg[MAX_MSG_LEN];
322+
sprintf(msg, "add: :%s", name);
323+
send(server_socket, msg, MAX_MSG_LEN, 0);
324+
325+
// listen_for_msg server
326+
listen_server();
327+
328+
return 0;
329+
}

lab10/src/common.h

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//
2+
// Created by sylwia on 5/26/21.
3+
//
4+
5+
#ifndef LAB10_COMMON_H
6+
#define LAB10_COMMON_H
7+
8+
#include <netdb.h>
9+
#include <poll.h>
10+
#include <pthread.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <string.h>
14+
#include <sys/socket.h>
15+
#include <sys/un.h>
16+
#include <time.h>
17+
#include <unistd.h>
18+
#include <errno.h>
19+
#include <signal.h>
20+
#include <stdbool.h>
21+
#include <arpa/inet.h>
22+
23+
#define MAX_CLIENTS 10
24+
#define MAX_MSG_LEN 256
25+
26+
typedef struct
27+
{
28+
char *name;
29+
int fd;
30+
bool available;
31+
int opponent_idx;
32+
} client;
33+
34+
typedef enum
35+
{
36+
START,
37+
WAIT_FOR_OPPONENT,
38+
WAIT_FOR_MOVE,
39+
OPPONENT_MOVE,
40+
MOVE,
41+
QUIT
42+
} state;
43+
44+
typedef enum
45+
{
46+
FREE,
47+
O,
48+
X
49+
} sign;
50+
51+
typedef struct
52+
{
53+
int move;
54+
sign objects[9];
55+
56+
} game_board;
57+
58+
#endif // LAB10_COMMON_H

0 commit comments

Comments
 (0)