Skip to content

Commit 4ad3049

Browse files
Integrated implementation of the NDS final project from
Ertug Obalar, Jens Patzelt and Milad Tousi
1 parent 18b9bd5 commit 4ad3049

20 files changed

+640
-202
lines changed

TikTakToe/TikTakToeGameModel.cpp

Lines changed: 111 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
* tiktaktoe - a game using SnodeC
3-
* Copyright (C) 2021 Volker Christian <[email protected]>
2+
* TikTakToe - a demo game using the snode.c framework
3+
* Copyright (C) 2020, 2021 Volker Christian <[email protected]>
4+
* Copyright (C) 2021 Ertug Obalar, Jens Patzelt and Milad Tousi
45
*
56
* This program is free software: you can redistribute it and/or modify
6-
* it under the terms of the GNU Lesser General Public License as published
7+
* it under the terms of the GNU General Public License as published
78
* by the Free Software Foundation, either version 3 of the License, or
89
* (at your option) any later version.
910
*
@@ -18,44 +19,138 @@
1819

1920
#include "TikTakToeGameModel.h"
2021

22+
#include <log/Logger.h>
2123
#include <map> // for operator==
2224
#include <nlohmann/json.hpp> // for basic_json<>::object_t, basic_json<>::v...
2325

2426
TikTakToeGameModel TikTakToeGameModel::gameModel;
2527

26-
void TikTakToeGameModel::playersMove(const std::string& player, int cellID) {
28+
void TikTakToeGameModel::playersMove(const std::string& player, int cell) {
2729
if (player == players[whosNext]) {
28-
int cellValue = 0;
30+
board[cell] = whosNext == 0 ? 1 : -1;
2931

30-
if (player == "red") {
31-
cellValue = 1;
32-
} else if (player == "blue") {
33-
cellValue = -1;
32+
switch (checkState(board)) {
33+
case 1:
34+
state = "update";
35+
break;
36+
37+
case 2:
38+
state = "tie";
39+
score[1]++;
40+
break;
41+
42+
case 3:
43+
state = "win";
44+
if (whosNext == 0)
45+
score[0]++;
46+
else
47+
score[2]++;
48+
winner = player;
49+
break;
50+
}
51+
52+
whosNext = whosNext == 0 ? 1 : 0;
53+
}
54+
}
55+
56+
int TikTakToeGameModel::checkState(int board[]) {
57+
int count = 0;
58+
59+
// Horizontal Win Check
60+
for (int i = 0; i < 3; i++) {
61+
for (int j = 0; j < 3; j++) {
62+
count += board[i * 3 + j];
63+
}
64+
65+
if (count == 3 || count == -3) {
66+
for (int j = 0; j < 3; j++) {
67+
board[i * 3 + j] *= 2;
68+
}
69+
70+
return 3;
71+
} else {
72+
count = 0;
73+
}
74+
}
75+
76+
// Vertical Win Check
77+
for (int i = 0; i < 3; i++) {
78+
for (int j = 0; j < 3; j++) {
79+
count += board[i + j * 3];
80+
}
81+
82+
if (count == 3 || count == -3) {
83+
for (int j = 0; j < 3; j++) {
84+
board[i + j * 3] *= 2;
85+
}
86+
87+
return 3;
88+
} else {
89+
count = 0;
90+
}
91+
}
92+
93+
// Left Diagonal Win Check
94+
{
95+
for (int i = 0; i < 3; i++) {
96+
count += board[i * 4];
3497
}
3598

36-
board[cellID] = cellValue;
99+
if (count == 3 || count == -3) {
100+
for (int i = 0; i < 3; i++) {
101+
board[i * 4] *= 2;
102+
}
37103

38-
if (whosNext >= 1) {
39-
whosNext = 0;
104+
return 3;
40105
} else {
41-
whosNext += 1;
106+
count = 0;
42107
}
43108
}
109+
110+
// Right Diagonal Win Check
111+
{
112+
for (int i = 0; i < 3; i++) {
113+
count += board[i * 2 + 2];
114+
}
115+
116+
if (count == 3 || count == -3) {
117+
for (int i = 0; i < 3; i++) {
118+
board[i * 2 + 2] *= 2;
119+
}
120+
121+
return 3;
122+
} else {
123+
count = 0;
124+
}
125+
}
126+
127+
// Ongoing Check
128+
for (int i = 0; i < 9; i++) {
129+
if (board[i] == 0)
130+
return 1;
131+
}
132+
133+
// Return Tie
134+
return 2;
44135
}
45136

46137
void TikTakToeGameModel::resetBoard() {
47-
whosNext = 0;
48138
for (int i = 0; i < 9; i++) {
49139
board[i] = 0;
50140
}
141+
142+
state = "reset";
143+
winner = "";
51144
}
52145

53146
nlohmann::json TikTakToeGameModel::updateClientState() {
54147
nlohmann::json message;
55148

56-
message["type"] = "update";
57-
message["whosTurn"] = players[whosNext];
58149
message["board"] = board;
150+
message["score"] = score;
151+
message["state"] = state;
152+
message["winner"] = winner;
153+
message["leader"] = players[whosNext];
59154

60155
return message;
61156
}

TikTakToe/TikTakToeGameModel.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
* tiktaktoe - a game using SnodeC
3-
* Copyright (C) 2021 Volker Christian <[email protected]>
2+
* TikTakToe - a demo game using the snode.c framework
3+
* Copyright (C) 2020, 2021 Volker Christian <[email protected]>
4+
* Copyright (C) 2021 Ertug Obalar, Jens Patzelt and Milad Tousi
45
*
56
* This program is free software: you can redistribute it and/or modify
6-
* it under the terms of the GNU Lesser General Public License as published
7+
* it under the terms of the GNU General Public License as published
78
* by the Free Software Foundation, either version 3 of the License, or
89
* (at your option) any later version.
910
*
@@ -19,29 +20,35 @@
1920
#ifndef TIKTAKTOEGAMEMODEL_H
2021
#define TIKTAKTOEGAMEMODEL_H
2122

22-
#include <nlohmann/json_fwd.hpp> // for json
23+
#include <nlohmann/json_fwd.hpp>
2324
#include <string>
2425

2526
class TikTakToeGameModel {
2627
protected:
2728
TikTakToeGameModel() = default;
2829

2930
public:
30-
void playersMove(const std::string& player, int cellID);
31+
void playersMove(const std::string& player, int cell);
3132
void resetBoard();
33+
int checkState(int board[]);
34+
3235
nlohmann::json updateClientState();
3336

3437
static TikTakToeGameModel& getGameModel();
3538

3639
protected:
37-
std::string players[2] = {"red", "blue"};
40+
std::string players[2] = {"player_1", "player_2"};
41+
std::string winner = "";
42+
std::string state = "setup";
43+
44+
int board[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
45+
int score[3] = {0, 0, 0};
3846
int whosNext = 0;
3947
int numPlayers = 0;
40-
int board[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
4148

4249
friend class TikTakToeSubProtocol;
4350

4451
static TikTakToeGameModel gameModel;
4552
};
4653

47-
#endif // TIKTAKTOEGAMEMODEL_H
54+
#endif

TikTakToe/TikTakToeSubProtocol.cpp

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
* tiktaktoe - a game using SnodeC
3-
* Copyright (C) 2021 Volker Christian <[email protected]>
2+
* TikTakToe - a demo game using the snode.c framework
3+
* Copyright (C) 2020, 2021 Volker Christian <[email protected]>
4+
* Copyright (C) 2021 Ertug Obalar, Jens Patzelt and Milad Tousi
45
*
56
* This program is free software: you can redistribute it and/or modify
6-
* it under the terms of the GNU Lesser General Public License as published
7+
* it under the terms of the GNU General Public License as published
78
* by the Free Software Foundation, either version 3 of the License, or
89
* (at your option) any later version.
910
*
@@ -22,8 +23,9 @@
2223
#include "config.h"
2324

2425
#include <log/Logger.h>
25-
#include <net/timer/IntervalTimer.h> // for IntervalTimer
2626
#include <nlohmann/json.hpp>
27+
#include <web/http/server/Request.h>
28+
#include <web/http/server/Response.h>
2729

2830
TikTakToeSubProtocol::TikTakToeSubProtocol(const std::string& name, TikTakToeGameModel& gameModel)
2931
: web::websocket::server::SubProtocol(name)
@@ -45,55 +47,58 @@ TikTakToeSubProtocol::~TikTakToeSubProtocol() {
4547
}
4648

4749
void TikTakToeSubProtocol::onConnected() {
48-
VLOG(0) << "TikTakToe on connected:";
50+
// VLOG(0) << "TikTakToe on connected:";
4951

50-
VLOG(0) << "\tServer: " + getLocalAddressAsString();
51-
VLOG(0) << "\tClient: " + getRemoteAddressAsString();
52+
// VLOG(0) << "\tServer: " + getLocalAddressAsString();
53+
// VLOG(0) << "\tClient: " + getRemoteAddressAsString();
5254

53-
VLOG(0) << "\tNumPlayers: " << gameModel.numPlayers;
55+
// VLOG(0) << "\tNumPlayers: " << gameModel.numPlayers;
5456

5557
if (gameModel.numPlayers < 2) {
5658
nlohmann::json json;
5759

58-
json["type"] = "setup";
59-
json["playerData"]["whosTurn"] = gameModel.players[gameModel.whosNext];
60-
json["playerData"]["playerID"] = gameModel.players[gameModel.numPlayers++];
61-
json["playerData"]["board"] = gameModel.board;
62-
63-
VLOG(0) << "Json: " << json.dump();
60+
json["board"] = gameModel.board;
61+
json["score"] = gameModel.score;
62+
json["state"] = gameModel.state;
63+
json["winner"] = gameModel.winner;
64+
json["leader"] = gameModel.players[gameModel.whosNext];
65+
json["player"] = gameModel.players[gameModel.numPlayers++];
6466

6567
sendMessage(json.dump());
66-
6768
activePlayer = true;
69+
70+
VLOG(0) << "JSON: " << json.dump();
6871
} else {
6972
sendClose();
73+
74+
VLOG(0) << "sendClose";
7075
}
7176
}
7277

73-
void TikTakToeSubProtocol::onMessageStart(int opCode) {
74-
VLOG(0) << "TikTakToe on Message Start - OpCode: " << opCode;
78+
void TikTakToeSubProtocol::onMessageStart([[maybe_unused]] int opCode) {
79+
// VLOG(0) << "TikTakToe on Message Start - OpCode: " << opCode;
7580
}
7681

77-
void TikTakToeSubProtocol::onMessageData(const char* junk, std::size_t junkLen) {
82+
void TikTakToeSubProtocol::onMessageData(const char* junk, size_t junkLen) {
7883
data += std::string(junk, junkLen);
7984
}
8085

8186
void TikTakToeSubProtocol::onMessageEnd() {
82-
VLOG(0) << "TikTakToe on Data: " << data;
87+
// VLOG(0) << "TikTakToe on Data: " << data;
8388

8489
nlohmann::json action = nlohmann::json::parse(data);
8590

8691
VLOG(0) << "Action dump: " << action.dump();
8792

8893
if (action["type"] == "move") {
89-
gameModel.playersMove(action["playerID"], action["cellID"]);
94+
gameModel.playersMove(action["player"], action["cell"]);
9095
nlohmann::json message = gameModel.updateClientState();
9196

92-
/* // also possible
93-
forEachClient([&message](SubProtocol* client) {
94-
client->sendMessage(message.dump());
95-
});
96-
*/
97+
sendBroadcast(message.dump());
98+
VLOG(0) << "SendMessage Dump: " << message.dump();
99+
} else if (action["type"] == "reset") {
100+
gameModel.resetBoard();
101+
nlohmann::json message = gameModel.updateClientState();
97102

98103
sendBroadcast(message.dump());
99104
VLOG(0) << "SendMessage Dump: " << message.dump();
@@ -107,12 +112,12 @@ void TikTakToeSubProtocol::onMessageError(uint16_t errnum) {
107112
}
108113

109114
void TikTakToeSubProtocol::onPongReceived() {
110-
VLOG(0) << "TikTakToe on Pong received";
115+
// VLOG(0) << "TikTakToe on Pong received";
111116
flyingPings = 0;
112117
}
113118

114119
void TikTakToeSubProtocol::onDisconnected() {
115-
VLOG(0) << "TikTakToe on disconnected:";
120+
// VLOG(0) << "TikTakToe on disconnected:";
116121

117122
if (activePlayer) {
118123
gameModel.numPlayers--;
@@ -122,6 +127,6 @@ void TikTakToeSubProtocol::onDisconnected() {
122127
}
123128
}
124129

125-
VLOG(0) << "\tServer: " + getLocalAddressAsString();
126-
VLOG(0) << "\tClient: " + getRemoteAddressAsString();
130+
// VLOG(0) << "\tServer: " + getLocalAddressAsString();
131+
// VLOG(0) << "\tClient: " + getRemoteAddressAsString();
127132
}

TikTakToe/TikTakToeSubProtocol.h

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
* tiktaktoe - a game using SnodeC
3-
* Copyright (C) 2021 Volker Christian <[email protected]>
2+
* TikTakToe - a demo game using the snode.c framework
3+
* Copyright (C) 2020, 2021 Volker Christian <[email protected]>
4+
* Copyright (C) 2021 Ertug Obalar, Jens Patzelt and Milad Tousi
45
*
56
* This program is free software: you can redistribute it and/or modify
6-
* it under the terms of the GNU Lesser General Public License as published
7+
* it under the terms of the GNU General Public License as published
78
* by the Free Software Foundation, either version 3 of the License, or
89
* (at your option) any later version.
910
*
@@ -21,12 +22,9 @@
2122

2223
class TikTakToeGameModel;
2324

25+
#include <net/timer/IntervalTimer.h>
2426
#include <web/websocket/server/SubProtocol.h>
2527

26-
namespace net::timer {
27-
class Timer;
28-
} // namespace net::timer
29-
3028
class TikTakToeSubProtocol : public web::websocket::server::SubProtocol {
3129
public:
3230
TikTakToeSubProtocol(const std::string& name, TikTakToeGameModel& game);
@@ -35,7 +33,7 @@ class TikTakToeSubProtocol : public web::websocket::server::SubProtocol {
3533

3634
void onConnected() override;
3735
void onMessageStart(int opCode) override;
38-
void onMessageData(const char* junk, std::size_t junkLen) override;
36+
void onMessageData(const char* junk, size_t junkLen) override;
3937
void onMessageEnd() override;
4038
void onMessageError(uint16_t errnum) override;
4139
void onPongReceived() override;
@@ -48,11 +46,9 @@ class TikTakToeSubProtocol : public web::websocket::server::SubProtocol {
4846

4947
int flyingPings = 0;
5048

51-
const std::string name;
52-
5349
TikTakToeGameModel& gameModel;
5450

5551
net::timer::Timer& timer;
5652
};
5753

58-
#endif // TIKTAKTOESUBPROTOCOL_H
54+
#endif

0 commit comments

Comments
 (0)