Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SFML/Graphics.hpp>
- #include <iostream>
- #include <vector>
- #include <iomanip>
- #include <fstream>
- const int SIZE = 8;
- const int TILE_SIZE = 80;
- const int WINDOW_SIZE = SIZE * TILE_SIZE;
- const sf::Color LIGHT_COLOR = sf::Color(0xFA, 0xFA, 0xFA); // light purple
- const sf::Color DARK_COLOR = sf::Color(0xE6, 0xB0, 0xE6); // dark purple
- const sf::Color HIGHLIGHT_COLOR = sf::Color(0x93, 0x70, 0xDB, 128); // semi-transparent purple
- const sf::Color KNIGHT_COLOR = sf::Color(0x80, 0x00, 0x80); // dark purple
- sf::Vector2i knightPosition = { -1, -1 };
- std::vector<sf::Vector2i> knightMoves;
- std::vector<sf::Vector2i> moveHistory;
- bool visited[SIZE][SIZE] = { false };
- int moveCounter[SIZE][SIZE] = { 0 };
- int moveNumber = 1;
- float bestTime = -1.0f;
- bool gameStarted = false;
- bool gameOver = false;
- bool isMoveValid(int x, int y) {
- return x >= 0 && x < SIZE && y >= 0 && y < SIZE && !visited[x][y];
- }
- std::vector<sf::Vector2i> getValidMoves(sf::Vector2i pos) {
- std::vector<sf::Vector2i> moves;
- int dx[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
- int dy[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
- for (int i = 0; i < 8; ++i) {
- int newX = pos.x + dx[i];
- int newY = pos.y + dy[i];
- if (isMoveValid(newX, newY)) {
- moves.push_back({ newX, newY });
- }
- }
- return moves;
- }
- bool isMoveInValidMoves(const sf::Vector2i& pos) {
- for (const auto& move : knightMoves) {
- if (move == pos) {
- return true;
- }
- }
- return false;
- }
- bool isGameOver() {
- for (int i = 0; i < SIZE; ++i) {
- for (int j = 0; j < SIZE; ++j) {
- if (!visited[i][j]) {
- return false;
- }
- }
- }
- return true;
- }
- void drawKnight(sf::RenderWindow& window, sf::Vector2i position) {
- sf::RectangleShape body(sf::Vector2f(TILE_SIZE * 0.6f, TILE_SIZE * 0.3f));
- body.setFillColor(KNIGHT_COLOR);
- body.setPosition(position.x * TILE_SIZE + TILE_SIZE * 0.2f, position.y * TILE_SIZE + TILE_SIZE * 0.4f);
- sf::CircleShape head(TILE_SIZE * 0.2f);
- head.setFillColor(KNIGHT_COLOR);
- head.setPosition(position.x * TILE_SIZE + TILE_SIZE * 0.4f, position.y * TILE_SIZE + TILE_SIZE * 0.1f);
- sf::RectangleShape ear1(sf::Vector2f(TILE_SIZE * 0.05f, TILE_SIZE * 0.1f));
- ear1.setFillColor(KNIGHT_COLOR);
- ear1.setPosition(position.x * TILE_SIZE + TILE_SIZE * 0.35f, position.y * TILE_SIZE + TILE_SIZE * 0.1f);
- sf::RectangleShape ear2(sf::Vector2f(TILE_SIZE * 0.05f, TILE_SIZE * 0.1f));
- ear2.setFillColor(KNIGHT_COLOR);
- ear2.setPosition(position.x * TILE_SIZE + TILE_SIZE * 0.6f, position.y * TILE_SIZE + TILE_SIZE * 0.1f);
- window.draw(body);
- window.draw(head);
- window.draw(ear1);
- window.draw(ear2);
- }
- void drawBoard(sf::RenderWindow& window, sf::Font& font, float timer) {
- window.clear();
- for (int i = 0; i < SIZE; ++i) {
- for (int j = 0; j < SIZE; ++j) {
- sf::RectangleShape tile(sf::Vector2f(TILE_SIZE, TILE_SIZE));
- tile.setPosition(i * TILE_SIZE, j * TILE_SIZE);
- tile.setFillColor((i + j) % 2 == 0 ? LIGHT_COLOR : DARK_COLOR);
- window.draw(tile);
- if (visited[i][j]) {
- sf::Text text;
- text.setFont(font);
- text.setString(std::to_string(moveCounter[i][j]));
- text.setCharacterSize(24);
- text.setFillColor(sf::Color::Red);
- text.setPosition(i * TILE_SIZE + TILE_SIZE / 3, j * TILE_SIZE + TILE_SIZE / 5);
- window.draw(text);
- }
- }
- }
- for (const auto& move : knightMoves) {
- sf::RectangleShape highlight(sf::Vector2f(TILE_SIZE, TILE_SIZE));
- highlight.setPosition(move.x * TILE_SIZE, move.y * TILE_SIZE);
- highlight.setFillColor(HIGHLIGHT_COLOR);
- window.draw(highlight);
- }
- if (knightPosition.x >= 0 && knightPosition.y >= 0) {
- sf::CircleShape knight(TILE_SIZE / 2);
- knight.setPosition(knightPosition.x * TILE_SIZE, knightPosition.y * TILE_SIZE);
- knight.setFillColor(KNIGHT_COLOR);
- window.draw(knight);
- }
- sf::Text timerText;
- timerText.setFont(font);
- timerText.setString("Time: " + std::to_string(static_cast<int>(timer)));
- timerText.setCharacterSize(24);
- timerText.setFillColor(sf::Color::Black);
- timerText.setPosition(10, 10);
- window.draw(timerText);
- if (bestTime > 0.0f) {
- sf::Text bestTimeText;
- bestTimeText.setFont(font);
- bestTimeText.setString("Best Time: " + std::to_string(static_cast<int>(bestTime)));
- bestTimeText.setCharacterSize(24);
- bestTimeText.setFillColor(sf::Color::Black);
- bestTimeText.setPosition(10, 40);
- window.draw(bestTimeText);
- }
- if (gameOver) {
- sf::Text gameOverText;
- gameOverText.setFont(font);
- gameOverText.setString(isGameOver() ? "You Win!" : "Game Over!");
- gameOverText.setCharacterSize(48);
- gameOverText.setFillColor(sf::Color::Red);
- gameOverText.setPosition(WINDOW_SIZE / 4, WINDOW_SIZE / 2);
- window.draw(gameOverText);
- }
- window.display();
- }
- void saveBestTime(float time) {
- std::ofstream outFile("best_time.txt");
- if (outFile.is_open()) {
- outFile << std::fixed << std::setprecision(2) << time;
- outFile.close();
- bestTime = time;
- std::cout << "Best time updated: " << bestTime << " seconds\n";
- }
- else {
- std::cerr << "Error: Unable to open best_time.txt for writing\n";
- }
- }
- float loadBestTime() {
- std::ifstream inFile("best_time.txt");
- float time;
- if (inFile.is_open()) {
- inFile >> time;
- inFile.close();
- return time;
- }
- else {
- std::cerr << "Error: Unable to open best_time.txt for reading\n";
- return -1.0f;
- }
- }
- void undoMove() {
- if (moveHistory.size() > 1) {
- sf::Vector2i lastMove = moveHistory.back();
- moveHistory.pop_back();
- visited[lastMove.x][lastMove.y] = false;
- moveCounter[lastMove.x][lastMove.y] = 0;
- knightPosition = moveHistory.back();
- moveNumber--;
- knightMoves = getValidMoves(knightPosition);
- }
- }
- void resetGame() {
- knightPosition = { -1, -1 };
- knightMoves.clear();
- moveHistory.clear();
- std::fill(&visited[0][0], &visited[0][0] + sizeof(visited) / sizeof(bool), false);
- std::fill(&moveCounter[0][0], &moveCounter[0][0] + sizeof(moveCounter) / sizeof(int), 0);
- moveNumber = 1;
- gameStarted = false;
- gameOver = false;
- }
- int main() {
- sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE, WINDOW_SIZE), "Knight's Tour");
- sf::Clock clock;
- float timer = 0.0f;
- bestTime = loadBestTime();
- sf::Font font;
- if (!font.loadFromFile("arial.ttf")) {
- std::cerr << "Error loading arial.ttf\n";
- return -1;
- }
- while (window.isOpen()) {
- sf::Event event;
- while (window.pollEvent(event)) {
- if (event.type == sf::Event::Closed) {
- window.close();
- }
- if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
- int mouseX = event.mouseButton.x / TILE_SIZE;
- int mouseY = event.mouseButton.y / TILE_SIZE;
- if (mouseX >= 0 && mouseX < SIZE && mouseY >= 0 && mouseY < SIZE) {
- if (!gameStarted) {
- knightPosition = { mouseX, mouseY };
- visited[mouseX][mouseY] = true;
- moveCounter[mouseX][mouseY] = moveNumber++;
- moveHistory.push_back(knightPosition);
- knightMoves = getValidMoves(knightPosition);
- gameStarted = true;
- gameOver = false;
- clock.restart();
- }
- else if (isMoveInValidMoves({ mouseX, mouseY })) {
- knightPosition = { mouseX, mouseY };
- visited[mouseX][mouseY] = true;
- moveCounter[mouseX][mouseY] = moveNumber++;
- moveHistory.push_back(knightPosition);
- knightMoves = getValidMoves(knightPosition);
- if (isGameOver()) {
- std::cout << "You Win!\n";
- if (bestTime < 0.0f || timer < bestTime) {
- saveBestTime(timer);
- }
- gameOver = true;
- gameStarted = false;
- }
- }
- }
- }
- if (event.type == sf::Event::KeyPressed) {
- if (event.key.code == sf::Keyboard::U) {
- undoMove();
- }
- if (event.key.code == sf::Keyboard::R) {
- resetGame();
- }
- }
- }
- if (gameStarted) {
- timer += clock.restart().asSeconds();
- }
- else {
- clock.restart();
- }
- drawBoard(window, font, timer);
- if (gameStarted && knightMoves.empty() && !isGameOver()) {
- std::cout << "No valid moves left. Game Over!\n";
- gameOver = true;
- gameStarted = false;
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement