Krzyżówki Online
Odkryj świat interaktywnych krzyżówek! Wejdź do gry, w której Twoje zainteresowania naprawdę mają znaczenie. Wybierz dziedzinę, dopasuj poziom trudności i zanurz się w zestawie zagadek, które za każdym razem są inne, generowane dynamicznie przy każdym uruchomieniu.
Sprawdzaj wiedzę i rozwijaj umysł To idealny sposób na trening pamięci, utrwalanie pojęć i poszerzanie wiedzy — niezależnie od tego, czy wolisz programowanie, geografię, fotografię czy fizykę.
Rywalizuj ze sobą i zdobywaj kolejne poziomy Każda krzyżówka to nowa szansa, by udowodnić, że poradzisz sobie z wyzwaniami — szybciej, lepiej i dokładniej niż wcześniej.
Gotowy na wyzwanie? Kliknij, wybierz zestaw i rozpocznij przygodę. Za każdym razem czeka na Ciebie nowa łamigłówka — sprawdź, jak daleko zajdziesz!
- Wybierz dziedzinę i poziom trudności,
- Kliknij na jedno z pól oznaczonych cyferką i wprowadź odpowiedź,
- Wypełnij wszystkie pola,
- Kliknij przycisk Sprawdź.
Odpowiedzi możesz poprawiać również po sprawdzeniu, klikając w podświetlone czerwone lub zielone pola i wprowadzając odpowiedź ponownie. Kierunek wprowadzania odpowiedzi możesz zmieniać wciskając Shift w trakcie wprowadzania odpowiedzi.
Pytania poziomo:
Pytania pionowo:
Kierunek: poziomo · Shift — zmiana kierunku.
Kod po stronie przeglądarki
<style>
.max-vh-75 {
max-height: 75vh !important;
}
.grid { margin-bottom: 1rem; }
.cell {
width: 36px;
height: 36px;
padding: 0;
position: relative;
}
.cell .letter {
width: 100%;
height: 100%;
text-align: center;
border: none;
background: transparent;
}
/* numer pola */
.cell .number {
font-size: 0.65rem;
pointer-events: none;
}
[data-bs-theme=light] .cell { border: 1px solid #212529; }
[data-bs-theme=light] .cell.black { background:#212529; }
[data-bs-theme=light] .cell.black input { background:#212529 !important; color:transparent; pointer-events:none; opacity: 0;}
[data-bs-theme=golden] .cell { border: 1px solid #4a2f1b; }
[data-bs-theme=golden] .cell.black { background:#4a2f1b; }
[data-bs-theme=golden] .cell.black input { background:#4a2f1b !important; color:transparent; pointer-events:none; opacity: 0;}
[data-bs-theme=twilight] .cell { border: 1px solid #f3f6ff; }
[data-bs-theme=twilight] .cell.black { background:#f3f6ff; }
[data-bs-theme=twilight] .cell.black input { background:#f3f6ff !important; color:transparent; pointer-events:none; opacity: 0;}
[data-bs-theme=dark] .cell { border: 1px solid #f8f9fa; }
[data-bs-theme=dark] .cell.black { background:#f8f9fa; }
[data-bs-theme=light] .cell.black input { background:#f8f9fa !important; color:transparent; pointer-events:none; opacity: 0;}
.ok { background: var(--bs-success) !important; color: #ffffff !important}
.bad { background: var(--bs-danger) !important; color: #ffffff !important}
</style>
<div id="app">
<div class="row">
<div class="col-md-6 mb-3">
<label for="domain" class="form-label">Dziedzina</label>
<select class="form-select" id="domain" data-bind="value: domain">
<option value="programming">programowanie</option>
<option value="physics">fizyka</option>
<option value="photography">fotografia</option>
<option value="geography">geografia</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="level" class="form-label">Poziom trudności</label>
<select class="form-select" id="level" data-bind="value: level">
<option value="beginner">początkujący</option>
</select>
</div>
</div>
<!-- ko if: loading -->
<div class="d-flex justify-content-center mb-3">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<!-- /ko -->
<div class="row">
<div class="col-md-6 mb-3">
<div class="max-vh-75 overflow-auto">
<!-- ko if: questionsH().length > 0 -->
<h2 class="h5">Pytania poziomo:</h2>
<ul data-bind="foreach: questionsH" class="list-group list-group-flush">
<li class="list-group-item" data-bind="text: $data"></li>
</ul>
<!-- /ko -->
<!-- ko if: questionsV().length > 0 -->
<h2 class="h5">Pytania pionowo:</h2>
<ul data-bind="foreach: questionsV" class="list-group list-group-flush">
<li class="list-group-item" data-bind="text: $data"></li>
</ul>
<!-- /ko -->
</div>
</div>
<div class="col-md-6 mb-3">
<p>
Kierunek: <b id="dirLabel">poziomo</b> ·
<kbd>Shift</kbd> — zmiana kierunku.
</p>
<table class="grid table table-borderless">
<tbody data-bind="foreach: crossdata">
<tr data-bind="foreach: $data">
<td class="cell position-relative"
data-bind="css: { black: $data === null }">
<!-- numer pola z mapy numbers -->
<span class="number position-absolute top-0 start-0 ms-1 mt-1 small fw-bold"
data-bind="
text: $root.numbers()[$parentContext.$index()] &&
$root.numbers()[$parentContext.$index()][$index()],
visible: $root.numbers()[$parentContext.$index()] &&
$root.numbers()[$parentContext.$index()][$index()] !== null
">
</span>
<!-- pole do wprowadzenia liter -->
<input class="letter"
data-bind="
attr: {
disabled: $data === null,
'data-row': $parentContext.$index(),
'data-col': $index()
}
" aria-label="Wprowadź literę">
</td>
</tr>
</tbody>
</table>
<button id="checkBtn" class="btn btn-primary">Sprawdź</button>
<button id="resetBtn" class="btn btn-secondary ms-2">Wyczyść</button>
<span id="result" class="ms-3 fw-bold"></span>
</div>
</div>
</div>
<script>
// --------------------------------------
// Twój ViewModel
// --------------------------------------
let ViewModel = null;
let vm = null;
document.addEventListener('DOMContentLoaded', function () {
ViewModel = function() {
const self = this;
self.questionsH = ko.observableArray();
self.questionsV = ko.observableArray();
self.numbers = ko.observableArray();
self.crossdata = ko.observableArray();
self.numRows = ko.observable(0);
self.numCols = ko.observable(0);
self.domain = ko.observable('programming');
self.level = ko.observable('beginner');
self.domain.subscribe(function(newVal){
self.load(newVal, null); // teraz zawsze dostaniesz aktualną wartość
});
self.level.subscribe(function(newVal){
self.load(null, newVal); // teraz zawsze dostaniesz aktualną wartość
});
self.loading = ko.observable(false);
self.load = function(domain = null, level = null)
{
self.loading(true);
self.questionsH([]);
self.questionsV([]);
self.numbers([]);
self.crossdata([]);
const params = {
operation: 'load',
inputdata: [],
domain: domain ?? self.domain(),
level: level ?? self.level(),
token: '0231d9d8947cc211ad8b3063834753f5cbde4754'
};
axios.post(urlSite('public/ajax/app/exec/42'), params, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
.then(function(response) {
const data = response.data;
self.questionsH(data.data.questions.horizontal);
self.questionsV(data.data.questions.vertical);
self.numbers(data.data.numbers);
self.crossdata(data.data.crossdata);
self.numRows(data.meta.rows);
self.numCols(data.meta.cols);
initCrosswordLogic();
document.getElementById('result').textContent = '';
self.loading(false);
}).catch(function(error) {
self.loading(false);
BootstrapToast.show({title: 'Błąd', message: error.response.data.message, when: 'teraz', type: 'danger', icon: 'bi-x-circle-fill'});
});
};
};
vm = new ViewModel();
ko.applyBindings(vm, document.getElementById('app'));
vm.load();
});
// --------------------------------------
// Funkcja inicjalizująca oryginalną logikę
// --------------------------------------
function initCrosswordLogic() {
const allInputs = Array.from(
document.querySelectorAll('input[data-row][data-col]')
);
const inputs = allInputs.filter(i => !i.disabled);
const resultEl = document.getElementById('result');
let direction = 'right';
const numRows = vm.numRows();
const numCols = vm.numCols();
const dirLabel = document.getElementById('dirLabel');
const setDir = (d) => {
direction = d;
dirLabel.textContent = d === 'right' ? 'poziomo' : 'pionowo';
};
function cell(r,c){return allInputs.find(i=>i.dataset.row==r && i.dataset.col==c)}
function nextRight(i){
let r=+i.dataset.row, c=+i.dataset.col+1;
while(c<=numCols){
const x=cell(r,c); if(x && !x.disabled) return x;
c++;
}
return null;
}
function prevLeft(i){
let r=+i.dataset.row, c=+i.dataset.col-1;
while(c>=1){
const x=cell(r,c); if(x && !x.disabled) return x;
c--;
}
return null;
}
function nextDown(i){
let r=+i.dataset.row+1, c=+i.dataset.col;
while(r<=numRows){
const x=cell(r,c); if(x && !x.disabled) return x;
r++;
}
return null;
}
function prevUp(i){
let r=+i.dataset.row-1, c=+i.dataset.col;
while(r>=1){
const x=cell(r,c); if(x && !x.disabled) return x;
r--;
}
return null;
}
// Not used
//if(inputs[0]) inputs[0].focus();
inputs.forEach(field => {
field.maxLength = 1;
field.addEventListener('input', () => {
field.value = field.value.toUpperCase().slice(0,1);
if(field.value){
const nxt = direction==='right' ? nextRight(field) : nextDown(field);
if(nxt) nxt.focus();
}
});
field.addEventListener('keydown', e => {
if(e.key === 'Shift'){
setDir(direction === 'right' ? 'down' : 'right');
return;
}
if(e.key === 'Backspace'){
if(field.value === ''){
e.preventDefault();
const prev = direction==='right' ? prevLeft(field) : prevUp(field);
if(prev){
prev.focus();
prev.value = '';
}
}
return;
}
if(e.key === 'ArrowRight'){
e.preventDefault();
const x = nextRight(field); if(x) x.focus();
return;
}
if(e.key === 'ArrowLeft'){
e.preventDefault();
const x = prevLeft(field); if(x) x.focus();
return;
}
if(e.key === 'ArrowDown'){
e.preventDefault();
const x = nextDown(field); if(x) x.focus();
return;
}
if(e.key === 'ArrowUp'){
e.preventDefault();
const x = prevUp(field); if(x) x.focus();
return;
}
});
field.addEventListener('click', e=>{
if(e.shiftKey) setDir(direction==='right' ? 'down' : 'right');
});
});
// sprawdzanie
document.getElementById('checkBtn').onclick = () => {
let correct = 0;
let total = 0;
let inputData = [];
inputs.forEach(i=>{
inputData.push({
row: i.dataset.row,
col: i.dataset.col,
value: i.value
});
});
const params = {
operation: 'check',
inputdata: inputData,
domain: vm.domain(),
level: vm.level(),
token: '0231d9d8947cc211ad8b3063834753f5cbde4754'
};
axios.post(urlSite('public/ajax/app/exec/42'), params, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
.then(function(response) {
const data = response.data.data;
let index = 0;
inputs.forEach(i=>{
const correctResult = data[index].correct;
total++;
i.classList.remove('ok','bad');
if(correctResult)
{
correct++;
i.classList.add('ok');
} else
{
i.classList.add('bad');
}
index++;
});
if (correct === total)
{
resultEl.textContent = "Wszystko poprawnie!";
BootstrapToast.show({
title: 'Świetna robota!',
message: 'Udało Ci się poprawnie rozwiązać całą krzyżówkę!',
when: 'teraz',
type: 'success',
icon: 'bi-check-circle-fill'
});
}
else
{
resultEl.textContent = `Poprawnych: ${correct} z ${total}`;
BootstrapToast.show({
title: 'Jeszcze chwilka!',
message: 'Niektóre odpowiedzi wymagają poprawek. Sprawdź ponownie i spróbuj jeszcze raz.',
when: 'teraz',
type: 'warning',
icon: 'bi-exclamation-triangle-fill'
});
}
}).catch(function(error) {
BootstrapToast.show({title: 'Błąd', message: error.response.data.message, when: 'teraz', type: 'danger', icon: 'bi-x-circle-fill'});
});
};
// reset
document.getElementById('resetBtn').onclick = () => {
inputs.forEach(i=>i.value='');
inputs.forEach(i=>i.classList.remove('ok','bad'));
resultEl.textContent = '';
// Not used
//if(inputs[0]) inputs[0].focus();
};
}
</script>
Kod po stronie serwera
Kod serwera niedostępny
Kod po stronie serwera tej aplikacji jest zamknięty i nie jest publicznie dostępny.