Skip to content
Snippets Groups Projects
Commit e3282989 authored by Amel Abdic's avatar Amel Abdic :8ball:
Browse files

Initial Commit Backend + Frontend 4 Gewinnt

parents
No related branches found
No related tags found
2 merge requests!2Master,!1Initial Commit Backend + Frontend 4 Gewinnt
# These are supported funding model platforms
github: kubowania
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.8" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N802" />
<option value="N801" />
<option value="N806" />
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.9 (Mood Meter)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/connect-four-master.iml" filepath="$PROJECT_DIR$/.idea/connect-four-master.iml" />
</modules>
</component>
</project>
\ No newline at end of file
# connect-four
A retro grid-based game in vanilla JavaScript, HTML and CSS
View the full walkthrough [here]()
I have kept the styling at a bare miniumum for you to go wild and make it your own. Please tag me as I would LOVE to see your game!!!
Connect Four (also known as Four Up, Plot Four, Find Four, Four in a Row, Four in a Line, Drop Four, and Gravitrips (in Soviet Union)) is a two-player board game in which the players first choose a color and then take turns dropping one colored disc from the top into a seven-column, six-row vertically suspended grid. The pieces fall straight down, occupying the lowest available space within the column. The objective of the game is to be the first to form a horizontal, vertical, or diagonal line of four of one's own discs.
In this repo, I will be putting extra focus on for loops. If you want to learn how to use for loops effectively, please have a look at my code.
## What are we going to focus on?
* for loops
* addEventListener
* document.querySelector
* arrow functions
## Rules of Connect Four
* You will start as player One
* You will take your go as player One
* You will not be allowed to go in squares that are not at the bottom of the grid, or do not have a taken square under it
* Once your go is taken and you did not win, It will be player Two's go
* The gamer will continue until a winning combination of four is reached by player One or player Two, or until the grid is full and no winning combination was found.
### MIT Licence
Copyright (c) 2020 Ania Kubow
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*Translation: Ofcourse you can use this for you project! Just make sure to say where you got this from :)
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
app.js 0 → 100644
document.addEventListener('DOMContentLoaded', () => {
const flaechen = document.querySelectorAll('.grid div');
const ergebnis = document.querySelector('#result');
const displayCurrentPlayer = document.querySelector('#current-player');
let currentPlayer = 1;
const gewinnFlaechen = [
[0, 1, 2, 3],
[41, 40, 39, 38],
[7, 8, 9, 10],
[34, 33, 32, 31],
[14, 15, 16, 17],
[27, 26, 25, 24],
[21, 22, 23, 24],
[20, 19, 18, 17],
[28, 29, 30, 31],
[13, 12, 11, 10],
[35, 36, 37, 38],
[6, 5, 4, 3],
[0, 7, 14, 21],
[41, 34, 27, 20],
[1, 8, 15, 22],
[40, 33, 26, 19],
[2, 9, 16, 23],
[39, 32, 25, 18],
[3, 10, 17, 24],
[38, 31, 24, 17],
[4, 11, 18, 25],
[37, 30, 23, 16],
[5, 12, 19, 26],
[36, 29, 22, 15],
[6, 13, 20, 27],
[35, 28, 21, 14],
[0, 8, 16, 24],
[41, 33, 25, 17],
[7, 15, 23, 31],
[34, 26, 18, 10],
[14, 22, 30, 38],
[27, 19, 11, 3],
[35, 29, 23, 17],
[6, 12, 18, 24],
[28, 22, 16, 10],
[13, 19, 25, 31],
[21, 15, 9, 3],
[20, 26, 32, 38],
[36, 30, 24, 18],
[5, 11, 17, 23],
[37, 31, 25, 19],
[4, 10, 16, 22],
[2, 10, 18, 26],
[39, 31, 23, 15],
[1, 9, 17, 25],
[40, 32, 24, 16],
[9, 17, 25, 33],
[8, 16, 24, 32],
[11, 17, 23, 29],
[12, 18, 24, 30],
[1, 2, 3, 4],
[5, 4, 3, 2],
[8, 9, 10, 11],
[12, 11, 10, 9],
[15, 16, 17, 18],
[19, 18, 17, 16],
[22, 23, 24, 25],
[26, 25, 24, 23],
[29, 30, 31, 32],
[33, 32, 31, 30],
[36, 37, 38, 39],
[40, 39, 38, 37],
[7, 14, 21, 28],
[8, 15, 22, 29],
[9, 16, 23, 30],
[10, 17, 24, 31],
[11, 18, 25, 32],
[12, 19, 26, 33],
[13, 20, 27, 34],
]
// Verbinden mit dem WebSocket.
const ws = new WebSocket('ws://localhost:89/ws');
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
const selectedColumn = data.column;
placeChipInColumn(selectedColumn);
};
function placeChipInColumn(column) {
// Beginne am unteren Ende der Spalte und suche das erste freie Feld
for (let i = 5; i >= 0; i--) {
const index = i * 7 + column;
if (!flaechen[index].classList.contains('taken')) {
flaechen[index].classList.add('taken');
if (currentPlayer === 1) {
flaechen[index].classList.add('player-one');
} else {
flaechen[index].classList.add('player-two');
}
checkBoard();
if (currentPlayer === 1) {
currentPlayer = 2;
} else {
currentPlayer = 1;
}
displayCurrentPlayer.innerHTML = currentPlayer;
break;
}
}
}
function checkBoard() {
for (let y = 0; y < gewinnFlaechen.length; y++) {
const square1 = flaechen[gewinnFlaechen[y][0]]
const square2 = flaechen[gewinnFlaechen[y][1]]
const square3 = flaechen[gewinnFlaechen[y][2]]
const square4 = flaechen[gewinnFlaechen[y][3]]
if (
square1.classList.contains('player-one') &&
square2.classList.contains('player-one') &&
square3.classList.contains('player-one') &&
square4.classList.contains('player-one')
)
{
ergebnis.innerHTML = 'Player One Wins!'
}
if (
square1.classList.contains('player-two') &&
square2.classList.contains('player-two') &&
square3.classList.contains('player-two') &&
square4.classList.contains('player-two')
)
{
ergebnis.innerHTML = 'Player Two Wins!'
}
}
}
for (let i = 0; i < flaechen.length; i++) {
flaechen[i].onclick = () => {
if (flaechen[i + 7].classList.contains('taken') &&!flaechen[i].classList.contains('taken')) {
if (currentPlayer == 1) {
flaechen[i].classList.add('taken')
flaechen[i].classList.add('player-one')
currentPlayer = 2
displayCurrentPlayer.innerHTML = currentPlayer
} else if (currentPlayer == 2){
flaechen[i].classList.add('taken')
flaechen[i].classList.add('player-two')
currentPlayer = 1
displayCurrentPlayer.innerHTML = currentPlayer
}
} else alert('Geht nicht')
checkBoard()
}
}
})
four.jpg 0 → 100644
four.jpg

160 KiB

This diff is collapsed.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Connect Four</title>
<link rel="stylesheet" href="style.css">
<script src="app.js" charset="utf-8" defer></script>
</head>
<body>
<h1>Der derzeitige Spieler ist: Spieler <span id="current-player">1</span></h1>
<h3 id="result"></h3>
<img id ="img" src="four.jpg" alt="Girl in a jacket" width="500" height="600"> <div class="grid">
<h1 id="title">4 GEWINNT SPIEL</h1>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="taken"></div>
<div class="taken"></div>
<div class="taken"></div>
<div class="taken"></div>
<div class="taken"></div>
<div class="taken"></div>
<div class="taken"></div>
</div>
</body>
</html>
main.py 0 → 100644
import uvicorn
from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse, Response
import cv2
from cvzone.HandTrackingModule import HandDetector
from imutils.video import VideoStream
import asyncio
app = FastAPI()
# Video-Capture initialisieren
try:
video_capture = VideoStream("http://localhost:88/video_feed").start()
except Exception as e:
print(f"We couldn't reach the camera")
exit()
# Hand-Detektor initialisieren
detector = HandDetector(maxHands=2)
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
print("WebSocket connection accepted")
while True:
frame = video_capture.read()
if frame is None:
continue
# Handgesten-Erkennung
hands, img = detector.findHands(frame, flipType=False)
if hands:
# Zähle die Anzahl der gestreckten Finger
total_fingers = 0
for hand in hands:
fingers = detector.fingersUp(hand)
total_fingers += sum(fingers)
# Begrenze die Fingeranzahl auf 7, da wir 7 Spalten haben (0-6)
selected_column = min(total_fingers, 6)
print("Selected column:", selected_column)
try:
await websocket.send_json({"column": selected_column})
except Exception as e:
print(f"Error sending message: {str(e)}")
# Warte drei Sekunden bevor die nächste Nachricht gesendet wird
await asyncio.sleep(3)
# Bild fürs Debugging anzeigen
cv2.imshow("Video", img)
cv2.waitKey(1)
# Endpoint für die HTML-Seite
@app.get("/", response_class=HTMLResponse)
async def get_html():
with open("index.html", "r") as file:
html_content = file.read()
return HTMLResponse(content=html_content, status_code=200)
# Endpoint für die CSS-Datei
@app.get("/style.css")
async def get_style():
with open("style.css", "r") as file:
css_content = file.read()
return Response(content=css_content, media_type="text/css")
# Endpoint für die JavaScript-Datei
@app.get("/app.js")
async def get_script():
with open("app.js", "r") as file:
script_content = file.read()
return Response(content=script_content, media_type="application/javascript")
# Endpoint für die Bilddatei
@app.get("/four.jpg")
async def get_image():
with open("four.jpg", "rb") as file:
image_content = file.read()
return Response(content=image_content, media_type="image/jpeg")
if __name__ == "__main__":
uvicorn.run(app, host="localhost", port=89)
.grid {
border: 1px solid;
height: 480px;
width: 560px;
display: flex;
flex-wrap: wrap;
background-color: blue;
}
.grid div {
height: 80px;
width: 80px;
}
.player-one {
background-color: red;
border-radius: 40px;
}
.player-two {
background-color: yellow;
border-radius: 40px;
}
#img{
position: absolute;
left: 800px;
}
#title{
position: absolute;
left: 900px;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment