offload helper functions to Utils, use Getline (which works everywhere) instead of cin

This commit is contained in:
2025-01-26 19:09:12 +01:00
parent 2d9ee6f956
commit 925d566177
8 changed files with 311 additions and 57 deletions

View File

@@ -164,19 +164,12 @@ void Board::smartSleep(int millis) {
}
}
void Board::_thread_wait_for_str_cin(bool &done, std::string &text) {
std::string result;
std::cin >> result;
text = result;
done = true;
}
std::string Board::asyncStrCin() {
bool done = false;
std::string text;
std::thread t(&Board::_thread_wait_for_str_cin, Board(), std::ref(done), std::ref(text));
// std::thread t(&Board::_thread_wait_for_str_cin, Board(), std::ref(done), std::ref(text));
std::thread t(_thread_wait_for_str_cin, std::ref(done), std::ref(text));
while(t.joinable()) {
this->update();
@@ -188,6 +181,71 @@ std::string Board::asyncStrCin() {
}
std::string Board::asyncStrGetline() {
bool done = false;
std::string text;
// std::thread t(&Board::_thread_wait_for_str_getline, Board(), std::ref(done), std::ref(text));
std::thread t(_thread_wait_for_str_getline, std::ref(done), std::ref(text));
while(t.joinable()) {
this->update();
this->render();
if (done) t.join();
}
return text;
}
void Board::selectAField(short &pickStatus, short &field) {
sf::Vector2i mousePosition;
sf::Vector2f mapped;
while (this->manualUpdate()) {
sf::Event currentEvent = this->lastEvent;
switch (currentEvent.type) {
case sf::Event::Closed:
this->closeWindow();
// Zamknięcie okna powinno wyjść z tej pętli
pickStatus = 8;
break;
case sf::Event::MouseButtonPressed:
// Informacje musimy pobrać przy naciśnięciu,
// ponieważ użytkownik może zwolnić przycisk poza oknem gry.
mousePosition = sf::Mouse::getPosition(*this->window);
mapped = this->window->mapPixelToCoords(mousePosition, this->view);
field = static_cast<short>(mapped.y / 100) * 11 + static_cast<short>(mapped.x / 100);
pickStatus = 4;
break;
case sf::Event::MouseButtonReleased:
if (pickStatus == 4) {
mousePosition = sf::Mouse::getPosition(*this->window);
mapped = this->window->mapPixelToCoords(mousePosition, this->view);
if (mapped.x >= 0 && mapped.x <= 1100 && mapped.y >= 0 && mapped.y <= 1100) {
// Wyznacz ponownie field, na wypadek jeśli użytkownik zmienił zdanie
field = static_cast<short>(mapped.y / 100) * 11 + static_cast<short>(mapped.x / 100);
}
pickStatus = 8;
}
break;
case sf::Event::Resized:
std::cout << "resized triggered: " << currentEvent.size.width << " " << currentEvent.size.height << "\n";
this->handleResize(currentEvent.size.width, currentEvent.size.height);
break;
}
}
}
void Board::closeWindow() {
this->window->close();

View File

@@ -4,6 +4,7 @@
#include <SFML/Graphics.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Time.hpp>
#include "Utils.hpp"
class Board {
@@ -16,7 +17,8 @@ class Board {
sf::Texture boardTexture;
sf::Sprite boardSprite;
void _thread_wait_for_str_cin(bool &done, std::string &text);
// void _thread_wait_for_str_cin(bool &done, std::string &text);
// void _thread_wait_for_str_getline(bool& done, std::string& text);
public:
@@ -47,5 +49,7 @@ class Board {
void smartSleep(int millis);
void handleResize(unsigned int newWidth, unsigned int newHeight);
std::string asyncStrCin();
std::string asyncStrGetline();
void selectAField(short &pickStatus, short &field);
};

View File

@@ -143,6 +143,7 @@
<ClCompile Include="main.cpp" />
<ClCompile Include="Pawn.cpp" />
<ClCompile Include="Player.cpp" />
<ClCompile Include="Utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Board.hpp" />
@@ -151,6 +152,7 @@
<ClInclude Include="Pawn.hpp" />
<ClInclude Include="Player.hpp" />
<ClInclude Include="ssp.hpp" />
<ClInclude Include="Utils.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -33,6 +33,9 @@
<ClCompile Include="Board.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Game.hpp">
@@ -53,5 +56,8 @@
<ClInclude Include="Board.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -83,7 +83,8 @@ void Engine::nextTurn() {
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// std::cin >> choice;
choice = board.asyncStrCin();
// std::cin.sync();
choice = this->board.asyncStrGetline();
choice[0] |= 32;
if (choice[0] == 'a') {
@@ -137,44 +138,19 @@ void Engine::nextTurn() {
}
// Użytkownik wybiera pionek na planszy, którym chce się ruszyć
int pickStatus = 0;
short pickStatus = 0;
short selectedField = -1;
if (currentPlayer.pawnsActive == 0 || !pickAPlace) pickStatus = 8; // pomiń pętlę
while (pickStatus != 8) {
while (board.manualUpdate()) {
this->board.selectAField(pickStatus, selectedField);
sf::Event currentEvent = board.lastEvent;
//std::cout << "currentEvent.type: " << currentEvent.type << "\n";
switch (currentEvent.type) {
}
case sf::Event::Closed:
board.closeWindow();
// Zamknięcie okna powinno wyjść z tej pętli
pickStatus = 8;
break;
std::cout << "(Engine.cpp) selected: " << selectedField << "\n";
case sf::Event::MouseButtonPressed:
std::cout << "pretend i'm selecting a piece\n";
pickStatus = 4;
break;
case sf::Event::MouseButtonReleased:
if (pickStatus == 4) {
std::cout << "pretend i'm releasing a piece\n";
this->pawnmoveBuffer.play();
this->board.smartSleep(1000);
pickStatus = 8;
}
break;
case sf::Event::Resized:
std::cout << "resized triggered: " << currentEvent.size.width << " " << currentEvent.size.height << "\n";
board.handleResize(currentEvent.size.width, currentEvent.size.height);
break;
}
}
}
// TEST
// currentPlayer.tryMovingPawn(0, 0);

View File

@@ -6,6 +6,7 @@
#include <filesystem> // sprawdzenie, czy plik istnieje
#include "ssp.hpp" // nagłówkowy parser plików .csv
#include "Engine.hpp"
#include "Utils.hpp"
void Game::printGameWelcomeText() const {
@@ -19,6 +20,12 @@ void Game::printGameWelcomeText() const {
"\n";
std::cout << "Witaj w Chinczyku!\nAutor: B.Z. (2 EF-DI, L01, 177188)\n";
#ifdef CHINCZYK188_IGNORE_USER_SEED
std::cout << "Wersja gry bez losowania deterministycznym ziarnem (z -DCHINCZYK188_IGNORE_USER_SEED).\n";
#endif
#ifndef CHINCZYK188_IGNORE_USER_SEED
std::cout << "Wersja gry z losowaniem deterministycznym ziarnem (bez -DCHINCZYK188_IGNORE_USER_SEED).\n";
#endif
std::cout << "Kod zrodlowy: https://gitea.7o7.cx/sherl/Chinczyk188 na licencji GPLv3\n";
std::cout << "Instrukcja gry powinna zostac dolaczona do tej kopii gry, w przeciwnym razie\n"
"jest ona dostepna w repozytorium git.\n\n";
@@ -170,13 +177,6 @@ void Game::initVariables() {
}
Game::Game() {
//:
// thread(std::thread([this]() {
// while (this->running()) {
// this->update();
// this->render();
// sf::sleep(sf::milliseconds(100));
// } })) {
// Konstruktor klasy. Klasę Game tworzymy poprzez
// ustawienie domyślnych wartości i stworzenie okna.
@@ -221,7 +221,7 @@ void Game::run() {
int numPlayers = 2;
std::cout << "Podaj prosze liczbe graczy (2-4):\n> ";
// std::cin >> numPlayers;
numPlayers = stoi(board.asyncStrCin());
numPlayers = stoi(removeWhitespace(board.asyncStrGetline()));
std::cout << "\n";
if (numPlayers < 2) numPlayers = 2;
@@ -236,18 +236,19 @@ void Game::run() {
std::cout << "Wpisz nazwe gracza " << (i + 1) << " (" << colorNames[i] << "): ";
//std::cin >> name;
name = board.asyncStrCin();
name = board.asyncStrGetline();
name = removeWhitespace(name);
// Zignoruj zawartość bufora do \n, aby zapobiec nadpisywaniu ziarna
// poprzez podanie nazwy ze znakami białymi.
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// std::cin.sync();
#ifndef CHINCZYK188_IGNORE_USER_SEED
// Jeżeli nie została zdefiniowana flaga do ignorowania ziarna użytkownika
// (deterministyczne losowanie), to pozwól na wprowadzanie ziaren.
std::cout << "Wpisz ziarno gracza " << (i + 1) << " (" << colorNames[i] << "): ";
str_seed = board.asyncStrCin();
// std::cin >> str_seed;
str_seed = board.asyncStrGetline();
#endif
std::cout << "\n";
@@ -258,7 +259,8 @@ void Game::run() {
board.updateAndRender();
// Podobnie, jak wyżej
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// std::cin.sync();
}

198
Chinczyk188/Utils.cpp Normal file
View File

@@ -0,0 +1,198 @@
#include "Utils.hpp"
/**
* @brief Removes spaces.
*
* @param[in] str The string
*
* @return String without spaces
*/
std::string removeSpaces(std::string str) {
std::string cleanStr;
for (int i = 0; i < str.size(); i++) {
if (str[i] != ' ') cleanStr += str[i];
}
return cleanStr;
}
/**
* @brief Removes whitespace.
*
* @param[in] str The string
*
* @return String without whitespace
*/
std::string removeWhitespace(std::string str) {
std::string cleanStr;
for (int i = 0; i < str.size(); i++) {
switch (str[i]) {
case ' ':
break;
case '\t':
break;
case '\n':
break;
default:
cleanStr += str[i];
}
}
return cleanStr;
}
void _thread_wait_for_str_cin(bool &done, std::string &text) {
std::string result;
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin >> result;
// std::cin.sync(); // działa z kompilatorem mingw (g++), ale nie MSVC
text = result;
done = true;
}
void _thread_wait_for_str_getline(bool& done, std::string& text) {
std::string result;
std::getline(std::cin, result);
text = result;
done = true;
}
short paths[4][44] = {
// czerwony
{
114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 104, 93, 82, 71
},
// niebieski
{
6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 16, 27, 38, 49
},
// żółty
{
44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 56, 57, 58, 59
},
// zielony
{
76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 64, 63, 62, 61
}
};
short red_path[44] = {
114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 104, 93, 82, 71
};
short blue_path[44] = {
6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 16, 27, 38, 49
};
short yellow_path[44] = {
44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 56, 57, 58, 59
};
short green_path[44] = {
76,
75, 74, 73, 72,
83, 94, 105, 116,
115, 114,
103, 92, 81, 70,
69, 68, 67, 66,
55, 44,
45, 46, 47, 48,
37, 26, 15, 4,
5, 6,
17, 28, 39, 50,
51, 52, 53, 54,
65, 64, 63, 62, 61
};

8
Chinczyk188/Utils.hpp Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <string>
#include <iostream>
std::string removeSpaces(std::string str);
std::string removeWhitespace(std::string str);
void _thread_wait_for_str_cin(bool &done, std::string &text);
void _thread_wait_for_str_getline(bool& done, std::string& text);