diff --git a/.DS_Store b/.DS_Store index cab3426..e4f57bf 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Battleships/.DS_Store b/Battleships/.DS_Store deleted file mode 100644 index 465823b..0000000 Binary files a/Battleships/.DS_Store and /dev/null differ diff --git a/Battleships/Lesson1.html b/Battleships/Lesson1.html deleted file mode 100644 index cb25f34..0000000 --- a/Battleships/Lesson1.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - Lesson 1: Battleships in Python! - - - -

๐ŸŽฎ Lesson 1: Find the Hidden Ship!

- -
-

โœ… Learning Outcomes

- -
- -
-

๐Ÿ’ก Why It Matters

-

Every video game has hidden logic โ€” secret levels, random enemies, or treasure locations. Learning to hide and reveal things with code is the first step to making your own games!

-

These same skills are used in apps, quizzes, and even smart home devices!

-
- -

โฑ๏ธ Lesson Plan (40 minutes)

- -
- 0โ€“5 min โ†’ Demo & Explain
- Show the game: โ€œThereโ€™s a secret ship! Can you find it?โ€
- Explain: Weโ€™ll write code that hides a ship and checks your guess. -
- -
- 5โ€“20 min โ†’ Code Together
- Type this starter code (or use your template): -
-import random
-
-ship_row = random.randint(0, 4)
-ship_col = random.randint(0, 4)
-
-print("Guess the ship!")
-guess_row = int(input("Row (0-4): "))
-guess_col = int(input("Col (0-4): "))
-
-if guess_row == ship_row and guess_col == ship_col:
-    print("๐ŸŽฏ HIT! You sank the ship!")
-else:
-    print("๐Ÿ’ฆ MISS!")
-
-print("The ship was at", ship_row, ship_col)
-    
-
- -
- 20โ€“35 min โ†’ Test & Improve
- โ€ข Run the program 3 times
- โ€ข Try to break it (type a letter instead of number โ€” what happens?)
- โ€ข ๐ŸŒŸ Challenge: Add a 2nd ship or limit to 3 guesses! -
- -
- 35โ€“40 min โ†’ Share & Celebrate
- Pair up! Can your partner guess the ship in 2 tries? -
- -

๐Ÿš€ You Just Learned:

-

How to create interactive programs that respond to user choices โ€” the heart of all games!

- - \ No newline at end of file diff --git a/Battleships/Lesson2.html b/Battleships/Lesson2.html deleted file mode 100644 index 13b9103..0000000 --- a/Battleships/Lesson2.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - Lesson 2: Hunt All the Ships! - - - -

๐Ÿšข Lesson 2: Hunt All the Ships!

- -
-

โœ… Learning Outcomes

- -
- -
-

๐Ÿ’ก Why It Matters

-

Real games donโ€™t end after one guess! They track score, lives, and progress. Learning to manage game state is how you build Pac-Man, Minecraft, or Roblox games!

-

Lists and loops are used in every programming language โ€” from apps to robots.

-
- -

โฑ๏ธ Lesson Plan (40 minutes)

- -
- 0โ€“5 min โ†’ Review & Goal
- โ€œLast time: 1 ship. Today: 3 ships and 10 turns!โ€
- Show the enhanced game in action. -
- -
- 5โ€“20 min โ†’ Upgrade Your Code
- Edit your Lesson 1 file to this: -
-import random
-
-ships = []
-while len(ships) < 3:
-    r = random.randint(0, 4)
-    c = random.randint(0, 4)
-    if [r, c] not in ships:
-        ships.append([r, c])
-
-print("3 ships hidden! 10 turns to find them all.")
-hits = 0
-
-for turn in range(10):
-    print("\nTurn", turn + 1)
-    guess_row = int(input("Row (0-4): "))
-    guess_col = int(input("Col (0-4): "))
-    
-    if [guess_row, guess_col] in ships:
-        print("๐ŸŽฏ HIT!")
-        ships.remove([guess_row, guess_col])
-        hits += 1
-        if hits == 3:
-            print("๐Ÿ† You win!")
-            break
-    else:
-        print("๐Ÿ’ฆ MISS!")
-
-if hits < 3:
-    print("Game over! You found", hits, "ships.")
-    
-
- -
- 20โ€“35 min โ†’ Level Up!
- โ€ข Test the game (try to win!)
- โ€ข ๐ŸŒŸ Challenge 1: Let players use A, B, C for rows!
- row_letter = input("Row (A-E): ").upper()
- guess_row = ord(row_letter) - ord('A')
- โ€ข ๐ŸŒŸ Challenge 2: Show how many turns are left! -
- -
- 35โ€“40 min โ†’ Play & Reflect
- Play your friendโ€™s game! What makes it fun?
- โ€œNow YOU can make games โ€” not just play them!โ€ -
- -

๐ŸŒŸ Youโ€™re Now a Game Coder!

-

Youโ€™ve learned the core ideas behind almost every game: hidden objects, player input, feedback, and win/lose conditions.

- - \ No newline at end of file diff --git a/Battleships/battleships-137-main/.DS_Store b/Battleships/battleships-137-main/.DS_Store deleted file mode 100644 index 7f938ab..0000000 Binary files a/Battleships/battleships-137-main/.DS_Store and /dev/null differ diff --git a/Battleships/battleships-137-main/.gitignore b/Battleships/battleships-137-main/.gitignore deleted file mode 100644 index 29c24da..0000000 --- a/Battleships/battleships-137-main/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -core.Microsoft* -core.mongo* -core.python* -env.py -__pycache__/ -*.py[cod] -node_modules/ -.github/ -creds.json \ No newline at end of file diff --git a/Battleships/battleships-137-main/.gitpod.dockerfile b/Battleships/battleships-137-main/.gitpod.dockerfile deleted file mode 100644 index cb70866..0000000 --- a/Battleships/battleships-137-main/.gitpod.dockerfile +++ /dev/null @@ -1,84 +0,0 @@ -FROM gitpod/workspace-base - -RUN echo "CI version from base" - -### NodeJS ### -USER gitpod -ENV NODE_VERSION=16.13.0 -ENV TRIGGER_REBUILD=1 -RUN curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | PROFILE=/dev/null bash \ - && bash -c ". .nvm/nvm.sh \ - && nvm install $NODE_VERSION \ - && nvm use $NODE_VERSION \ - && nvm alias default $NODE_VERSION \ - && npm install -g typescript yarn node-gyp" \ - && echo ". ~/.nvm/nvm.sh" >> /home/gitpod/.bashrc.d/50-node -ENV PATH=$PATH:/home/gitpod/.nvm/versions/node/v${NODE_VERSION}/bin - -### Python ### -USER gitpod -RUN sudo install-packages python3-pip -ENV PYTHON_VERSION 3.12.2 - -ENV PATH=$HOME/.pyenv/bin:$HOME/.pyenv/shims:$PATH -RUN curl -fsSL https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash \ - && { echo; \ - echo 'eval "$(pyenv init -)"'; \ - echo 'eval "$(pyenv virtualenv-init -)"'; } >> /home/gitpod/.bashrc.d/60-python \ - && pyenv update \ - && pyenv install $PYTHON_VERSION \ - && pyenv global $PYTHON_VERSION \ - && python3 -m pip install --no-cache-dir --upgrade pip \ - && python3 -m pip install --no-cache-dir --upgrade \ - setuptools wheel virtualenv pipenv pylint rope flake8 \ - mypy autopep8 pep8 pylama pydocstyle bandit notebook \ - twine \ - && sudo rm -rf /tmp/*USER gitpod -ENV PYTHONUSERBASE=/workspace/.pip-modules \ - PIP_USER=yes -ENV PATH=$PYTHONUSERBASE/bin:$PATH - -# Setup Heroku CLI -RUN curl https://cli-assets.heroku.com/install.sh | sh - -RUN wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb && sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb && \ - sudo rm -rf /var/cache/apt/* /var/lib/apt/lists/* /tmp/* /home/gitpod/*.deb && \ - sudo chown -R gitpod:gitpod /home/gitpod/.cache/heroku/ - -# Setup PostgreSQL - -RUN sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list' && \ - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 && \ - sudo apt-get update -y && \ - sudo apt-get install -y postgresql-12 - -ENV PGDATA="/workspace/.pgsql/data" - -RUN mkdir -p ~/.pg_ctl/bin ~/.pg_ctl/sockets \ - && echo '#!/bin/bash\n[ ! -d $PGDATA ] && mkdir -p $PGDATA && initdb --auth=trust -D $PGDATA\npg_ctl -D $PGDATA -l ~/.pg_ctl/log -o "-k ~/.pg_ctl/sockets" start\n' > ~/.pg_ctl/bin/pg_start \ - && echo '#!/bin/bash\npg_ctl -D $PGDATA -l ~/.pg_ctl/log -o "-k ~/.pg_ctl/sockets" stop\n' > ~/.pg_ctl/bin/pg_stop \ - && chmod +x ~/.pg_ctl/bin/* - -# ENV DATABASE_URL="postgresql://gitpod@localhost" -# ENV PGHOSTADDR="127.0.0.1" -ENV PGDATABASE="postgres" - -ENV PATH="/usr/lib/postgresql/12/bin:/home/gitpod/.nvm/versions/node/v${NODE_VERSION}/bin:$HOME/.pg_ctl/bin:$PATH" - - -# Add aliases - -RUN echo 'alias run="python3 $GITPOD_REPO_ROOT/manage.py runserver 0.0.0.0:8000"' >> ~/.bashrc && \ - echo 'alias heroku_config=". $GITPOD_REPO_ROOT/.vscode/heroku_config.sh"' >> ~/.bashrc && \ - echo 'alias python=python3' >> ~/.bashrc && \ - echo 'alias pip=pip3' >> ~/.bashrc && \ - echo 'alias arctictern="python3 $GITPOD_REPO_ROOT/.vscode/arctictern.py"' >> ~/.bashrc && \ - echo 'alias font_fix="python3 $GITPOD_REPO_ROOT/.vscode/font_fix.py"' >> ~/.bashrc && \ - echo 'alias set_pg="export PGHOSTADDR=127.0.0.1"' >> ~/.bashrc && \ - echo 'alias make_url="python3 $GITPOD_REPO_ROOT/.vscode/make_url.py "' >> ~/.bashrc - -# Local environment variables -ENV PORT="8080" -ENV IP="0.0.0.0" - - diff --git a/Battleships/battleships-137-main/.gitpod.yml b/Battleships/battleships-137-main/.gitpod.yml deleted file mode 100644 index 39778f8..0000000 --- a/Battleships/battleships-137-main/.gitpod.yml +++ /dev/null @@ -1,14 +0,0 @@ -image: - file: .gitpod.dockerfile -tasks: - - init: . ${GITPOD_REPO_ROOT}/.vscode/init_tasks.sh - command: /home/gitpod/.pg_ctl/bin/pg_start > /dev/null - - command: . ${GITPOD_REPO_ROOT}/.vscode/uptime.sh & -vscode: - extensions: - - ms-python.python - - formulahendry.auto-close-tag - - eventyret.bootstrap-4-cdn-snippet - - hookyqr.beautify - - matt-rudge.auto-open-preview-panel - diff --git a/Battleships/battleships-137-main/.replit b/Battleships/battleships-137-main/.replit deleted file mode 100644 index 2bec17a..0000000 --- a/Battleships/battleships-137-main/.replit +++ /dev/null @@ -1,8 +0,0 @@ -modules = ["web", "nodejs-20", "python-3.12"] -run = "python3 run.py" - -[nix] -channel = "stable-24_05" - -[deployment] -run = ["sh", "-c", "python3 run.py"] diff --git a/Battleships/battleships-137-main/.vscode/arctictern.py b/Battleships/battleships-137-main/.vscode/arctictern.py deleted file mode 100644 index bd164ce..0000000 --- a/Battleships/battleships-137-main/.vscode/arctictern.py +++ /dev/null @@ -1,186 +0,0 @@ -""" -arctictern.py -A little script that does a big migration -""" - -import json -import os -import requests -import shutil -import subprocess -import sys -from os.path import exists - -COLOURS = {"red": "\033[31m", - "blue": "\033[34m", - "green": "\033[32m", - "reset": "\033[0m", - "bold": "\033[1m"} - -BASE_URL = "https://raw.githubusercontent.com/Code-Institute-Org/gitpod-full-template/main/" -CURRENT_VERSION = 1.0 -THIS_VERSION = 1.0 - - -UPGRADE_FILE_LIST = [{"filename": ".vscode/settings.json", - "url": ".vscode/settings.json" - }, - {"filename": ".vscode/launch.json", - "url": ".vscode/launch.json" - }, - {"filename": ".gitpod.yml", - "url": ".gitpod.yml" - }, - {"filename": ".gitpod.dockerfile", - "url": ".gitpod.dockerfile" - }, - {"filename": ".vscode/heroku_config.sh", - "url": ".vscode/heroku_config.sh" - }, - {"filename": ".vscode/init_tasks.sh", - "url": ".vscode/init_tasks.sh" - }, - {"filename": ".vscode/uptime.sh", - "url": ".vscode/uptime.sh" - }, - {"filename": ".vscode/make_url.py", - "url": ".vscode/make_url.py" - }, - {"filename": ".vscode/arctictern.py", - "url": ".vscode/arctictern.py" - }] - -FINAL_LINES = "\nexport POST_UPGRADE_RUN=1\nsource ~/.bashrc\n" - - -def get_versions(): - - if exists(".vscode/version.txt"): - with open(".vscode/version.txt", "r") as f: - THIS_VERSION = float(f.read().strip()) - else: - with open(".vscode/version.txt", "w") as f: - f.write(str(THIS_VERSION)) - - r = requests.get(BASE_URL + ".vscode/version.txt") - CURRENT_VERSION = float(r.content) - - return {"this_version": THIS_VERSION, - "current_version": CURRENT_VERSION} - -def needs_upgrade(): - """ - Checks the version of the current template against - this version. - Returns True if upgrade is needed, False if not. - """ - - versions = get_versions() - - print(f"Upstream version: {versions['current_version']}") - print(f"Local version: {versions['this_version']}") - - return versions["current_version"] > versions["this_version"] - - -def write_version(): - - versions = get_versions() - - with open(".vscode/version.txt", "w") as f: - f.write(str(versions["current_version"])) - - -def build_post_upgrade(): - - r = requests.get(BASE_URL + ".vscode/upgrades.json") - upgrades = json.loads(r.content.decode("utf-8")) - content = "" - - for k,v in upgrades.items(): - if float(k) > THIS_VERSION: - print(f"Adding version changes for {k} to post_upgrade.sh") - content += v - - if content: - content += FINAL_LINES - with open(".vscode/post_upgrade.sh", "w") as f: - f.writelines(content) - - print("Built post_upgrade.sh. Restart your workspace for it to take effect.") - - -def process(file, suffix): - """ - Replaces and optionally backs up the files that - need to be changed. - Arguments: file - a path and filename - suffix - the suffix to the BASE_URL - """ - - if file == ".gitpod.dockerfile" or file == ".gitpod.yml": - try: - shutil.copyfile(file, f"{file}.tmp") - except FileNotFoundError: - pass - - with open(file, "wb") as f: - r = requests.get(BASE_URL + suffix) - f.write(r.content) - - if exists(f"{file}.tmp"): - result = os.system(f"diff -q {file} {file}.tmp > /dev/null") - if result != 0: - os.remove(f"{file}.tmp") - return True - - return False - - -def start_migration(): - """ - Calls the process function and - renames the directory - """ - push_and_recreate = False - - if not os.path.isdir(".vscode"): - print("Creating .vscode directory") - os.mkdir(".vscode") - - for file in UPGRADE_FILE_LIST: - print(f"Processing: {file['filename']}") - result = process(file["filename"], file["url"]) - if result == True: - push_and_recreate = True - - if push_and_recreate: - write_version() - - if needs_upgrade() and not push_and_recreate: - build_post_upgrade() - - print("Changes saved.") - print("Please add, commit and push to GitHub.") - print("You may need to stop and restart your workspace for") - print("the changes to take effect.\n") - - if push_and_recreate: - print(f"{COLOURS['red']}{COLOURS['bold']}*** IMPORTANT INFORMATION ***{COLOURS['reset']}") - print("The files used to create this workspace have been updated") - print("Please download any files that are in .gitignore and") - print("recreate this workspace by clicking on the Gitpod button") - print("in GitHub. Then, upload your saved files again.\n") - - -if __name__ == "__main__": - - print(f"\n๐Ÿฆ {COLOURS['blue']}{COLOURS['bold']}ArcticTern version 0.3{COLOURS['reset']}") - print("CI Template Migration Utility") - print("-----------------------------") - print("Upgrades the workspace to the latest version.\n") - - if input("Start? Y/N ").lower() == "y": - start_migration() - else: - sys.exit("Migration cancelled by the user") diff --git a/Battleships/battleships-137-main/.vscode/heroku_config.sh b/Battleships/battleships-137-main/.vscode/heroku_config.sh deleted file mode 100644 index 5056d45..0000000 --- a/Battleships/battleships-137-main/.vscode/heroku_config.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# Script to allow Heroku API key to be pasted -# exported as an environment variable -# -# Matt Rudge, May 2021 - -echo Heroku authentication configuration script -echo Code Institute, 2021 -echo -echo Get your Heroku API key by going to https://dashboard.heroku.com -echo Go to Account Settings and click on Reveal to view your Heroku API key -echo - -if [[ -z "${HEROKU_API_KEY}" ]]; then - echo Paste your Heroku API key here or press Enter to quit: - read apikey - if [[ -z "${apikey}" ]]; then - return 0 - fi - echo export HEROKU_API_KEY=${apikey} >> ~/.bashrc - echo Added the export. Refreshing the terminal. - . ~/.bashrc > /dev/null - echo Done! -else - echo API key is already set. - echo - echo To reset the API key please input "'reset'": - read reset_trigger - if [[ ${reset_trigger} == reset ]]; then - unset HEROKU_API_KEY - unset reset_trigger - echo - echo API key removed! - else - unset reset_trigger - echo API key unchanged. - fi - echo - echo Exiting -fi diff --git a/Battleships/battleships-137-main/.vscode/init_tasks.sh b/Battleships/battleships-137-main/.vscode/init_tasks.sh deleted file mode 100644 index c532e38..0000000 --- a/Battleships/battleships-137-main/.vscode/init_tasks.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Gives a personalised greeting -# Adds configuration options for SQLite -# Creates run aliases -# Author: Matt Rudge - -echo "Setting the greeting" -sed -i "s/USER_NAME/$GITPOD_GIT_USER_NAME/g" ${GITPOD_REPO_ROOT}/README.md -echo "Creating .sqliterc file" -echo ".headers on" > ~/.sqliterc -echo ".mode column" >> ~/.sqliterc -echo "Your workspace is ready to use. Happy coding!" diff --git a/Battleships/battleships-137-main/.vscode/make_url.py b/Battleships/battleships-137-main/.vscode/make_url.py deleted file mode 100644 index 1a27167..0000000 --- a/Battleships/battleships-137-main/.vscode/make_url.py +++ /dev/null @@ -1,14 +0,0 @@ -# Simple utility for creating the Cloudinary URL from a -# cloudinary_python.txt file -# Matt Rudge, November 2021 - -import re - -with open("cloudinary_python.txt") as f: - content = f.readlines() - -cloud_name = re.findall(r"['](.*?)[']",content[15])[0] -api_key = re.findall(r"['](.*?)[']",content[16])[0] -api_secret = re.findall(r"['](.*?)[']",content[17])[0] - -print(f"cloudinary://{api_key}:{api_secret}@{cloud_name}") diff --git a/Battleships/battleships-137-main/.vscode/settings.json b/Battleships/battleships-137-main/.vscode/settings.json deleted file mode 100644 index c683001..0000000 --- a/Battleships/battleships-137-main/.vscode/settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "python.pythonPath": ".venv/bin/python", - "python.formatting.provider": "black", - "python.formatting.blackArgs": ["--line-length=79" ], - "python.formatting.autopep8Args": ["--max-line-length=79" ], - "python.linting.enabled": true, - "python.linting.flake8Enabled": true, - "python.linting.pylintEnabled": true, - "python.linting.lintOnSave": true, - "python.linting.flake8Args": [ - "--max-line-length=79" - ], - "python.linting.pylintArgs": [ - "--disable=C0111" // Disable missing docstring warnings if needed - ], - "files.autoSave": "onFocusChange" -} \ No newline at end of file diff --git a/Battleships/battleships-137-main/.vscode/uptime.sh b/Battleships/battleships-137-main/.vscode/uptime.sh deleted file mode 100644 index 25a37f8..0000000 --- a/Battleships/battleships-137-main/.vscode/uptime.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Pings the webhook so that we can gather -# basic usage stats. No personally identifiable -# data is captured here, and it is impossible to -# identify an individual user from the captured data. -# Matt Rudge, April 2021 - -UUID=$(cat /proc/sys/kernel/random/uuid) -URL=https://1xthkmzwg3.execute-api.eu-west-1.amazonaws.com/prod/lrsapi/ -API_KEY=jceBCdeGZP9RDeUNCfM4jIQ39Cx0jtG51QgcwDwc -VERB="started" - -clear - -while true; do - - DATA="{\"activity_time\":\"$(date +%Y-%m-%dT%H:%M:%S).000Z\",\"actor\":\"${UUID}\",\"verb\":\"${VERB}\",\"activity_object\":\"Gitpod Workspace\",\"extra_data\":\"{}\"}" - curl -s -X POST -H "x-api-key: ${API_KEY}" -d "${DATA}" ${URL} 1> /dev/null - VERB="running" - sleep 300 - -done diff --git a/Battleships/battleships-137-main/Procfile b/Battleships/battleships-137-main/Procfile deleted file mode 100644 index 5ec9cc2..0000000 --- a/Battleships/battleships-137-main/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: node index.js \ No newline at end of file diff --git a/Battleships/battleships-137-main/README.md b/Battleships/battleships-137-main/README.md deleted file mode 100644 index 5458730..0000000 --- a/Battleships/battleships-137-main/README.md +++ /dev/null @@ -1,284 +0,0 @@ -# [Battleship Game](https://battleships-hedgemonkey-131f157c44ae.herokuapp.com/ "Click to see deployed app") - -This is a simple command-line Battleship game written in Python, with a leader board stored in a google docs spreadsheet. - -## Contents - -
-Click here for Table of Contents - -[Screenshots](#screenshots) - -[Flow Chart Screenshots](#flow-chart-screenshots) - -[Features](#features) - -[Testing](#testing) - -[Future](#future) - -[Deployment](#deployment) - -[Credits](#credits) - -
- -## Screenshots -| Heroku Deployed App | -| :---: | -| ![Screenshot of app on Heroku](readme/screenshot.jpg) | -| This is the app showing the Welcome screenwith Leaderboard with scores sourced through Google Docs API | - -## Flow Chart Screenshots -| Flow Chart Screenshot | -| :---: | -| ![Screenshot of Flowchart](readme/flow_chart.jpg) | -| This is a rough flow chart displaying the program processes made using [Milanote](https://milanote.com/) - -[Back to top](#contents) - -## Features -* **Player vs. Computer:** Play against a challenging AI opponent. -* **Multiple Board Sizes:** Choose a board size between 5x5 and 9x9. -* **High Scores:** Track your best scores and compare them to others. -* **Colorful Interface:** Enjoy a visually enhanced gameplay experience with colored console output. -* **Leaderboard:** Top scores saved to a Google sheets leaderboard using `Google Docs API` and `gspread` - -[Back to top](#contents) - -## Testing - -### Replit -Most of this project was developed using Replit and so testing was done as I was building the project step by step. - -### Manual Testing -The following manual tests were conducted to ensure the application works as expected: - -#### Test 1: Welcome Message -**Steps:** -1. Run the application. -2. Observe the welcome message displayed in the console. - -**Expected Result:** -- The welcome message should be centered and displayed with appropriate colors. - -**Actual Result:** -- The welcome message is displayed correctly. - -**Screenshot:** -![Welcome Message](readme/welcome.jpg) - -#### Test 2: High Scores Display -**Steps:** -1. Run the application. -2. Observe the high scores displayed after the welcome message. - -**Expected Result:** -- The high scores should be displayed in a centered format with appropriate colors. - -**Actual Result:** -- The high scores are displayed correctly. - -**Screenshot:** -![High Scores](readme/welcome.jpg) - -#### Test 3: Board Size Input -**Steps:** -1. Run the application. -2. Enter a valid board size (between 5 and 9). - -**Expected Result:** -- The application should accept the input and proceed to the next step. - -**Actual Result:** -- The application accepts valid inputs and proceeds correctly. - -**Screenshot:** -![Board Size Input](readme/board_size.jpg) - -#### Test 4: Invalid Board Size Input -**Steps:** -1. Run the application. -2. Enter an invalid board size (outside the range of 5 to 9). - -**Expected Result:** -- The application should display an error message and prompt for input again. - -**Actual Result:** -- The application displays an error message and prompts for input again. - -**Screenshot:** -![Invalid Board Size Input](readme/board_size.jpg) - -#### Test 5: Player Turn -**Steps:** -1. Run the application. -2. Enter valid coordinates for the player's turn. - -**Expected Result:** -- The application should update the board and display the result (hit or miss). - -**Actual Result:** -- The application updates the board and displays the result correctly. - -**Screenshot:** -![Player Turn](readme/player_turn.jpg) - -#### Test 6: Computer Turn -**Steps:** -1. Run the application. -2. Observe the computer's turn. - -**Expected Result:** -- The application should update the board and display the result (hit or miss). - -**Actual Result:** -- The application updates the board and displays the result correctly. - -**Screenshot:** -![Computer Turn](readme/player_turn.jpg) - -#### Test 7: Game Over -**Steps:** -1. Run the application. -2. Play the game until either the player or the computer wins. - -**Expected Result:** -- The application should display the game over message and the final scores. - -**Actual Result:** -- The application displays the game over message and the final scores correctly. - -**Screenshot:** -![Game Over](readme/game_over.jpg) - -#### Test 8: Save High Score -**Steps:** -1. Run the application. -2. Win the game and choose to save the high score. -3. Enter a name when prompted. - -**Expected Result:** -The application should save the high score to the Google Sheets and display a success message. - -**Actual Result:** -The application saves the high score and displays the success message correctly. - -**Empty Username:** Players can intentionally leave the username field empty if they prefer not to submit a name. The high score will still be recorded on the leaderboard with a blank entry for the name. - -**Screenshot:** -![Save High Score](readme/save_high_score.jpg) - -[Back to top](#contents) - -### PEP 8 Compliance - -The project's Python code has been refactored to improve adherence to PEP 8 style guidelines. This enhances readability and maintainability. Specific improvements include: - -* **Reduced Branching:** Complex conditional logic, particularly in the `display_boards` function, has been simplified to reduce the number of branches, improving code clarity. -* **Modernized String Formatting:** F-strings (formatted string literals) have been adopted throughout the codebase for more concise and readable string formatting. -* **Removed Redundant Code:** Unnecessary `else` clauses following `return`, `break`, and `continue` statements have been eliminated. -* **Import Order:** Imports have been reorganized to follow PEP 8 recommendations (standard library imports first, followed by third-party and then local imports). - -These changes were guided by feedback from the `pylint` static analysis tool. - -![Pylint Output](readme/pylint_screenshot.jpg) - -[Back to top](#contents) - - -## Future -### Potential Future Features -* **Player vs. Player:** Perhaps add functionality to allow for a 2 player turn-based mode -* **Various Ship Sizes:** It would be nice to add different dized ships more akin to traditional Battleships game, with a choice of orientation -* **Number of Ships:** The added functionality to not only choose the board size but to also choose how many ships on the board would also be an attractive addition to the game -* **Choose Ship Placement:** The option to decide where you would like to place your ships on the board would also be a nice future feature to incorporate - -[Back to top](#contents) - -## Deployment -The site was deployed to Heroku. The steps to deploy are as follows: - -- Set up a [Heroku](https://dashboard.heroku.com) Account and create a new App -- In Settings add the python and nodejs buildpacks -- In `Settings > Config Vars` Add the creds.json contents under the variable `CREDS` -- Link the [GitHub repository](https://github.com/hedgemonkey/battleships) to the Heroku app. - -Heroku git URL -[https://git.heroku.com/battleships-hedgemonkey.git] - -The live link can be found [here](https://battleships-hedgemonkey-131f157c44ae.herokuapp.com/) - -[Back to top](#contents) - -### Google Docs -This project uses a `Google Sheets` spreadsheet hosted on `Google Docs` accessed by `Google Cloud API` this is to keep track of past scores. - -In order to deploy this yourself you would have to get the correct credentials to access this file or specify your own spreadsheet and provide your own Google Cloud API Credentials - -To do this you ned to save your own credentials to `creds.json` and change the line `SHEET = GSPREAD_CLIENT.open('battleship_scores').sheet1` replacing `battleship_scores` with your own spreadsheet filename - -The spreadsheet can be access [HERE](https://docs.google.com/spreadsheets/d/1cUhnYhy8DuxIEW6_BLnj0OFL38dNoRqmyVvkgnQDai8/edit?usp=sharing) - -[Back to top](#contents) - -### Local Deployment - -You can clone or fork this project to make a local copy on your system. - -[Back to top](#contents) - -#### Cloning - -You can clone the repository by following these steps: - -1. Go to the [GitHub repository](https://github.com/Hedgemonkey/battleships). -2. Locate the Code button above the list of files and click it. -3. Select if you prefer to clone using HTTPS, SSH, or GitHub CLI and click the copy button to copy the URL to your clipboard. -4. Open Git Bash or Terminal. -5. Change the current working directory to the one where you want the cloned directory. -6. In your IDE Terminal, type the following command to clone my repository: - - `git clone https://github.com/hedgemonkey/battleships.git` -7. Press Enter to create your local clone. - -[Back to top](#contents) - -#### Forking - -By forking the GitHub Repository, we make a copy of the original repository on our GitHub account to view and/or make changes without affecting the original owner's repository. -You can fork this repository by using the following steps: - -1. Log in to GitHub and locate the [GitHub repository](https://github.com/Hedgemonkey/battleships). -2. At the top of the Repository (not the top of the page) just above the "Settings" Button on the menu, locate the "Fork" Button. -3. Once clicked, you should now have a copy of the original repository in your own GitHub account. - -[Back to top](#contents) - -### Local vs Deployment - -There are no notable differences between my locally developed app and the Heroku deployed site aside from slight variances in the terminal colours. - -[Back to top](#contents) - - -## Credits - -In this section, I will reference the sources of my content and media, full disclosure of any resources used shall be detailed here. - -- Milanote used to create Flow Chart Diagram - -- Gemini Pro AI Used to help guide me when code wasn't doing as I intended - -[Back to top](#contents) - -### Content - -[Back to top](#contents) - -### Acknowledgements - -- I would like to thank the [Code Institute Slack community](https://code-institute-room.slack.com) for the moral support and general information that helps with my studies. -- I would like to also thank Gemini Pro AI for assisting me whenever I needed a bit of quick advice, although it's suggestions often lead to more complications it's explinations and tips were incredibly helpful -- YTMusic for providing me with a soundtrack to work to - -[Back to top](#contents) \ No newline at end of file diff --git a/Battleships/battleships-137-main/controllers/default.js b/Battleships/battleships-137-main/controllers/default.js deleted file mode 100644 index 96ffdd4..0000000 --- a/Battleships/battleships-137-main/controllers/default.js +++ /dev/null @@ -1,60 +0,0 @@ -const Pty = require('node-pty'); -const fs = require('fs'); - -exports.install = function () { - - ROUTE('/'); - WEBSOCKET('/', socket, ['raw']); - -}; - -function socket() { - - this.encodedecode = false; - this.autodestroy(); - - this.on('open', function (client) { - - // Spawn terminal - client.tty = Pty.spawn('python3', ['run.py'], { - name: 'xterm-color', - cols: 80, - rows: 24, - cwd: process.env.PWD, - env: process.env - }); - - client.tty.on('exit', function (code, signal) { - client.tty = null; - client.close(); - console.log("Process killed"); - }); - - client.tty.on('data', function (data) { - client.send(data); - }); - - }); - - this.on('close', function (client) { - if (client.tty) { - client.tty.kill(9); - client.tty = null; - console.log("Process killed and terminal unloaded"); - } - }); - - this.on('message', function (client, msg) { - client.tty && client.tty.write(msg); - }); -} - -if (process.env.CREDS != null) { - console.log("Creating creds.json file."); - fs.writeFile('creds.json', process.env.CREDS, 'utf8', function (err) { - if (err) { - console.log('Error writing file: ', err); - socket.emit("console_output", "Error saving credentials: " + err); - } - }); -} \ No newline at end of file diff --git a/Battleships/battleships-137-main/index.js b/Battleships/battleships-137-main/index.js deleted file mode 100644 index 2598955..0000000 --- a/Battleships/battleships-137-main/index.js +++ /dev/null @@ -1,30 +0,0 @@ -// =================================================== -// Total.js start script -// https://www.totaljs.com -// =================================================== - -const options = {}; - -// options.ip = '127.0.0.1'; -options.port = parseInt(process.env.PORT); -// options.unixsocket = require('path').join(require('os').tmpdir(), 'app_name'); -// options.config = { name: 'Total.js' }; -// options.sleep = 3000; -// options.inspector = 9229; -// options.watch = ['private']; -// options.livereload = 'https://yourhostname'; - -// Enables cluster: -// options.cluster = 'auto'; -// options.cluster_limit = 10; // max 10. threads (works only with "auto" scaling) - -// Enables threads: -// options.cluster = 'auto'; -// options.cluster_limit = 10; // max 10. threads (works only with "auto" scaling) -// options.timeout = 5000; -// options.threads = '/api/'; -// options.logs = 'isolated'; - -var type = process.argv.indexOf('--release', 1) !== -1 || process.argv.indexOf('release', 1) !== -1 ? 'release' : 'debug'; -// require('total4/' + type)(options); -require('total4').http('release', options); \ No newline at end of file diff --git a/Battleships/battleships-137-main/package-lock.json b/Battleships/battleships-137-main/package-lock.json deleted file mode 100644 index 29dfbf0..0000000 --- a/Battleships/battleships-137-main/package-lock.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "name": "terminal", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "terminal", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "node-pty": "^0.10.1", - "node-static": "^0.7.11", - "total4": "^0.0.45" - } - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", - "license": "MIT" - }, - "node_modules/nan": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", - "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", - "license": "MIT" - }, - "node_modules/node-pty": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-0.10.1.tgz", - "integrity": "sha512-JTdtUS0Im/yRsWJSx7yiW9rtpfmxqxolrtnyKwPLI+6XqTAPW/O2MjS8FYL4I5TsMbH2lVgDb2VMjp+9LoQGNg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "nan": "^2.14.0" - } - }, - "node_modules/node-static": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.11.tgz", - "integrity": "sha512-zfWC/gICcqb74D9ndyvxZWaI1jzcoHmf4UTHWQchBNuNMxdBLJMDiUgZ1tjGLEIe/BMhj2DxKD8HOuc2062pDQ==", - "license": "MIT", - "dependencies": { - "colors": ">=0.6.0", - "mime": "^1.2.9", - "optimist": ">=0.3.4" - }, - "bin": { - "static": "bin/cli.js" - }, - "engines": { - "node": ">= 0.4.1" - } - }, - "node_modules/optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", - "license": "MIT/X11", - "dependencies": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "node_modules/total4": { - "version": "0.0.45", - "resolved": "https://registry.npmjs.org/total4/-/total4-0.0.45.tgz", - "integrity": "sha512-96vXqejddbAeNL6zpzbfm8ztiWL4G0fOuoUWniHDlu6oSz+DcxekHkzK0Y9X+ErlHCRTMsP2+ieMTqG6waowiA==", - "license": "MIT", - "bin": { - "total4": "bin/total4" - } - }, - "node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - } - } -} diff --git a/Battleships/battleships-137-main/package.json b/Battleships/battleships-137-main/package.json deleted file mode 100644 index 56ca191..0000000 --- a/Battleships/battleships-137-main/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "terminal", - "version": "1.0.0", - "main": "server.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/lechien73/terminal.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/lechien73/terminal/issues" - }, - "homepage": "https://github.com/lechien73/terminal#readme", - "dependencies": { - "node-static": "^0.7.11", - "node-pty": "^0.10.1", - "total4": "^0.0.45" - } -} \ No newline at end of file diff --git a/Battleships/battleships-137-main/readme/board_size.jpg b/Battleships/battleships-137-main/readme/board_size.jpg deleted file mode 100644 index 076b19d..0000000 Binary files a/Battleships/battleships-137-main/readme/board_size.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/flow_chart.jpg b/Battleships/battleships-137-main/readme/flow_chart.jpg deleted file mode 100644 index 61c9d05..0000000 Binary files a/Battleships/battleships-137-main/readme/flow_chart.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/flow_chart.png b/Battleships/battleships-137-main/readme/flow_chart.png deleted file mode 100644 index b548883..0000000 Binary files a/Battleships/battleships-137-main/readme/flow_chart.png and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/game_over.jpg b/Battleships/battleships-137-main/readme/game_over.jpg deleted file mode 100644 index 1b04466..0000000 Binary files a/Battleships/battleships-137-main/readme/game_over.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/player_turn.jpg b/Battleships/battleships-137-main/readme/player_turn.jpg deleted file mode 100644 index 805afc8..0000000 Binary files a/Battleships/battleships-137-main/readme/player_turn.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/pylint_screenshot.jpg b/Battleships/battleships-137-main/readme/pylint_screenshot.jpg deleted file mode 100644 index 681e940..0000000 Binary files a/Battleships/battleships-137-main/readme/pylint_screenshot.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/save_high_score.jpg b/Battleships/battleships-137-main/readme/save_high_score.jpg deleted file mode 100644 index 6686f44..0000000 Binary files a/Battleships/battleships-137-main/readme/save_high_score.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/screenshot.jpg b/Battleships/battleships-137-main/readme/screenshot.jpg deleted file mode 100644 index 936bab8..0000000 Binary files a/Battleships/battleships-137-main/readme/screenshot.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/screenshot.png b/Battleships/battleships-137-main/readme/screenshot.png deleted file mode 100644 index 8ee4d02..0000000 Binary files a/Battleships/battleships-137-main/readme/screenshot.png and /dev/null differ diff --git a/Battleships/battleships-137-main/readme/welcome.jpg b/Battleships/battleships-137-main/readme/welcome.jpg deleted file mode 100644 index cbe24ca..0000000 Binary files a/Battleships/battleships-137-main/readme/welcome.jpg and /dev/null differ diff --git a/Battleships/battleships-137-main/requirements.txt b/Battleships/battleships-137-main/requirements.txt deleted file mode 100644 index 84f6cf3..0000000 --- a/Battleships/battleships-137-main/requirements.txt +++ /dev/null @@ -1,20 +0,0 @@ -cachetools==5.5.0 -certifi==2024.8.30 -cffi==1.17.1 -charset-normalizer==3.3.2 -cryptography==43.0.1 -google-auth==2.34.0 -google-auth-oauthlib==1.2.1 -google-oauth==1.0.1 -gspread==6.1.2 -idna==3.8 -oauthlib==3.2.2 -pyasn1==0.6.0 -pyasn1_modules==0.4.0 -pycparser==2.22 -pyOpenSSL==24.2.1 -requests==2.32.3 -requests-oauthlib==2.0.0 -rsa==4.9 -six==1.16.0 -urllib3==2.2.2 diff --git a/Battleships/battleships-137-main/run.py b/Battleships/battleships-137-main/run.py deleted file mode 100644 index 59e29ad..0000000 --- a/Battleships/battleships-137-main/run.py +++ /dev/null @@ -1,371 +0,0 @@ -"""This module is a battleship game""" - -import os -import re -import string # Corrected import order (see point 14) -import random -import gspread -from google.oauth2.service_account import Credentials - - -SCOPE = [ - "https://www.googleapis.com/auth/spreadsheets", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive" - ] - - -CREDS = Credentials.from_service_account_file('creds.json') -SCOPED_CREDS = CREDS.with_scopes(SCOPE) -GSPREAD_CLIENT = gspread.authorize(SCOPED_CREDS) -SHEET = GSPREAD_CLIENT.open('battleship_scores').sheet1 - - -def center_text(text): - """ - Function to center text in the console - """ - console_width = os.get_terminal_size().columns - text_length = len(re.sub(r'\x1b\[[0-9;]*m', '', text)) - padding = (console_width - text_length) // 2 - return " " * padding + text + " " * padding - - -def pause(): - """ - Function to pause and clear the screen - """ - input("\n" + Bcolors.OKCYAN + center_text("Press Enter to continue...") + - Bcolors.ENDC) - os.system('cls' if os.name == 'nt' else 'clear') - - -class Bcolors: - # pylint: disable=too-few-public-methods - """ - Colors for console output - """ - HEADER = '\033[95m' - OKBLUE = '\033[34m' - OKCYAN = '\033[96m' - OKGREEN = '\033[32m' - WARNING = '\033[93m' - RED = '\033[31m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - - -def welcome_message(): - """ - Function to display the welcome message with colors - """ - print(Bcolors.HEADER + - Bcolors.BOLD + - center_text("Welcome to Battleships!") + - Bcolors.ENDC) - print("\n" + Bcolors.BOLD + - center_text("Welcome to my simple battleships game!") + - Bcolors.ENDC) - print("\n" + Bcolors.BOLD + - center_text("The aim of the game is to hit your opponents ships" + - " in the least trys possible!") + - Bcolors.ENDC) - print("\n" + Bcolors.BOLD + - center_text("Just select a gameboard size between a 5x5 grid and a" + - " 9x9 grid!") + - Bcolors.ENDC) - print("\n" + Bcolors.BOLD + - center_text("Then enter the co-ordinates of where you want to" + - " shoot when prompted!") + - Bcolors.ENDC) - - -def display_high_scores(): - """ - Function to display top 5 high scores - """ - print("\n" + Bcolors.HEADER + center_text("Current High Scores") + - Bcolors.ENDC) - print("\n" + Bcolors.OKCYAN + center_text("Top 5 Lowest Misses:") + - Bcolors.ENDC) - scores = SHEET.get_all_values() - sorted_scores = scores[1:] - sorted_scores.sort(key=lambda x: int(x[1])) - for i in range(1, 6): - if i <= len(sorted_scores): - print(center_text(f"{i}. {sorted_scores[i-1][0]}: { - sorted_scores[i-1][1]}")) - else: - print(f"{i}. N/A") - - -def get_board_size(): - """ - Function to get valid board size input - """ - while True: - try: - size = int(input("Choose board size (5-9): ")) - if 5 <= size <= 9: - return size - print("Invalid size. Please enter a number between 5 and 9") - except ValueError: - print("Invalid input. Please enter a number.") - - -def create_boards(size): - """ - Function to create and initialize boards - """ - player_board = [['O' for _ in range(size)] for _ in range(size)] - computer_board = [['O' for _ in range(size)] for _ in range(size)] - return player_board, computer_board - - -def place_ships(board, num_ships): - """ - Function to place ships randomly - """ - ship_locations = [] - for _ in range(num_ships): - while True: - row = random.randint(0, len(board) - 1) - col = random.randint(0, len(board[0]) - 1) - if board[row][col] == 'O': - board[row][col] = 'S' - ship_locations.append((row, col)) - break - return ship_locations - - -def display_boards(player_board, computer_board): - """ - Function to display both boards side by side with colors and spacing - """ - board_size = len(player_board) - header_spacing = board_size - 3 - max(0, board_size - 6) - print("\n" + center_text(Bcolors.RED + "Player Board " + - " "*header_spacing + - Bcolors.ENDC + " | " + - Bcolors.RED + - " Computer Board" + - Bcolors.ENDC)) - print("\n" + center_text(Bcolors.OKCYAN + " " + - " ".join([str(i) for i in range( - 1, board_size + 1)]) + - " " + Bcolors.ENDC + - " |" + - " " + Bcolors.OKCYAN + - " ".join([str(i) for i in range( - 1, board_size + 1)]) + - " " + - Bcolors.ENDC)) - letters = list(string.ascii_uppercase[:board_size]) - for i in range(board_size): - player_row = [] - computer_row = [] - for j in range(board_size): - if player_board[i][j] == 'X': - player_row.append(Bcolors.RED + - Bcolors.BOLD + - 'X' + - Bcolors.ENDC) - elif player_board[i][j] == 'S': - player_row.append(Bcolors.OKBLUE + - Bcolors.BOLD + - 'S' + - Bcolors.ENDC) - elif player_board[i][j] == 'M': - player_row.append(Bcolors.OKGREEN + - Bcolors.BOLD + - 'M' + - Bcolors.ENDC) - else: - player_row.append(player_board[i][j]) - if computer_board[i][j] == 'X': - computer_row.append(Bcolors.RED + - Bcolors.BOLD + - 'X' + - Bcolors.ENDC) - elif computer_board[i][j] == 'M': - computer_row.append(Bcolors.OKGREEN + - Bcolors.BOLD + - 'M' + - Bcolors.ENDC) - else: - computer_row.append('O') - player_row_str = ' '.join(player_row) - computer_row_str = ' '.join(computer_row) - row_str = f"{Bcolors.OKCYAN}{letters[i]: <2} {Bcolors.ENDC}{ - player_row_str: <{len(player_row_str) + 2}} | { - Bcolors.OKCYAN}{ - letters[i]: <2}{ - Bcolors.ENDC} { - computer_row_str: <{len(computer_row_str) + 2}}" - print(center_text(row_str)) - - -def get_target(board): - """ - Function to get valid target coordinates - """ - while True: - try: - row_letter = input(f"Enter row (A-{chr(ord('A') + len(board) - 1)}). ").upper() - row = string.ascii_uppercase.index(row_letter.upper()) - col = int(input(f"Enter column (1-{len(board)}). ")) - 1 - if 0 <= row < len(board) and 0 <= col < len(board[0]): - return row, col - print("Invalid coordinates. Please enter numbers within the" + - " board size.") - except ValueError: - print("Invalid input. Please enter letters for Rows and numbers" + - " for columns.") - - -def player_turn(player_board, computer_board, computer_ships, misses): - """ - Function to handle player's turn - """ - print(Bcolors.OKBLUE + "\nYour turn:" + Bcolors.ENDC) - display_boards(player_board, computer_board) - while True: - row, col = get_target(computer_board) - if computer_board[row][col] == 'M' or computer_board[row][col] == 'X': - print(Bcolors.WARNING + - "You already tried that target. Choose another one.\n" + - Bcolors.ENDC) - else: - if (row, col) in computer_ships: - computer_board[row][col] = 'X' - computer_ships.remove((row, col)) - print(Bcolors.OKGREEN + - "Hit! Target: " + - chr(ord('A') + row) + - " " + - str(col + 1) + - Bcolors.ENDC) - else: - computer_board[row][col] = 'M' - print(Bcolors.RED + - "Miss! Target: " + - chr(ord('A') + row) + - " " + - str(col + 1) + - Bcolors.ENDC) - misses += 1 - print(Bcolors.OKCYAN + - "\nMisses: " + - Bcolors.ENDC + - str(misses)) - break - return computer_board, computer_ships, misses - - -def computer_turn(player_board, player_ships, misses): - """ - Function to handle computer's turn - """ - print(Bcolors.OKCYAN + "\nComputer's turn:" + Bcolors.ENDC) - while True: - row = random.randint(0, len(player_board) - 1) - col = random.randint(0, len(player_board[0]) - 1) - if player_board[row][col] == 'M' or player_board[row][col] == 'X': - continue - if (row, col) in player_ships: - player_board[row][col] = 'X' - player_ships.remove((row, col)) - print(Bcolors.OKGREEN + - "Computer hit! Target: " + - chr(ord('A') + row) + - " " + - str(col + 1) + - Bcolors.ENDC) - break - player_board[row][col] = 'M' - print(Bcolors.RED + - "Computer missed! Target: " + - chr(ord('A') + row) + - " " + - str(col + 1) + - Bcolors.ENDC) - misses += 1 - break - pause() - return player_board, player_ships, misses - - -def play_game(): - """ - Function to handle the game loop - """ - while True: - os.system('cl' if os.name == 'nt' else 'clear') - welcome_message() - display_high_scores() - board_size = get_board_size() - pause() - player_board, computer_board = create_boards(board_size) - player_ships = place_ships(player_board, 5) - computer_ships = place_ships(computer_board, 5) - player_misses = 0 - computer_misses = 0 - while player_ships and computer_ships: - computer_board, computer_ships, player_misses = player_turn( - player_board, - computer_board, - computer_ships, - player_misses) - if not computer_ships: - print(Bcolors.OKGREEN + "\nCongratulations! You win!" + - Bcolors.ENDC) - save_to_high_scores(player_misses) - break - player_board, player_ships, computer_misses = computer_turn( - player_board, - player_ships, - computer_misses) - if not player_ships: - print(Bcolors.RED + "\nYou lose! Better luck next time." + - Bcolors.ENDC) - break - print("\nFinal Score:") - print(f"Player: {player_misses}") - print(f"Computer: {computer_misses}") - - while True: - play_again = input("\nPlay again? (y/n): ").lower() - if play_again in ('y', 'n'): - os.system('cls' if os.name == 'nt' else 'clear') - break - print("Invalid input. Please enter 'y' or 'n'.") - if play_again == 'n': - print("Goodbye!") - break - - -def save_to_high_scores(misses): - """ - Function to handle saving scores to the spreadsheet - """ - while True: - save_score = input("Do you want to save your score to the high " + - "scores? (y/n): ") - if save_score.lower() == 'y': - name = input("Enter your name: ") - SHEET.append_row([name, misses]) - os.system('cls' if os.name == 'nt' else 'clear') - print("Score saved successfully!") - display_high_scores() - break - if save_score.lower() == 'n': - os.system('cls' if os.name == 'nt' else 'clear') - print("Score not saved.") - display_high_scores() - break - print("Invalid input. Please enter 'y' or 'n'.") - - -if __name__ == "__main__": - play_game() diff --git a/Battleships/battleships-137-main/runtime.txt b/Battleships/battleships-137-main/runtime.txt deleted file mode 100644 index b884b0f..0000000 --- a/Battleships/battleships-137-main/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.12.2 \ No newline at end of file diff --git a/Battleships/battleships-137-main/views/index.html b/Battleships/battleships-137-main/views/index.html deleted file mode 100644 index 6e6c1ac..0000000 --- a/Battleships/battleships-137-main/views/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - -
- - - \ No newline at end of file diff --git a/Battleships/battleships-137-main/views/layout.html b/Battleships/battleships-137-main/views/layout.html deleted file mode 100644 index aaec1c9..0000000 --- a/Battleships/battleships-137-main/views/layout.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - Python Terminal by Code Institute - - - -@{body} - - \ No newline at end of file diff --git a/Battleships/lesson_1.py b/Battleships/lesson_1.py deleted file mode 100644 index 0eb0f6f..0000000 --- a/Battleships/lesson_1.py +++ /dev/null @@ -1,41 +0,0 @@ -# BATTLESHIPS - Grade 7 Python Game -# Lesson 2: Full mini-game with 3 ships and turns! - -import random - -# Step 1: Create 3 hidden ships (as a list of [row, col]) -ships = [] -while len(ships) < 3: - r = random.randint(0, 4) - c = random.randint(0, 4) - if [r, c] not in ships: # avoid duplicates - ships.append([r, c]) - -print("3 ships are hidden on a 5x5 grid!") -print("You have 10 turns to find them all.") - -hits = 0 -turns = 10 - -# Step 2: Game loop -for turn in range(turns): - print("\nTurn", turn + 1) - - # Get guess - guess_row = int(input("Row (0-4): ")) - guess_col = int(input("Col (0-4): ")) - - # Check if guess is a ship - if [guess_row, guess_col] in ships: - print("๐ŸŽฏ HIT!") - ships.remove([guess_row, guess_col]) # remove found ship - hits += 1 - if hits == 3: - print("๐Ÿ† You found all ships! You win!") - break - else: - print("๐Ÿ’ฆ MISS!") - -# Step 3: Game over message -if hits < 3: - print("Game over! You found", hits, "out of 3 ships.") \ No newline at end of file diff --git a/Battleships/lesson_2.py b/Battleships/lesson_2.py deleted file mode 100644 index 6b34463..0000000 --- a/Battleships/lesson_2.py +++ /dev/null @@ -1,22 +0,0 @@ -# BATTLESHIPS - Grade 7 Python Game -# Lesson 1: Find the hidden ship! - -import random - -# Step 1: Create a secret ship location (row 0-4, col 0-4) -ship_row = random.randint(0, 4) -ship_col = random.randint(0, 4) - -# Step 2: Ask the player for a guess (we'll improve this later!) -print("Guess the ship location!") -guess_row = int(input("Row (0-4): ")) -guess_col = int(input("Col (0-4): ")) - -# Step 3: Check if they hit the ship -if guess_row == ship_row and guess_col == ship_col: - print("๐ŸŽฏ HIT! You sank the ship!") -else: - print("๐Ÿ’ฆ MISS! Try again.") - -# Step 4: (Optional) Show where the ship really was -print("The ship was at row", ship_row, "and col", ship_col) \ No newline at end of file diff --git a/README.md b/README.md index 77c483e..3f10ba0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ -# ai6-m2 +# Quizimoto - Russian Millionaire Quiz Game +## Team Roles: +- **Dima**: Backend Developer (app.py) +- **Inna**: Frontend Developer (templates/, static/script.js) +- **Danil**: Database Designer (questions.json) +- **Artyom**: Graphics/UX Designer (static/style.css, visual design) + +## Development Instructions: +1. Each team member focuses on their designated files +2. Commit and push changes regularly +3. Test your components independently +4. Collaborate on integration issues diff --git a/app.py b/app.py new file mode 100644 index 0000000..2696d61 --- /dev/null +++ b/app.py @@ -0,0 +1,44 @@ +from flask import Flask, render_template, request, jsonify, session +import json +import random +import os + +app = Flask(__name__) +app.secret_key = 'quizimoto_secret_key' + +# TODO: Dima - Implement prize structure (15 levels) +PRIZE_LEVELS = [ + # Format: [1000, 2000, 4000, 8000, 16000, 32000, ... up to 15 values] +] +GUARANTEED_LEVELS = [5, 10] # First and second guaranteed levels + +@app.route('/') +def index(): + return render_template('index.html') + +@app.route('/start') +def start_game(): + # TODO: Dima - Initialize game session + # Set up: score, current_question, lifelines, questions + return render_template('game.html') + +@app.route('/get_question') +def get_question(): + # TODO: Dima - Serve questions to frontend + # Return: question, options, question_number, current_prize + return jsonify({"error": "Not implemented"}) + +@app.route('/answer', methods=['POST']) +def check_answer(): + # TODO: Dima - Validate answers and update score + # Check if answer is correct, update session, return result + return jsonify({"error": "Not implemented"}) + +@app.route('/lifeline/') +def use_lifeline(lifeline_name): + # TODO: Dima - Implement 50:50 and Phone a Friend + # Note: Ask AI will be version 2 + return jsonify({"error": "Not implemented"}) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/pingpong/pingpong.html b/pingpong/pingpong.html deleted file mode 100644 index 3b308c0..0000000 --- a/pingpong/pingpong.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - Simple Paddle Game - - - - -
-
-
-
- - - - - \ No newline at end of file diff --git a/questions.json b/questions.json new file mode 100644 index 0000000..e25edeb --- /dev/null +++ b/questions.json @@ -0,0 +1,12 @@ +[ + { + "question": "EXAMPLE: What is the capital of Russia?", + "options": ["St. Petersburg", "Moscow", "Kazan", "Sochi"], + "correct_answer": "Moscow" + }, + { + "question": "TODO: Danil - Add Russian culture question here", + "options": ["Option A", "Option B", "Option C", "Option D"], + "correct_answer": "Correct Answer" + } +] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..597ce19 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Flask==2.3.3 diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..0fd8828 --- /dev/null +++ b/static/script.js @@ -0,0 +1,104 @@ +// TODO: Inna - Implement frontend game functionality + +let gameState = { + currentQuestion: null, + optionsDisabled: false +}; + +function loadQuestion() { + fetch('/get_question') + .then(response => response.json()) + .then(data => { + if (data.error) { + console.error(data.error); + return; + } + if (data.game_over) { + endGame(data.final_score); + return; + } + gameState.currentQuestion = data; + displayQuestion(data); + }) + .catch(error => console.error('Error:', error)); +} + +function displayQuestion(questionData) { + document.getElementById('question-num').textContent = questionData.question_number; + document.getElementById('question-text').textContent = questionData.question; + + const optionsContainer = document.getElementById('options-container'); + optionsContainer.innerHTML = ''; + + const optionLetters = ['A', 'B', 'C', 'D']; + questionData.options.forEach((option, index) => { + const optionElement = document.createElement('div'); + optionElement.className = 'option'; + optionElement.textContent = `${optionLetters[index]}. ${option}`; + optionElement.onclick = () => selectAnswer(option); + optionsContainer.appendChild(optionElement); + }); + + document.getElementById('feedback').style.display = 'none'; + gameState.optionsDisabled = false; +} + +function selectAnswer(selectedAnswer) { + if (gameState.optionsDisabled) return; + gameState.optionsDisabled = true; + + fetch('/answer', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ answer: selectedAnswer }) + }) + .then(response => response.json()) + .then(data => { + const feedback = document.getElementById('feedback'); + feedback.style.display = 'block'; + + if (data.correct) { + feedback.textContent = 'Correct! ๐ŸŽ‰'; + feedback.className = 'feedback correct'; + setTimeout(() => { + if (data.next_question) loadQuestion(); + else endGame(data.final_score, true); + }, 1500); + } else { + feedback.textContent = `Incorrect! Correct answer: ${data.correct_answer}`; + feedback.className = 'feedback incorrect'; + setTimeout(() => endGame(data.final_score), 2000); + } + }) + .catch(error => console.error('Error:', error)); +} + +function useLifeline(lifelineName) { + fetch(`/lifeline/${lifelineName}`) + .then(response => response.json()) + .then(data => { + if (data.error) { + alert(data.error); + return; + } + document.getElementById('lifeline-result').textContent = + data.hint || data.friend_says || 'Lifeline used!'; + }) + .catch(error => console.error('Error:', error)); +} + +function endGame(finalScore, isWin = false) { + document.getElementById('final-prize').textContent = finalScore; + document.getElementById('game-over-screen').style.display = 'block'; + document.querySelector('.game-area').style.display = 'none'; +} + +function restartGame() { + window.location.href = '/start'; +} + +document.addEventListener('DOMContentLoaded', function() { + if (window.location.pathname === '/start') { + loadQuestion(); + } +}); diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..874be31 --- /dev/null +++ b/static/style.css @@ -0,0 +1,105 @@ +/* TODO: Artyom - Enhance this CSS with Russian-themed design */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: Arial, sans-serif; +} + +body { + background: #1a2a6c; + color: white; + min-height: 100vh; + padding: 20px; +} + +.container { + max-width: 800px; + margin: 0 auto; + background: rgba(255, 255, 255, 0.1); + border-radius: 10px; + padding: 20px; +} + +header { + text-align: center; + margin-bottom: 20px; + padding: 15px; + background: #b21f1f; + border-radius: 8px; +} + +h1 { + font-size: 2.5rem; + margin-bottom: 10px; +} + +.question-container { + background: rgba(255, 255, 255, 0.1); + padding: 20px; + border-radius: 8px; + margin-bottom: 20px; +} + +.question { + font-size: 1.3rem; + margin-bottom: 20px; + text-align: center; +} + +.options-container { + display: grid; + gap: 10px; +} + +.option { + background: #fdbb2d; + color: #1a2a6c; + padding: 15px; + border-radius: 5px; + cursor: pointer; + text-align: center; + font-weight: bold; +} + +.option:hover { + background: #e6a923; +} + +.lifelines { + background: rgba(255, 255, 255, 0.1); + padding: 15px; + border-radius: 8px; +} + +.lifeline-buttons { + display: flex; + gap: 10px; + justify-content: center; +} + +.lifeline-btn { + background: #1a2a6c; + color: white; + border: none; + padding: 10px 15px; + border-radius: 5px; + cursor: pointer; +} + +.start-btn { + background: #fdbb2d; + color: #1a2a6c; + border: none; + padding: 15px 30px; + border-radius: 25px; + font-size: 1.2rem; + cursor: pointer; + display: block; + margin: 20px auto; +} + +.game-over-screen { + text-align: center; + padding: 30px; +} diff --git a/templates/game.html b/templates/game.html new file mode 100644 index 0000000..a9329e7 --- /dev/null +++ b/templates/game.html @@ -0,0 +1,47 @@ + + + + + + Quizimoto - Game + + + +
+
+

Quizimoto

+
Prize: 0 โ‚ฝ
+
+ +
+
+
Question 1/15
+
Loading question...
+ +
+ +
+ + +
+ +
+

Lifelines

+
+ + +
+
+
+
+ + +
+ + + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..cc22259 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,30 @@ + + + + + + Quizimoto - Russian Millionaire Quiz + + + +
+
+

Quizimoto

+

Russian Millionaire Quiz Game

+
+ +
+

Welcome!

+

Test your knowledge of Russian culture and win up to 1,000,000 โ‚ฝ!

+ + +
+
+ + + +