Познание теории вероятности не помогает выиграть — оно лишь даёт абсолютную уверенность в том, что проиграешь.
Вообще, один старый еврей хорошо сказал о тех, кто хочет чего-то достичь “познанием”
Познание теории вероятности не помогает выиграть — оно лишь даёт абсолютную уверенность в том, что проиграешь.
Вообще, один старый еврей хорошо сказал о тех, кто хочет чего-то достичь “познанием”
@BABOS , есть старинная стратегическая игра, ей 1500 лет (не путать с 100500). Напиши ее для браузера с websocket. Вводишь ip соперника, он вводит твой (вы в одной локальной сети). Простенькая, но как начало вполне себе. И кубик не надо кидать.
все решается если есть деньги и время, без них я с наскока не смогу создать))) не занимался ни сайтами, не администрированием…
к тому же сервер поднимать наверное… как по мне лучше уж сделать 3 вебсервер, к которому подключаться будут другие…
мокша пат ? чатурангу ?)))
Трынька.
краткость сестра таланта конечно, но это не тот случай)))
Так вы покажите знания. Пока вы изначально не смогли понять, что задача реализации данной стратегии не потребует сайта. Поэтому пока вы намека для получения Вами вознаграждения для реализации нет. Поэтому Вам никто и не заплатит.
сервера она не потребует ?
ведь это мы реализуем через файл .js…
я может тоже самое делаю, только по своему, но я бы создал один вебсервер, к которому игроки подключались бы, и наблюдали одну и туже картину, не вникая в то что хотите показать вы))) потому что я еще могу понимать что вы предлагаете вообще не так… в любом случае с помощью костылей это можно сделать кучей способов…
Diskless спс что пытаетесь чему научить…))) вот вам пример портирования обычного html для esp32
версия html посмотреть ее можно с пк
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>Калькулятор больших чисел — с копированием</title>
<style>
* {
box-sizing: border-box;
/* Убираем глобальный user-select, чтобы выделение работало */
}
body {
background: linear-gradient(145deg, #2c3e50 0%, #1a2632 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', 'Roboto', 'Monaco', 'Courier New', monospace;
margin: 0;
padding: 20px;
}
.calculator {
background: #1e1f2c;
border-radius: 48px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1);
padding: 24px 20px 28px 20px;
width: 100%;
max-width: 540px;
transition: all 0.2s;
}
.display {
background: #0c0e16;
border-radius: 32px;
padding: 20px 20px;
margin-bottom: 28px;
box-shadow: inset 0 4px 8px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.05);
}
/* выделяемые блоки - теперь можно выделять мышкой */
.copyable {
cursor: text;
transition: background 0.1s ease;
border-radius: 12px;
padding: 4px 8px;
margin: -4px -8px;
user-select: text; /* разрешаем выделение текста */
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
}
.copyable:hover {
background: rgba(255, 255, 255, 0.08);
}
#expression {
font-size: 1.2rem;
color: #8f9bb5;
min-height: 2rem;
word-break: break-all;
text-align: right;
font-family: 'Monaco', 'Menlo', monospace;
letter-spacing: 0.3px;
}
#result {
font-size: 2.6rem;
font-weight: 500;
color: #f0f3ff;
text-align: right;
word-break: break-word;
line-height: 1.2;
font-family: 'Segoe UI', 'Monaco', monospace;
margin-top: 12px;
min-height: 4rem;
}
.buttons {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px 10px;
}
button {
background: #2a2d3e;
border: none;
color: #eef2ff;
font-size: 1.5rem;
font-weight: 500;
padding: 18px 0;
border-radius: 28px;
cursor: pointer;
transition: all 0.1s ease;
box-shadow: 0 3px 0 #12131c;
font-family: inherit;
display: flex;
align-items: center;
justify-content: center;
user-select: none; /* только для кнопок, чтобы при клике не выделялся текст */
}
button:active {
transform: translateY(2px);
box-shadow: 0 1px 0 #12131c;
}
.span-2 {
grid-column: span 2;
}
.func {
background: #3a2e4a;
color: #d9c8ff;
font-size: 1.2rem;
}
.num {
background: #353b4e;
font-size: 1.6rem;
font-weight: 600;
}
.eq {
background: #4f46e5;
color: white;
box-shadow: 0 3px 0 #2e1f8a;
}
.clear {
background: #3b2a3a;
color: #ffa7c4;
}
.danger {
background: #5e2a3a;
color: #ffb3c6;
}
@media (max-width: 480px) {
.buttons {
gap: 8px;
}
button {
padding: 14px 0;
font-size: 1.2rem;
}
#result {
font-size: 1.9rem;
}
}
/* подсказка для копирования */
.copy-tip {
text-align: right;
font-size: 0.7rem;
color: #6b7280;
margin-top: 8px;
padding-right: 8px;
user-select: none;
}
</style>
</head>
<body>
<div class="calculator">
<div class="display">
<div id="expression" class="copyable"></div>
<div id="result" class="copyable">0</div>
<div class="copy-tip">💡 Кликните на выражение или ответ и нажмите Ctrl+C (Cmd+C) для копирования</div>
</div>
<div class="buttons">
<button class="func clear" data-action="clear">C</button>
<button class="func" data-action="backspace">⌫</button>
<button class="func" data-action="percent">%</button>
<button class="func" data-op="/">÷</button>
<button class="func" data-op="*">×</button>
<button class="num" data-num="7">7</button>
<button class="num" data-num="8">8</button>
<button class="num" data-num="9">9</button>
<button class="func" data-op="-">-</button>
<button class="func" data-op="+">+</button>
<button class="num" data-num="4">4</button>
<button class="num" data-num="5">5</button>
<button class="num" data-num="6">6</button>
<button class="func span-2" data-action="sqrt">√x</button>
<button class="num" data-num="1">1</button>
<button class="num" data-num="2">2</button>
<button class="num" data-num="3">3</button>
<button class="func" data-action="square">x²</button>
<button class="func" data-action="reciprocal">1/x</button>
<button class="num" data-num="0">0</button>
<button class="num" data-dot=".">.</button>
<button class="func" data-action="sign">±</button>
<button class="func" data-action="leftParen">(</button>
<button class="func" data-action="rightParen">)</button>
<button class="func eq span-2" data-action="equals">=</button>
<button class="func" data-action="exp">exp</button>
<button class="func" data-action="pow10">10ˣ</button>
</div>
</div>
<script>
// ---------- Состояние ----------
let currentInput = "0";
let pendingEval = false;
let lastResult = null;
let lastExpression = "";
const expressionDiv = document.getElementById("expression");
const resultDiv = document.getElementById("result");
// ---------- Безопасное вычисление с поддержкой больших чисел ----------
function isIntegerExpression(expr) {
if (/\./.test(expr)) return false;
if (expr.includes('/')) return false;
const tokens = expr.match(/\d+(?:\.\d+)?|[\+\-\*\/\(\)%]/g);
if(!tokens) return false;
for(let t of tokens) {
if(/^\d+(?:\.\d+)?$/.test(t) && t.includes('.')) return false;
}
return true;
}
function evaluateSafe(expr) {
expr = expr.trim();
if (expr === "") return "0";
let jsExpr = expr.replace(/×/g, '*').replace(/÷/g, '/');
if (isIntegerExpression(jsExpr) && !jsExpr.includes('**') && !jsExpr.includes('sqrt') && !jsExpr.includes('pow')) {
try {
if (jsExpr.includes('(') || jsExpr.includes(')')) {
let val = eval(jsExpr);
if (isNaN(val) || !isFinite(val)) throw new Error();
return String(val);
}
let bigExpr = jsExpr.replace(/(\d+)/g, (m) => `${m}n`);
let withMod = bigExpr.replace(/%/g, '*');
if (withMod.includes('%')) return String(eval(jsExpr));
let resultBig = eval(bigExpr);
return resultBig.toString();
} catch(e) {
let val = eval(jsExpr);
if (isNaN(val) || !isFinite(val)) return "Ошибка";
return String(val);
}
} else {
try {
let result = eval(jsExpr);
if (isNaN(result) || !isFinite(result)) return "Ошибка";
if (Math.abs(result) > 1e15 && Number.isInteger(result)) {
return result.toFixed(0);
}
if (typeof result === 'number') {
if (Math.abs(result) > 1e12) return result.toExponential(10);
let str = result.toFixed(12).replace(/\.?0+$/, '');
return str;
}
return String(result);
} catch (err) {
return "Ошибка";
}
}
}
function updateDisplay() {
expressionDiv.innerText = lastExpression || "";
resultDiv.innerText = currentInput;
}
function setResult(value) {
currentInput = value;
lastExpression = "";
updateDisplay();
}
function handleNumber(num) {
if (pendingEval) {
currentInput = "0";
pendingEval = false;
lastExpression = "";
}
if (currentInput === "0" && !currentInput.includes('.')) {
currentInput = num;
} else {
currentInput += num;
}
updateDisplay();
}
function handleDot() {
if (pendingEval) {
currentInput = "0";
pendingEval = false;
lastExpression = "";
}
if (!currentInput.includes('.')) {
currentInput += ".";
}
updateDisplay();
}
function handleOperator(op) {
if (pendingEval) {
pendingEval = false;
lastExpression = currentInput;
}
let expr = lastExpression + currentInput;
if (/[+\-*\/÷×]$/.test(expr)) {
expr = expr.slice(0, -1);
}
let newExpr = expr + op;
lastExpression = newExpr;
currentInput = "0";
updateDisplay();
}
function handleEquals() {
if (pendingEval) return;
let fullExpr = lastExpression + currentInput;
if (fullExpr === "") fullExpr = currentInput;
if (/[+\-*\/÷×]$/.test(fullExpr)) fullExpr = fullExpr.slice(0, -1);
if (fullExpr === "") {
currentInput = "0";
lastExpression = "";
updateDisplay();
return;
}
let result = evaluateSafe(fullExpr);
if (result === "Ошибка") {
currentInput = "Ошибка";
lastExpression = "";
} else {
currentInput = result;
lastExpression = fullExpr + "=";
pendingEval = true;
lastResult = result;
}
updateDisplay();
}
function clearAll() {
currentInput = "0";
lastExpression = "";
pendingEval = false;
updateDisplay();
}
function backspace() {
if (pendingEval) {
clearAll();
return;
}
if (currentInput.length === 1 || (currentInput.length === 2 && currentInput.startsWith("-"))) {
currentInput = "0";
} else {
currentInput = currentInput.slice(0, -1);
}
updateDisplay();
}
function changeSign() {
if (pendingEval) {
currentInput = "0";
pendingEval = false;
lastExpression = "";
}
let val = parseFloat(currentInput);
if (isNaN(val)) val = 0;
let newVal = (-val).toString();
if (currentInput.includes('.') && !newVal.includes('.')) {
if (currentInput.split('.')[1].length > 0) {
newVal = (-val).toFixed(currentInput.split('.')[1].length);
}
}
currentInput = newVal;
updateDisplay();
}
function handleFunction(func) {
if (pendingEval) {
lastExpression = "";
pendingEval = false;
}
let val;
try {
val = parseFloat(currentInput);
if (isNaN(val)) val = 0;
} catch(e) { val = 0; }
let resultNum;
switch(func) {
case 'square': resultNum = val * val; break;
case 'sqrt': resultNum = Math.sqrt(val); break;
case 'reciprocal':
if (val === 0) { currentInput = "Ошибка"; updateDisplay(); return; }
resultNum = 1 / val; break;
case 'exp': resultNum = Math.exp(val); break;
case 'pow10': resultNum = Math.pow(10, val); break;
default: return;
}
if (isNaN(resultNum) || !isFinite(resultNum)) {
currentInput = "Ошибка";
} else {
if (Number.isInteger(resultNum) && Math.abs(resultNum) < 1e15) {
currentInput = resultNum.toString();
} else if (Math.abs(resultNum) > 1e12) {
currentInput = resultNum.toExponential(10);
} else {
let str = resultNum.toFixed(10).replace(/\.?0+$/, '');
currentInput = str;
}
}
lastExpression = func + "(" + val + ") =";
pendingEval = true;
updateDisplay();
}
function handlePercent() {
if (pendingEval) clearAll();
let currentVal = parseFloat(currentInput);
if (isNaN(currentVal)) currentVal = 0;
let percentVal = currentVal / 100;
currentInput = percentVal.toString();
updateDisplay();
}
function handleParen(p) {
if (pendingEval) {
lastExpression = "";
pendingEval = false;
currentInput = "0";
}
let expr = lastExpression + currentInput;
lastExpression = expr + p;
currentInput = "";
updateDisplay();
}
// ---------- Привязка обработчиков к кнопкам ----------
document.querySelectorAll("[data-num]").forEach(btn => {
btn.addEventListener("click", () => handleNumber(btn.getAttribute("data-num")));
});
document.querySelector("[data-dot]")?.addEventListener("click", handleDot);
document.querySelectorAll("[data-op]").forEach(btn => {
btn.addEventListener("click", () => handleOperator(btn.getAttribute("data-op")));
});
document.querySelector("[data-action='equals']")?.addEventListener("click", handleEquals);
document.querySelector("[data-action='clear']")?.addEventListener("click", clearAll);
document.querySelector("[data-action='backspace']")?.addEventListener("click", backspace);
document.querySelector("[data-action='sign']")?.addEventListener("click", changeSign);
document.querySelector("[data-action='square']")?.addEventListener("click", () => handleFunction("square"));
document.querySelector("[data-action='sqrt']")?.addEventListener("click", () => handleFunction("sqrt"));
document.querySelector("[data-action='reciprocal']")?.addEventListener("click", () => handleFunction("reciprocal"));
document.querySelector("[data-action='exp']")?.addEventListener("click", () => handleFunction("exp"));
document.querySelector("[data-action='pow10']")?.addEventListener("click", () => handleFunction("pow10"));
document.querySelector("[data-action='percent']")?.addEventListener("click", handlePercent);
document.querySelector("[data-action='leftParen']")?.addEventListener("click", () => handleParen("("));
document.querySelector("[data-action='rightParen']")?.addEventListener("click", () => handleParen(")"));
// Инициализация
updateDisplay();
</script>
</body>
</html>
можно портировать на веб сервер esp32, мы же тут мк программируем)))
#include <WiFi.h>
#include <WebServer.h>
WebServer server(80);
// ВАШ HTML КОД ВСТАВЛЯЕТСЯ СЮДА
const char index_html[] PROGMEM = R"rawliteral(
//тут просто вставить html
)rawliteral";
void setup() {
Serial.begin(115200);
WiFi.softAP("ESP32_Server", "12345678");
server.on("/", []() {
server.send(200, "text/html", index_html);
});
server.begin();
Serial.println("Сервер запущен");
}
void loop() {
server.handleClient();
}
в целом не понимаю зачем мне что то там делать иначе… но у каждого свои задачи, мне удобнее так решать, если надо сделаю проверку id что бы другой игрок не смог кидать чужой кубик… или еще что… все можно добавить, и все ручками!))) такой способ для чего то может и не подойдет, а кому то может наоборот понравится легко добавлять в свой код часть логики на html, конечно там надо много примеров выложить c парсером данных еще… но может сами вникнут, я просто примерно показал инструмент)))