Initial commit
This commit is contained in:
commit
f4a3463df1
20 files changed
+16475
No files matched your search
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user