Refactoring

main
selim 2025-01-02 16:28:32 +01:00
parent 26a0a195c2
commit bc6b3f9487
9 changed files with 252 additions and 282 deletions

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/src/assets/react.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CONNECT4</title>
</head>

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,40 @@
#app-container{
font-family: Arial, Helvetica, sans-serif;
}
.gamemode {
text-align: center;
margin-left: auto;
margin-right: auto;
width: 300px;
height: 202px;
border: 5px solid black;
background-color: blue;
}
.gamemode-selection {
margin-top: 34px;
border: 3px solid black;
width: 50%;
height: 50px;
font-size: larger;
}
.gamemode-selection:hover {
cursor: pointer;
background-color: lightgray;
}
.message{
text-align: center;
font-size: larger;
}
.heading{
text-align: center;
transition: font-size 1s ease-out 100ms;
}
.heading:hover{
font-size:3em;
}

View File

@ -0,0 +1,62 @@
import { useState } from "react";
import { clickHandlerGamemode } from "./AppFunctions.js";
import "./App.css";
import Board from "../Board/Board.jsx";
export const self = {};
const App = () => {
const [menu, setMenu] = useState(true);
self.menu = menu;
self.setMenu = setMenu;
const [gamemode, setGamemode] = useState(0);
self.gamemode = gamemode;
self.setGamemode = setGamemode;
return (
<div id="app-container">
<Heading />
<Gamemode />
<Board />
<Message />
</div>
);
};
const Gamemode = () => (
<div className="gamemode" hidden={!self.menu}>
<button
className="gamemode-selection"
onClick={async () => await clickHandlerGamemode(self, 1)}
>
singleplayer
</button>
<br />
<button
className="gamemode-selection"
onClick={async () => await clickHandlerGamemode(self, 2)}
>
multiplayer
</button>
</div>
);
const Heading = () => (
<h1 className="heading" hidden={!self.menu}>
CONNECT4
</h1>
);
const Message = () => {
const [message, setMessage] = useState("");
self.message = message;
self.setMessage = setMessage;
return (
<p className="message" hidden={self.menu}>
{message}
</p>
);
};
export default App;

View File

@ -0,0 +1,4 @@
export const clickHandlerGamemode = async (self, gamemode) => {
await self.setMenu(false);
await self.setGamemode(gamemode);
};

View File

@ -1,9 +1,3 @@
body {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
color: black;
}
.board-outer {
width: 600px;
border: 5px solid black;
@ -31,7 +25,17 @@ body {
outline-offset: -7px;
}
.inner-button {
.board-action{
display: flex;
align-items: center;
justify-content: center;
margin-left: auto;
margin-right: auto;
margin-top: 30px;
margin-bottom: 30px;
}
.action-button {
width: 17%;
height: 60px;
font-size: larger;
@ -45,73 +49,11 @@ body {
font-size: x-large;
}
.inner-button:hover {
.action-button:hover {
cursor: pointer;
background-color: lightgray;
}
#board-load-button{
margin-left: 16.1%;
}
.flex-box .inner-button{
width: 200px;
}
.board-state .inner-button:disabled{
margin-left: 16.1%;
color: black;
background-color: lightgray;
border-color: black;
cursor: not-allowed ;
}
.gamemode-div {
margin-left: auto;
margin-right: auto;
width: 300px;
height: 202px;
border: 5px solid black;
background-color: blue;
}
.gamemode-div .gamemode-button {
margin-top: 34px;
border: 3px solid black;
width: 50%;
height: 50px;
font-size: larger;
}
.gamemode-div .gamemode-button:hover {
cursor: pointer;
background-color: lightgray;
}
.message {
font-size: larger;
}
.heading{
transition: font-size 1s ease-out 100ms;
}
.heading:hover{
font-size:3em;
}
.board-rw{
height: 40px;
width: 60%;
border: 3px solid black;
font-size: medium;
margin-right: auto;
}
.board-state{
display: flex;
align-items: center;
@ -123,21 +65,24 @@ body {
margin-top: 10px;
}
.action-bar{
display: flex;
align-items: center;
justify-content: center;
margin-left: auto;
margin-right: auto;
margin-bottom: 30px;
.board-state-action{
margin-right: 3%;
}
.board-state .inner-button{
.board-state-number{
height: 40px;
width: 60%;
border: 3px solid black;
font-size: medium;
}
.board-state .board-action{
margin-top: 0px;
margin-bottom: 0px;
}
.board-state .action-button{
width: 100px;
height: 48px;
}
.field-div{
width: 20%;
margin-left: auto;
}

View File

@ -2,15 +2,14 @@ import { useState } from "react";
import {
clickHandlerTurn,
clickHandlerRestart,
clickHandlerGamemode,
clickHandlerReturn,
clickHandlerLoadBoard,
clickHandlerCopyClipboard,
} from "./functions";
} from "./BoardFunctions.js";
import "./Board.css";
import { self } from "../App/App.jsx";
const self = {};
export default function App() {
const Board = () => {
const [colorBoard, setColorBoard] = useState(
Array.from(Array(6), () => new Array(7).fill("white"))
);
@ -31,37 +30,48 @@ export default function App() {
self.currentPlayer = currentPlayer;
self.setCurrentPlayer = setCurrentPlayer;
const [message, setMessage] = useState("");
self.message = message;
self.setMessage = setMessage;
const [turns, setTurns] = useState(0);
self.turns = turns;
self.setTurns = setTurns;
const [menu, setMenu] = useState(true);
self.menu = menu;
self.setMenu = setMenu;
const [gamemode, setGamemode] = useState(0);
self.gamemode = gamemode;
self.setGamemode = setGamemode;
const [turnsMem, setTurnsMem] = useState("");
self.turnsMem = turnsMem;
self.setTurnsMem = setTurnsMem;
return (
<>
<Heading />
<Gamemode />
<Board />
<Message />
</>
const fields = colorBoard.map((subarr, row) =>
subarr.map((color, col) => {
return (
<Field
key={row.toString() + col.toString()}
row={row}
col={col}
style={{
backgroundColor: color,
outlineWidth: outlineBoard[row][col].split(" ")[0],
outlineColor: outlineBoard[row][col].split(" ")[2],
outlineStyle: outlineBoard[row][col].split(" ")[1],
}}
disabled={row === 0 ? gameOver : true}
/>
);
})
);
}
function Field({ row, col, style, disabled }) {
return (
<div className="board-outer" hidden={self.menu}>
<div className="board-inner">
{fields.map((subarr) => subarr.map((field) => field))}
</div>
<BoardState />
<div className="board-action">
<Return />
<Restart />
</div>
</div>
);
};
const Field = ({ row, col, style, disabled }) => {
const [pointer, setPointer] = useState(false);
const [hoverColor, setHoverColor] = useState("white");
@ -108,106 +118,9 @@ function Field({ row, col, style, disabled }) {
&nbsp;
</button>
);
}
};
function Board() {
const fields = self.colorBoard.map((subarr, row) =>
subarr.map((color, col) => {
return (
<Field
key={row.toString() + col.toString()}
row={row}
col={col}
style={{
backgroundColor: color,
outlineWidth: self.outlineBoard[row][col].split(" ")[0],
outlineColor: self.outlineBoard[row][col].split(" ")[2],
outlineStyle: self.outlineBoard[row][col].split(" ")[1],
}}
disabled={row === 0 ? self.gameOver : true}
/>
);
})
);
const displayMem = self.menu ? "none" : "";
const displayState = self.gamemode === 1 ? "none" : "";
return (
<div className="board-outer" style={{ display: displayMem }}>
<div className="board-inner">
{fields.map((subarr) => subarr.map((field) => field))}
</div>
<BoardState display={displayState} />
<br />
<div className="action-bar">
<Return />
<Restart />
</div>
</div>
);
}
function Restart() {
return (
<button
className="inner-button"
id="restart"
hidden={!self.gameOver}
onClick={() => clickHandlerRestart(self)}
>
&#8634;
</button>
);
}
function Return() {
return (
<button className="inner-button" onClick={() => clickHandlerReturn(self)}>
menu
</button>
);
}
function Gamemode() {
return (
<div className="gamemode-div" hidden={!self.menu}>
<button
className="gamemode-button"
onClick={() => clickHandlerGamemode(self, 1)}
>
singleplayer
</button>
<br />
<button
className="gamemode-button"
onClick={() => clickHandlerGamemode(self, 2)}
>
multiplayer
</button>
</div>
);
}
function Message() {
const displayMem = self.menu ? "none" : "";
return (
<p className="message" style={{ display: displayMem }}>
{self.message}
</p>
);
}
function Heading() {
const displayMem = !self.menu ? "none" : "";
return (
<h1 className="heading" style={{ display: displayMem }}>
CONNECT4
</h1>
);
}
function BoardState({ display }) {
const BoardState = () => {
const [boardDecimal, setBoardDecimal] = useState("");
self.boardDecimal = boardDecimal;
self.setBoardDecimal = setBoardDecimal;
@ -221,11 +134,11 @@ function BoardState({ display }) {
self.setShowCopy = setShowCopy;
return (
<div style={{ display: display }}>
<div hidden={self.gamemode !== 2}>
<div className="board-state">
<div className="field-div">
<div className="board-state-action">
<button
className="inner-button"
className="action-button"
onClick={() => {
clickHandlerCopyClipboard(self);
}}
@ -234,29 +147,52 @@ function BoardState({ display }) {
</button>
</div>
<input
className="board-rw"
id="1"
className="board-state-number"
type="text"
readOnly={true}
value={self.showCopy ? "copied to clipboard!" : self.boardDecimal}
value={showCopy ? "copied to clipboard!" : boardDecimal}
name="board-state-output"
/>
</div>
<div className="board-state">
<div className="field-div">
<div className="board-state-action">
<button
className="inner-button"
onClick={() => clickHandlerLoadBoard(self, self.inputDecimal)}
className="action-button"
onClick={() => clickHandlerLoadBoard(self, inputDecimal)}
>
load
</button>
</div>
<input
className="board-rw"
type="text"
value={self.inputDecimal}
onChange={(i) => setInputDecimal(i.target.value)}
className="board-state-number"
type="number"
min="7"
max="6239465226101869857685537024892857210"
step="1"
value={inputDecimal === 0 ? "" : inputDecimal}
name="board-state-input"
onChange={(i) => setInputDecimal(Math.floor(i.target.value))}
/>
</div>
</div>
);
}
};
const Return = () => (
<button className="action-button" onClick={() => clickHandlerReturn(self)}>
menu
</button>
);
const Restart = () => (
<button
className="action-button"
id="restart"
hidden={!self.gameOver}
onClick={() => clickHandlerRestart(self)}
>
&#8634;
</button>
);
export default Board;

View File

@ -1,10 +1,10 @@
async function putChip(
const putChip = async (
col,
colorBoard,
currentPlayer,
setColorBoard,
setCurrentPlayer
) {
) => {
for (let row = 5; row >= 0; row--) {
if (colorBoard[row][col] === "white") {
if (currentPlayer === "red") {
@ -23,14 +23,14 @@ async function putChip(
}
}
return false;
}
};
async function checkWin(
const checkWin = async (
colorBoard,
currentPlayer,
outlineBoard,
setOutlineBoard
) {
) => {
const memOutlineBoard = outlineBoard;
for (let row = 0; row <= 5; row++) {
@ -90,28 +90,44 @@ async function checkWin(
}
return false;
}
};
function botChoice(colorBoard) {
const botChoice = (colorBoard) => {
while (true) {
const rand = Math.floor(Math.random() * 7);
if (colorBoard[0][rand] === "white") {
return rand;
}
}
}
};
export function colFull(col, colorBoard) {
for (let row = 5; row >= 0; row--) {
if (colorBoard[row][col] === "white") {
return false;
} else {
return true;
}
const sepToDec = (sep) => {
let res = 0n;
let ind = 0n;
let mem = sep.split("").reverse().join("");
while (ind < mem.length) {
res = BigInt(7n ** ind * BigInt(mem[ind])) + res;
ind++;
}
}
res = BigInt(7n ** ind) + res;
export async function clickHandlerTurn(self, col) {
return res;
};
const decToSep = (dec) => {
let mem = BigInt(dec);
let res = "";
while (mem > 0n) {
res = (mem % 7n).toString() + res;
mem = mem / 7n;
}
res = res.slice(1, res.length);
return res;
};
export const clickHandlerTurn = async (self, col) => {
const iMax = self.gamemode === 1 ? 2 : 1;
for (let i = 0; i < iMax; i++) {
@ -166,9 +182,9 @@ export async function clickHandlerTurn(self, col) {
if (self.gamemode === 2) {
await self.setBoardDecimal(sepToDec(self.turnsMem).toString());
}
}
};
export async function clickHandlerRestart(self) {
export const clickHandlerRestart = async (self) => {
await self.setTurns(0);
await self.setGameOver(false);
await self.setCurrentPlayer("red");
@ -182,14 +198,9 @@ export async function clickHandlerRestart(self) {
await self.setTurnsMem("");
await self.setBoardDecimal("");
await self.setInputDecimal("");
}
};
export async function clickHandlerGamemode(self, gamemode) {
await self.setMenu(false);
await self.setGamemode(gamemode);
}
export async function clickHandlerReturn(self) {
export const clickHandlerReturn = async (self) => {
await self.setMenu(true);
await self.setTurns(0);
await self.setGameOver(false);
@ -204,9 +215,9 @@ export async function clickHandlerReturn(self) {
await self.setTurnsMem("");
await self.setBoardDecimal("");
await self.setInputDecimal("");
}
};
export async function clickHandlerLoadBoard(self, dec) {
export const clickHandlerLoadBoard = async (self, dec) => {
let sep = decToSep(dec);
await clickHandlerRestart(self);
@ -214,38 +225,12 @@ export async function clickHandlerLoadBoard(self, dec) {
await clickHandlerTurn(self, sep[sep.length - 1]);
sep = sep.slice(0, -1);
}
}
};
export async function clickHandlerCopyClipboard(self) {
export const clickHandlerCopyClipboard = async (self) => {
navigator.clipboard.writeText(self.boardDecimal);
self.setShowCopy(true);
setTimeout(() => {
self.setShowCopy(false);
}, 1500);
}
function sepToDec(sep) {
let res = 0n;
let ind = 0n;
let mem = sep.split("").reverse().join("");
while (ind < mem.length) {
res = BigInt(7n ** ind * BigInt(mem[ind])) + res;
ind++;
}
res = BigInt(7n ** ind) + res;
return res;
}
function decToSep(dec) {
let mem = BigInt(dec);
let res = "";
while (mem > 0n) {
res = (mem % 7n).toString() + res;
mem = mem / 7n;
}
res = res.slice(1, res.length);
return res;
}
};

View File

@ -1,7 +1,6 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.jsx";
import App from "./components/App/App.jsx";
createRoot(document.getElementById("root")).render(
<StrictMode>