Przejdź do głównej treści

Krzyżówki Online

Grafika Krzyżówki

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!

Jak obsługiwać aplikację?
  1. Wybierz dziedzinę i poziom trudności,
  2. Kliknij na jedno z pól oznaczonych cyferką i wprowadź odpowiedź,
  3. Wypełnij wszystkie pola,
  4. 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.

Loading...

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

3 grudnia 2025 4

Kategorie

Technologie

Dziękujemy!
()

Informacja o cookies

Moja strona internetowa wykorzystuje wyłącznie niezbędne pliki cookies, które są wymagane do jej prawidłowego działania. Nie używam ciasteczek w celach marketingowych ani analitycznych. Korzystając z mojej strony, wyrażasz zgodę na stosowanie tych plików. Możesz dowiedzieć się więcej w mojej polityce prywatności.