Initial commit

This commit is contained in:
Maksymilian Wilczyński committed 2025-05-07 18:47:04 +02:00
commit f4a3463df1
20 files changed
+16475

No files matched your search

+223
View File
@@ -0,0 +1,223 @@
#include <iostream>
#include <vector>
#include <string>
#include <random>
#include <algorithm>
#include <limits>
#include <fmt/core.h>
#include <fmt/color.h>
enum class Color { Red, Green, Blue, Yellow };
std::string colorToString(Color c) {
switch (c) {
case Color::Red: return "Red";
case Color::Green: return "Green";
case Color::Blue: return "Blue";
case Color::Yellow: return "Yellow";
default: return "Unknown";
}
}
struct Card {
Color color;
int number;
void print() const {
fmt::color fmt_color;
switch (color) {
case Color::Red: fmt_color = fmt::color::red; break;
case Color::Green: fmt_color = fmt::color::green; break;
case Color::Blue: fmt_color = fmt::color::blue; break;
case Color::Yellow: fmt_color = fmt::color::yellow; break;
}
fmt::print(fmt::fg(fmt_color), "[{} {}] ", colorToString(color), number);
}
bool matches(const Card& other) const {
return color == other.color || number == other.number;
}
};
std::vector<Card> createDeck() {
std::vector<Card> deck;
for (int c = 0; c < 4; ++c) {
for (int n = 0; n <= 9; ++n) {
// Two of each card (except 0 which appears once)
deck.push_back({ static_cast<Color>(c), n });
if (n != 0) deck.push_back({ static_cast<Color>(c), n });
}
}
std::shuffle(deck.begin(), deck.end(), std::mt19937{ std::random_device{}() });
return deck;
}
Card drawCard(std::vector<Card>& deck) {
if (deck.empty()) throw std::runtime_error("Deck is empty!");
Card c = deck.back();
deck.pop_back();
return c;
}
void printHand(const std::vector<Card>& hand) {
for (size_t i = 0; i < hand.size(); ++i) {
fmt::print("[{}] ", i);
hand[i].print();
fmt::print("\n");
}
}
bool hasPlayableCard(const std::vector<Card>& hand, const Card& topCard) {
for (const auto& card : hand) {
if (card.matches(topCard)) return true;
}
return false;
}
void clearScreen() {
#ifdef _WIN32
std::system("cls");
#else
std::system("clear");
#endif
}
std::string rightAlign(std::string text, size_t width = 50) {
if (text.length() >= width) return text;
return std::string(width - text.length(), ' ') + text;
}
int main() {
auto deck = createDeck();
std::vector<Card> playerHand, aiHand;
for (int i = 0; i < 7; ++i) {
playerHand.push_back(drawCard(deck));
aiHand.push_back(drawCard(deck));
}
Card topCard = drawCard(deck);
bool playerTurn = true;
while (true) {
clearScreen();
// Prepare UNO! labels if needed
std::string playerUno = (playerHand.size() == 1) ? rightAlign(fmt::format(fmt::emphasis::bold, "YOU: UNO!")) : "";
std::string aiUno = (aiHand.size() == 1) ? rightAlign(fmt::format(fmt::emphasis::bold, "AI: UNO!")) : "";
// Print top card and UNO! indicator
fmt::print("Top card: ");
topCard.print();
if (!playerUno.empty()) fmt::print("{}", playerUno);
if (!aiUno.empty()) fmt::print("{}", aiUno);
fmt::print("\n");
fmt::print("AI has {} card(s).\n\n", aiHand.size());
if (playerHand.empty()) {
fmt::print(fmt::fg(fmt::color::green), "You win!\n");
break;
}
if (aiHand.empty()) {
fmt::print(fmt::fg(fmt::color::red), "AI wins!\n");
break;
}
if (deck.empty()) {
fmt::print(fmt::fg(fmt::color::gray), "Deck is empty! Reshuffling...\n");
deck = createDeck(); // not perfect, doesn’t exclude cards in play
}
if (playerTurn) {
fmt::print(fmt::fg(fmt::color::cyan), "Your turn:\n");
printHand(playerHand);
if (!hasPlayableCard(playerHand, topCard)) {
fmt::print("No playable card. Press 'd' to draw: ");
char input;
std::cin >> input;
if (input == 'd' || input == 'D') {
playerHand.push_back(drawCard(deck));
Card drawn = drawCard(deck);
playerHand.push_back(drawn);
fmt::print("You drew: ");
drawn.print();
fmt::print("\nPress Enter to continue...");
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
playerTurn = false;
continue;
}
}
else {
while (true) {
fmt::print("Choose card index to play or 'd' to draw: ");
std::string input;
std::cin >> input;
if (input == "d" || input == "D") {
playerHand.push_back(drawCard(deck));
fmt::print("You drew a card. ");
fmt::print("Press Enter to continue...");
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
playerTurn = false;
break;
}
try {
int choice = std::stoi(input);
if (choice >= 0 && choice < static_cast<int>(playerHand.size())) {
if (playerHand[choice].matches(topCard)) {
topCard = playerHand[choice];
playerHand.erase(playerHand.begin() + choice);
playerTurn = false;
break;
}
else {
fmt::print("Invalid move. You must match color or number.\n");
}
}
else {
fmt::print("Invalid index.\n");
}
}
catch (...) {
fmt::print("Invalid input.\n");
}
}
}
}
else {
fmt::print(fmt::fg(fmt::color::yellow), "AI's turn...\n");
bool played = false;
for (size_t i = 0; i < aiHand.size(); ++i) {
if (aiHand[i].matches(topCard)) {
topCard = aiHand[i];
aiHand.erase(aiHand.begin() + i);
fmt::print("AI played: ");
topCard.print();
fmt::print("\n");
played = true;
break;
}
}
if (!played) {
aiHand.push_back(drawCard(deck));
fmt::print("AI drew a card.\n");
}
fmt::print("Press Enter to continue...");
if (played)
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
playerTurn = true;
}
}
return 0;
}