Здесь делается вжух 🪄

test

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » test » новый не новый » бой


бой

Сообщений 1 страница 2 из 2

1

[html](function(){
  const topicId = 4;          // ID темы Rusff
  const gameMaster = 'admin'; // Автор поста
  const size = 10;
  const letters = 'ABCDEFGHIJ'.split('');
  const turnDelay = 2601000; // 2 минуты
  const wrap = document.getElementById('battleship');
  if(!wrap) return;
  wrap.innerHTML =     <style>       #battleship table {border-collapse: collapse; margin:0 auto;}       #battleship td {width:42px;height:42px;border:1px solid #444;text-align:center;vertical-align:middle;cursor:pointer;background:#b0d4ff;font-weight:bold;user-select:none;}       #battleship td.hit {background:#f00 url(https://forumstatic.ru/files/0014/cc/0a/39265.png) no-repeat center/70%;}       #battleship td.miss {background:#9bb;opacity:0.9;}       #battleship th {background:#e0f0ff;padding:5px;}       #reset-game {margin-top:10px;display:none;}     </style>     <h2>⚓ Морской бой</h2>     <div id="battle-field"></div>     <button id="reset-game" type="button">Сбросить поле</button>     <p id="game-status" style="margin-top:10px;font-weight:bold;"></p>  ;
  // ---------------- Создаем поле ----------------
  function createField(){
    let html = '<table><tr><th></th>';
    for(let i=1;i<=size;i++) html+='<th>'+i+'</th>';
    html+='</tr>';
    for(let r=0;r<size;r++){ html+="<tr><th>" th>';
      for(let c=1;c<=size;c++){
        html+='<td data-cell="'+letters[r]+c+'"></td>';
      }
      html+='';
    }
    html+='</table>';
    const bf = document.getElementById('battle-field');
    bf.innerHTML = html;
  }
  // ---------------- Расставляем корабли случайно ----------------
  function placeShips(){
    const shipsLen = [4,3,3,2,2,2,1,1,1,1];
    const taken = new Set();
    function randomDir(){return Math.random()<0.5?'h':'v';}
    function canPlace(r,c,len,dir){
      for(let i=0;i<len;i++){ let rr="r+(dir==='v'?i:0)," cc="c+(dir==='h'?i:0);">=size||cc>=size) return false;
        const key=rr+''+cc;
        if(taken.has(key)) return false;
        for(let dr=-1;dr<=1;dr++)
          for(let dc=-1;dc<=1;dc++)
            if(taken.has((rr+dr)+''+(cc+dc))) return false;
      }
      return true;
    }
    const ships=[];
    shipsLen.forEach(len=>{
      let attempts=0;
      let placed=false;
      while(!placed && attempts<1000){
        attempts++;
        let r=Math.floor(Math.random()*size);
        let c=Math.floor(Math.random()*size);
        let dir=randomDir();
        if(canPlace(r,c,len,dir)){
          for(let i=0;i<len;i++){ let rr="r+(dir==='v'?i:0)," cc="c+(dir==='h'?i:0);" taken.add(rr+''+cc); ships.push(rr+''+cc); } placed="true;" if(!placed) console.warn('не удалось разместить корабль длины', len); }); return ships; ---------------- состояние игры state="{" ships: [], клетки кораблей (формат 'r_c') shots: {}, все выстрелы по ключу 'a1'="hit" |'miss' lastshot:{} время последнего выстрела игроков }; конвертируем ячейку function convertcell(cell){ const row="letters.indexOf(cell[0]);" col="parseInt(cell.slice(1))-1;" row+'_'+col; отправляем сообщение в тему posttotopic(msg, hit){ if(typeof ="=="′undefined′)return;="==" 'undefined') return;="=="′undefined′)return;.post(' misc.php?item="ajax_lottery'," { a:'message', id: topicid, msg: '[b]'+msg+'[ b]', color: hit?'red':'blue' }).fail(()>console.warn('Не удалось отправить пост в тему'));
    const status = document.getElementById('game-status');
    if(status) status.textContent = msg;
  }
  // ---------------- Рендер ----------------
  function render(){
    const cells = document.querySelectorAll('#battle-field td[data-cell]');
    cells.forEach(td=>{
      const cell=td.dataset.cell;
      td.classList.remove('hit','miss');
      if(state.shots[cell]==='miss') td.classList.add('miss');
      else if(state.shots[cell]==='hit') td.classList.add('hit');
    });
  }
  // ---------------- Обработка кликов ----------------
  function activate(){
    const bf = document.getElementById('battle-field');
    if(!bf) return;
    bf.addEventListener('click', function(e){
      const td = e.target.closest('td[data-cell]');
      if(!td) return;
      // Безопасно получить имя пользователя
      const user = (window.FORUM && FORUM.user && FORUM.user.name) ? FORUM.user.name : 'guest';
      const now = Date.now();
      if(state.lastShot[user] && now - state.lastShot[user]<turndelay){ 2 alert('можно стрелять раз в минуты.'); return; } const cell="td.dataset.cell;" if(state.shots[cell]) hit="state.ships.indexOf(convertCell(cell))" !="=" -1; state.shots[cell]="hit" ? 'hit':'miss'; state.lastshot[user]="now;" render(); savestate(); posttotopic('игрок '+user+' выстрелил '+cell+' — '+(hit?'попал!':'мимо.'), hit); }); показать кнопку сброса если пользователь мастер игры btn="document.getElementById('reset-game');" if(btn){ currentuser="(window.FORUM" && forum.user forum.user.name) forum.user.name : null; if(currentuser btn.style.display="inline-block" ; else { btn.addeventlistener('click', function(){ if(!confirm('сбросить поле и расставить корабли заново?')) state.ships="[];" state.shots="{};" state.lastshot="{};" posttotopic('⚓ сброшено администратором!', false); ---------------- сохраняем загружаем function savestate(){ if(typeof ="=="′undefined′)="==" 'undefined')="=="′undefined′).post(' misc.php?item="ajax_lottery'," a:'save', id: topicid, data: json.stringify(state) }).fail(()>console.warn('Не удалось сохранить состояние'));
  }
  function loadState(cb){
    if(typeof $ === 'undefined'){ // если нет jQuery, инициализируем без загрузки
      if(!state.ships.length) state.ships = placeShips();
      if(cb) cb();
      return;
    }
    $.get('/misc.php?item=ajax_lottery&id='+topicId+'&action=get').done(function(res){
      try {
        const parsed = typeof res === 'string' ? JSON.parse(res) : res;
        if(parsed && parsed.ships) state = parsed;
      } catch(e){
        state = {ships:[],shots:{},lastShot:{}};
      }
      if(!state.ships || !state.ships.length) state.ships = placeShips();
      if(cb) cb();
    }).fail(function(){
      state = {ships:[],shots:{},lastShot:{}};
      state.ships = placeShips();
      if(cb) cb();
    });
  }
  // ---------------- Инициализация ----------------
  createField();
  loadState(function(){
    render();
    activate();
  });
})();[/html]

0

2

[html]<!-- === Морской бой для Rusff — вставь в сообщение темы === -->
<style>
/* Минимальные стили поля — вписаны в твой стиль (.lot-table) */
.battle-wrap { max-width:520px; margin:10px auto; text-align:center; font-family: Arial, sans-serif; }
.battle-grid { display:inline-block; border-collapse:collapse; margin:10px 0; }
.battle-grid td { width:48px; height:48px; border:1px solid #222; box-sizing:border-box;
  vertical-align:middle; text-align:center; font-weight:700; font-size:14px; cursor:pointer;
  background: rgba(255,255,255,0.03); background-size:70% auto; background-position:center; }
.battle-grid td.header { background:transparent; cursor:default; font-weight:700; font-size:13px; }
.battle-grid td.coord { background:transparent; cursor:default; font-weight:600; font-size:13px; color:#000; opacity:0.7; }
.battle-grid td.miss { background-image: none; color:#2b6ea3; opacity:0.9; }
.battle-grid td.hit { background-image: none; color:#fff; background: #cc3a3a; }
.battle-grid td.ship { /* показывать корабль при reveal */
  background: url('https://forumstatic.ru/files/0014/cc/0a/39265.png') no-repeat center;
  background-size:60%;
}
.battle-controls { margin:6px 0; }
.battle-controls button { margin:0 6px; padding:6px 10px; cursor:pointer; }
.battle-legend { font-size:13px; margin-top:6px; opacity:0.95; }
.battle-info { margin-top:8px; font-size:13px; opacity:0.9; }
</style>

<div id="battleship" class="battle-wrap">
  <h3 style="margin:6px 0;">⚓ Морской бой — поле 8×8</h3>

  <div class="battle-controls">
    <button id="bs-reset">Сброс и новая расстановка</button>
    <button id="bs-toggle-reveal">Показать корабли</button>
    <button id="bs-export">Экспорт состояния (json)</button>
  </div>

  <div id="bs-board-container" style="overflow:auto;">
    <table id="bs-board" class="battle-grid lot-table" style="table-layout:fixed;">
      <!-- генерируется скриптом -->
    </table>
  </div>

  <div class="battle-info">
    <span id="bs-status">Попаданий: <b id="bs-hits">0</b> / <span id="bs-total-cells">0</span></span>
  </div>

  <div class="battle-legend">
    <span style="display:inline-block;margin-right:12px;">🔴 — попадание</span>
    <span style="display:inline-block;margin-right:12px;">🔵 — промах</span>
    <span style="display:inline-block;">🟩 — корабль (только при показе)</span>
  </div>
</div>

<script type="text/javascript">
/* Battleship для Rusff — автономный, сохраняет состояние в localStorage.
   Ключ сохранения: 'battleship_topic_' + (FORUM.topic.id || hash(location.href))
   Автор: адаптация под твой шаблон.
*/
(function(){
  // безопасные имена в глобальных пространствах от твоих скриптов
  if (typeof FORUM === 'undefined') window.FORUM = window.FORUM || {};
  FORUM.battleship = FORUM.battleship || {};

  // Конфигурация
  var ROWS = 8, COLS = 8;
  var LETTERS = ['A','B','C','D','E','F','G','H'];
  var FLEET = [4,3,3,2,2,2,1,1,1,1]; // клетки каждого корабля (1×4,2×3,3×2,4×1)
  var storageKey = (function(){
    try {
      if (window.FORUM && FORUM.topic && FORUM.topic.id) return 'battleship_topic_' + FORUM.topic.id;
    } catch(e){}
    // fallback: hash URL
    function simpleHash(s){
      var h=0; for(var i=0;i<s.length;i++){h=(h<<5)-h + s.charCodeAt(i); h|=0;}
      return Math.abs(h);
    }
    return 'battleship_topic_' + simpleHash(location.href);
  })();

  // state: {ships: [[{r,c},...],...], cells: { "r_c": "miss"|"hit" }, revealed:bool}
  var state = null;

  // DOM refs
  var boardEl = null, hitsEl=null, totalCellsEl=null, btnReset=null, btnReveal=null, btnExport=null;

  // helpers
  function saveState(){
    try { localStorage.setItem(storageKey, JSON.stringify(state)); } catch(e){ console.warn(e); }
  }
  function loadState(){
    try {
      var s = localStorage.getItem(storageKey);
      if (s) return JSON.parse(s);
    } catch(e){}
    return null;
  }
  function clearState(){
    state = null;
    localStorage.removeItem(storageKey);
  }

  // попытка разместить флот случайно без пересечений и в пределах поля
  function placeFleetRandom(){
    var ships = [];
    var occupied = {}; // key "r_c"
    function tryPlace(len){
      var dir = Math.random() < 0.5 ? 'h' : 'v';
      var r = Math.floor(Math.random()*ROWS);
      var c = Math.floor(Math.random()*COLS);
      var cells = [];
      for (var k=0;k<len;k++){
        var rr = dir==='h' ? r : r+k;
        var cc = dir==='h' ? c+k : c;
        if (rr<0 || rr>=ROWS || cc<0 || cc>=COLS) return null;
        if (occupied[rr+'_'+cc]) return null;
        cells.push({r:rr,c:cc});
      }
      // also prevent adjacent placement (optional rule) — keep gap 1 cell around ship
      for (var i=0;i<cells.length;i++){
        for(var dr=-1;dr<=1;dr++){
          for(var dc=-1;dc<=1;dc++){
            var nr=cells[i].r+dr, nc=cells[i].c+dc;
            if (nr>=0 && nr<ROWS && nc>=0 && nc<COLS && occupied[nr+'_'+nc]) return null;
          }
        }
      }
      return cells;
    }

    for (var i=0;i<FLEET.length;i++){
      var len = FLEET[i];
      var attempts = 0, placed = null;
      while(attempts < 200){
        placed = tryPlace(len);
        if (placed) break;
        attempts++;
      }
      if (!placed){
        // если не смогли разместить (очень маловероятно), начинаем заново
        return placeFleetRandom();
      }
      ships.push(placed);
      for (var j=0;j<placed.length;j++){
        occupied[placed[j].r+'_'+placed[j].c] = true;
      }
    }
    return ships;
  }

  // init state (создать или загрузить)
  function initState(){
    var s = loadState();
    if (s && s.ships && s.cells) {
      state = s;
    } else {
      state = { ships: placeFleetRandom(), cells: {}, revealed: false };
      saveState();
    }
  }

  // отрисовка таблицы (с буквами/цифрами)
  function renderBoard(){
    if (!boardEl) return;
    boardEl.innerHTML = '';
    var tbody = document.createElement('tbody');

    // первая строка: пустая клетка + заголовки столбцов A..H
    var trHead = document.createElement('tr');
    trHead.appendChild(td('', 'header')); // пустая
    for (var c=0;c<COLS;c++){
      trHead.appendChild(td(LETTERS[c], 'header'));
    }
    tbody.appendChild(trHead);

    for (var r=0;r<ROWS;r++){
      var tr = document.createElement('tr');
      // номер строки слева
      tr.appendChild(td(String(r+1), 'coord'));
      for (var c=0;c<COLS;c++){
        var cell = td('', '');
        cell.dataset.r = r; cell.dataset.c = c;
        var key = r+'_'+c;
        // determine css based on state.cells
        if (state.cells[key] === 'miss') {
          cell.classList.add('miss');
          cell.textContent = '•';
          cell.title = 'Промах';
        } else if (state.cells[key] === 'hit') {
          cell.classList.add('hit');
          cell.textContent = '✖';
          cell.title = 'Попадание';
        } else {
          cell.textContent = '';
        }

        // show ship if revealed or (optionally) if hit
        if (state.revealed && isShipAt(r,c)) {
          cell.classList.add('ship');
          cell.title = cell.title || 'Корабль';
        }

        // bind click handler only for untouched cells
        (function(rr,cc,el){
          el.addEventListener('click', function(e){
            handleCellClick(rr,cc,el);
          });
        })(r,c,cell);

        tr.appendChild(cell);
      }
      tbody.appendChild(tr);
    }
    boardEl.appendChild(tbody);

    // update counters
    var totalShipCells = countTotalShipCells();
    totalCellsEl.textContent = totalShipCells;
    hitsEl.textContent = countHits();
  }

  function td(text, cls){
    var el = document.createElement('td');
    if (cls) el.className = cls;
    el.textContent = text;
    return el;
  }

  function isShipAt(r,c){
    for (var i=0;i<state.ships.length;i++){
      for (var j=0;j<state.ships[i].length;j++){
        if (state.ships[i][j].r===r && state.ships[i][j].c===c) return true;
      }
    }
    return false;
  }

  function countTotalShipCells(){
    var s=0;
    for (var i=0;i<state.ships.length;i++) s += state.ships[i].length;
    return s;
  }

  function countHits(){
    var cnt=0;
    for (var k in state.cells) if (state.cells[k]==='hit') cnt++;
    return cnt;
  }

  // клик по клетке
  function handleCellClick(r,c,el){
    var key = r+'_'+c;
    if (state.cells[key] === 'hit' || state.cells[key] === 'miss') {
      // уже кликали — ничего не делаем
      return;
    }
    if (isShipAt(r,c)){
      state.cells[key] = 'hit';
      el.classList.add('hit');
      el.textContent = '✖';
      el.title = 'Попадание';
    } else {
      state.cells[key] = 'miss';
      el.classList.add('miss');
      el.textContent = '•';
      el.title = 'Промах';
    }
    saveState();
    hitsEl.textContent = countHits();

    // optional: если все потоплены — показать уведомление
    if (countHits() >= countTotalShipCells()){
      setTimeout(function(){
        alert('Поздравляем! Все корабли потоплены.');
      }, 50);
    }
  }

  // UI: кнопки
  function attachUI(){
    btnReset = document.getElementById('bs-reset');
    btnReveal = document.getElementById('bs-toggle-reveal');
    btnExport = document.getElementById('bs-export');
    hitsEl = document.getElementById('bs-hits');
    totalCellsEl = document.getElementById('bs-total-cells');

    btnReset && btnReset.addEventListener('click', function(){
      if (!confirm('Сбросить поле и заново расставить корабли?')) return;
      state = { ships: placeFleetRandom(), cells: {}, revealed: false };
      saveState();
      renderBoard();
      btnReveal.textContent = 'Показать корабли';
    });

    btnReveal && btnReveal.addEventListener('click', function(){
      state.revealed = !state.revealed;
      saveState();
      renderBoard();
      btnReveal.textContent = state.revealed ? 'Скрыть корабли' : 'Показать корабли';
    });

    btnExport && btnExport.addEventListener('click', function(){
      var data = JSON.stringify(state);
      // простое окно с json — можно скопировать
      var w = window.open('', '_blank', 'width=700,height=400');
      w.document.write('<pre style="white-space:pre-wrap;word-wrap:break-word;font-family:monospace;">' + escapeHtml(data) + '</pre>');
      w.document.title = 'battleship state export';
    });
  }

  function escapeHtml(s){ return (s+'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }

  // init everything
  function init(){
    boardEl = document.getElementById('bs-board');
    if (!boardEl) return;
    attachUI();
    initState();
    renderBoard();
    // ensure reveal button label correct
    var rb = document.getElementById('bs-toggle-reveal');
    if (rb) rb.textContent = state.revealed ? 'Скрыть корабли' : 'Показать корабли';
  }

  // run on DOM ready
  if (document.readyState === 'loading'){
    document.addEventListener('DOMContentLoaded', init);
  } else init();

})();
</script>[/html]

0


Вы здесь » test » новый не новый » бой


Рейтинг форумов | Создать форум бесплатно