рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА рднрд╛рдЧ 1: рд╕реНрд╡реЗрд▓реЗрдЯ рдФрд░ рдХреИрдирд╡рд╕ 2 рдбреА

рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА 0: рддреБрд▓рдирд╛ рд╕реЗрд╡реЗрд▓реНрдЯ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛
рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА рднрд╛рдЧ 1: рд╕реНрд╡реЗрд▓ рдФрд░ рдХреИрдирд╡рд╕ 2 рдбреА
рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА рднрд╛рдЧ 2: рд╕реНрдЯреЗрдЯрд▓реЗрд╕ рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ
рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА, рднрд╛рдЧ 3: рдХрдорд╛рдВрдб рд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд╕рд╛рде рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ
рдЯрд┐рдХ рдЯреАрдПрд╕реА рдХреЛ рдкреИрд░ рдХреА рдЕрдВрдЧреБрд▓реА рднрд╛рдЧ 4: HTTP рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлреНрд▓рд╛рд╕реНрдХ рдмреИрдХрдПрдВрдб рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд

рд▓реЗрдЦ "рддреБрд▓рдирд╛: рд╕реНрд╡реЗрд▓реЗрдЯ рдФрд░ рд░рд┐рдПрдХреНрдЯ" рдореЗрдВ рдореИрдВрдиреЗ рдЦреЗрд▓ рдЯрд┐рдХ рдЯреАрдПрд╕реА рдкреИрд░ рдХреЗ рдЕрдВрдЧреВрдареЗ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЛ рджреЛрд╣рд░рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рд╡рд╣рд╛рдВ рдореИрдВрдиреЗ рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХрд╛ рд╕рдорд░реНрдерди рдХрд┐рдП рдмрд┐рдирд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдореВрд▓ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХрд╛ рдХреЗрд╡рд▓ рдкрд╣рд▓рд╛ рднрд╛рдЧ рдкреВрд░рд╛ рдХрд┐рдпрд╛ред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рд╕реНрд╡реЗрд▓реНрдЯреЗ рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рдЦреЗрд▓ рдХрд╛ рд╡рд┐рдХрд╛рд╕ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗред рдЪрд╛рд▓реЛрдВ рдХрд╛ рдЗрддрд┐рд╣рд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ рдкреНрд░рдгрд╛рд▓реА рд╣реИред рд░рд┐рдПрдХреНрдЯ рдкрд░ рдореВрд▓ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ, рдХрд┐рд╕реА рднреА рд░рд╛рдЬреНрдп рдореЗрдВ рд░реИрдВрдбрдо рдПрдХреНрд╕реЗрд╕ рдХреЗ рд╕рд╛рде рд░рд╛рдЬреНрдп рднрдВрдбрд╛рд░рдг рдХреЗ рд╕рд╛рде рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред Undo / Redo рд╕рд┐рд╕реНрдЯрдо рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╕рдордп, рдХрдорд╛рдВрдб рдкреИрдЯрд░реНрди рдЖрдорддреМрд░ рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ Undo / Redo рдХрдорд╛рдВрдб рдХреЛ рдХрдорд╛рдВрдб рдХреА рд╕реВрдЪреА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдмрд╛рдж рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗ, рдЕрдм рд╣рдо рд░рд╛рдЬреНрдп рднрдВрдбрд╛рд░рдг рдХреЗ рд╕рд╛рде рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВрдЧреЗред


рд╡рд┐рдХрд╛рд╕ рднрдВрдбрд╛рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдлреНрд▓рдХреНрд╕ рд╡рд╛рд╕реНрддреБ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд▓реЗрдЦ рдореЗрдВ рдПрдХ рдЕрд▓рдЧ рдЕрдиреБрднрд╛рдЧ рд╣реИред


рдХреЛрдб рд╢реБрд░реВ рдХрд░реЗрдВ

REPL рдХреЛрдб


App.svelte
<script> import Board from './Board.svelte'; </script> <div class="game"> <div class="game-board"> <Board /> </div> <div class="game-info"> <div class="status">Next player: X</div> <div></div> <ol></ol> </div> </div> <style> .game { font: 14px "Century Gothic", Futura, sans-serif; margin: 20px; display: flex; flex-direction: row; } .game-info { margin-left: 20px; } .status { margin-bottom: 10px; } ol { padding-left: 30px; } </style> 

Board.svelte
 <script> import { onMount } from 'svelte'; export let width = 3; export let height = 3; export let cellWidth = 34; export let cellHeight = 34; export let colorStroke = "#999"; let boardWidth = 1 + (width * cellWidth); let boardHeight = 1 + (height * cellHeight); let canvas; onMount(() => { const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, boardWidth, boardHeight); ctx.beginPath(); // vertical lines for (let x = 0; x <= boardWidth; x += cellWidth) { ctx.moveTo(0.5 + x, 0); ctx.lineTo(0.5 + x, boardHeight); } // horizontal lines for (let y = 0; y <= boardHeight; y += cellHeight) { ctx.moveTo(0, 0.5 + y); ctx.lineTo(boardWidth, 0.5 + y); } // draw the board ctx.strokeStyle = colorStroke; ctx.stroke(); ctx.closePath(); }); </script> <canvas bind:this={canvas} width={boardWidth} height={boardHeight} ></canvas> 

рдкреНрд░рд╛рд░рдВрдн рдХреЛрдб рдПрдХ рдЦрд╛рд▓реА рдЧреНрд░рд┐рдб рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ HTML5 рдХреИрдирд╡рд╛рд╕ рддрддреНрд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рддрддреНрд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП, рдкрд┐рдЫрд▓рд╛ рд▓реЗрдЦ рджреЗрдЦреЗрдВ рд╕реНрд╡реИрд▓рд┐рдВрдЧ рдкрд░ рд╡рд┐рдХрд╛рд╕рд╢реАрд▓ рдмреНрд░реЗрдХрдЖрдЙрдЯ ред рдпрд╣рд╛рдБ рдПрдХ рдЧреНрд░рд┐рдб рдХреА рдЬрд╛рд╕реВрд╕реА рдХреИрд╕реЗ рдХрд░реЗрдВ ред рдЕрдиреНрдп рдЦреЗрд▓реЛрдВ рдореЗрдВ рдмреЛрд░реНрдб рдШрдЯрдХ рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЪреМрдбрд╝рд╛рдИ рдФрд░ рдКрдВрдЪрд╛рдИ рдЪрд░ рдХреЛ рдмрджрд▓рдХрд░, рдЖрдк рдЧреНрд░рд┐рдб рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ; рд╕реЗрд▓рд╡рд┐рдж рдФрд░ рд╕реЗрд▓рд╣рд╛рдЗрдЯ рдЪрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдмрджрд▓рдХрд░ , рдЖрдк рд╕реЗрд▓ рдХрд╛ рдЖрдХрд╛рд░ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред


рд╢реВрдиреНрдп рдХреЗ рд╕рд╛рде рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рднрд░реЗрдВ

REPL рдХреЛрдб
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдСрдирдорд╛рдЙрдВрдЯ () рдиреЗ рдЧреНрд░рд┐рдб рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рдмрд╛рдж рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рд╢реВрдиреНрдп рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рдЬреЛрдбрд╝рд╛ред рдФрд░ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ рд╕реНрдерд┐рддрд┐ рдореВрд▓реНрдпреЛрдВ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдХреБрдЫ рдореИрдЬрд┐рдХ рдирдВрдмрд░ред


 ctx.beginPath(); ctx.font = "bold 22px Century Gothic"; let d = 8; for (let i = 0; i < height; i+=1) { for (let j = 0; j < width; j+=1) { ctx.fillText("O", j * cellWidth + d + 1, (i + 1) * cellHeight - d); } } ctx.closePath(); 

рд░рд╛рдЬреНрдп рднрдВрдбрд╛рд░рдг рдЬреЛрдбрд╝реЗрдВ

REPL рдХреЛрдб
рдЗрд╕ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ, рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд░рд╛рдЬреНрдп рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдПрдХ рдЕрд▓рдЧ store.js рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реНрдЯреЗрдЯ рд╕реНрдЯреЛрд░реЗрдЬ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛, рдпрд╣ рд╕реНрдЯреЛрд░реЗрдЬ рджреЛрдиреЛрдВ рдХрдВрдкреЛрдиреЗрдВрдЯреНрд╕: рдРрдк рдФрд░ рдмреЛрд░реНрдб рдореЗрдВ рдЗрдВрдкреЛрд░реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЦреЗрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрджрд▓рдиреЗ рд╡рд╛рд▓реЗ рд░рд╛рдЬреНрдп 1 рдФрд░ рд░рд╛рдЬреНрдп 2 рддрд░реАрдХреЗ рдЗрд╕ рднрдВрдбрд╛рд░ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реЛрддреЗ рд╣реИрдВред


 import { writable } from 'svelte/store'; function createState() { const { subscribe, set, update } = writable(Array(9).fill('O')); return { subscribe, state1: () => set(Array(9).fill('1')), state2: () => set(Array(9).fill('2')), }; } export const state = createState(); 

App рдШрдЯрдХ рдореЗрдВ рджреЛ рдмрдЯрди рд╕реНрдЯреЗрдЯ 1 рдФрд░ рд╕реНрдЯреЗрдЯ 2 рдЬреЛрдбрд╝реЗред рдмрдЯрдиреЛрдВ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдХреЗ, рд╣рдо рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рддрд░реАрдХреЛрдВ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВред


 <button on:click={state.state1}>State 1</button> <button on:click={state.state2}>State 2</button> 

рдмреЛрд░реНрдб рдШрдЯрдХ рдореЗрдВ, рдореИрдВрдиреЗ рдЙрдирдХреЗ рд░рд╛рдЬреНрдп рднрдВрдбрд╛рд░рдг рд╕реЗ рдбреЗрдЯрд╛ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЗ рд▓рд┐рдП рд╢реВрдиреНрдп рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреА рд░реЗрдЦрд╛ рдХреЛ рдмрджрд▓ рджрд┐рдпрд╛ред рдпрд╣рд╛рдВ рд╣рдо рд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд▓рд┐рдП рдСрдЯреЛ-рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред


 ctx.fillText($state[k], j * cellWidth + d + 1, (i + 1) * cellHeight - d); 

рдЗрд╕ рд╕реНрддрд░ рдкрд░, рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╢реВрдиреНрдп рд╕реЗ рднрд░ рдЬрд╛рддрд╛ рд╣реИ, рд░рд╛рдЬреНрдп 1 рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ - рдХреНрд╖реЗрддреНрд░ рдЗрдХрд╛рдЗрдпреЛрдВ рд╕реЗ рднрд░ рдЬрд╛рддрд╛ рд╣реИ, рд░рд╛рдЬреНрдп 2 рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ - рдХреНрд╖реЗрддреНрд░ рдбреНрдпреВрд╕ рд╕реЗ рднрд░ рдЬрд╛рддрд╛ рд╣реИред


рдорд╛рдЙрд╕ рдХреНрд▓рд┐рдХ рд╕реЗ рд╕реЗрд▓ рднрд░рдирд╛

REPL рдХреЛрдб
рд░рд╛рдЬреНрдп рдХреА рджреБрдХрд╛рди рдореЗрдВ, рдореИрдВрдиреЗ рд╕реЗрдЯрд╕реЗрд▓ () рдкрджреНрдзрддрд┐ рдХреЛ рдЬреЛрдбрд╝рд╛, рдЬреЛ рдЪрдпрдирд┐рдд рд╕реЗрд▓ рдХреЛ рдПрдХ рдХреНрд░реЙрд╕ рдХреЗ рд╕рд╛рде рднрд░рддрд╛ рд╣реИред


 setCell: (i) => update(a => {a[i] = 'X'; return a;}), 

рдПрдХ рдорд╛рдЙрд╕-рдХреНрд▓рд┐рдХ рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреИрдирд╡рд╛рд╕ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛, рдпрд╣рд╛рдВ рд╣рдо рд╕реЗрд▓ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд░рд╛рдЬреНрдп рднрдВрдбрд╛рд░рдг рдХреЗ рд╕реЗрдЯрд╕реЗрд▓ () рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред


 function handleClick(event) { let x = Math.trunc((event.offsetX + 0.5) / cellWidth); let y = Math.trunc((event.offsetY + 0.5) / cellHeight); let i = y * width + x; state.setCell(i); } 

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рд╢реВрдиреНрдп рд╕реЗ рднрд░ рдЬрд╛рддрд╛ рд╣реИ, рд╣рдо рдХрд┐рд╕реА рднреА рд╕реЗрд▓ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рд╢реВрдиреНрдп рдХреЛ рдПрдХ рдХреНрд░реЙрд╕ рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдЪрд╛рд▓ рдХрд╛ рдЗрддрд┐рд╣рд╛рд╕

REPL рдХреЛрдб
рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛ рджреВрдВ рдХрд┐ рд╣рдо рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд░реИрдВрдбрдо рдПрдХреНрд╕реЗрд╕ рдХреЗ рд╕рд╛рде рд░рд╛рдЬреНрдп рднрдВрдбрд╛рд░рдг рдХреЗ рд╕рд╛рде рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВред


 import { writable } from 'svelte/store'; class History { constructor() { this.history = new Array; this.current = -1; } currentState() { return this.history[this.current]; } push(state) { // TODO: remove all redo states this.current++; this.history.push(state); } } function createHistory() { const { subscribe, set, update } = writable(new History); return { subscribe, push: (state) => update(h => { h.push(state); return h; }), }; } export const history = createHistory(); 

рд╕реНрдЯреЗрдЯ рд╕реНрдЯреЛрд░ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрддрд┐рд╣рд╛рд╕ рд╕реНрдЯреЛрд░ рдХреЛ рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред рд╣рдо рдЗрддрд┐рд╣рд╛рд╕ рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрддрд┐рд╣рд╛рд╕ рд╕рд░рдгреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдХрднреА-рдХрднреА, рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ рдкреНрд░рдгрд╛рд▓реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╕рдордп, рджреЛ LIFO рд╕реНрдЯреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдкреВрд░реНрд╡-рд╕реНрдЯреИрдХ рдФрд░ рд░реАрдбреЛ-рд╕реНрдЯреИрдХред рд╣рдо рдЗрддрд┐рд╣рд╛рд╕ рдореЗрдВ рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХрд▓ рдЗрддрд┐рд╣рд╛рд╕ рд╕рд░рдгреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╡рд░реНрддрдорд╛рди рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЦреЗрд▓ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрддрд┐рд╣рд╛рд╕ рдореЗрдВ рд╕рднреА рд░рд╛рдЬреНрдп рд╕рд░рдгреА рдХреА рд╢реБрд░реБрдЖрдд рд╕реЗ рд╡рд░реНрддрдорд╛рди рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд╕рд╛рде рд░рд╛рдЬреНрдп рддрдХ, рдЗрд╕рд▓рд┐рдП рдмреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреВрд░реНрд╡рд╡рдд рд╕реВрдЪреА рдореЗрдВ рд╣реИрдВ, рдФрд░ рдЕрдиреНрдп рд╕рднреА Redo рд╕реВрдЪреА рдореЗрдВ рд╣реИрдВред рдореМрдЬреВрджрд╛ рд╕рдВрдкрддреНрддрд┐ рдореЗрдВ рдХрдореА рдпрд╛ рд╡реГрджреНрдзрд┐, рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ рдпрд╛ рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ рдЖрджреЗрд╢реЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рд░рд╛рдЬреНрдп рдХреЛ рд╢реБрд░реБрдЖрдд рдпрд╛ рдЦреЗрд▓ рдХреЗ рдЕрдВрдд рдХреЗ рдХрд░реАрдм рдЪреБрдирддреЗ рд╣реИрдВред рдкреВрд░реНрд╡рд╡рдд рдФрд░ рдлрд┐рд░ рд╕реЗ рддрд░реАрдХреЗ рдЕрднреА рддрдХ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдмрд╛рдж рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛ред CurrentState () рдФрд░ push () рд╡рд┐рдзрд┐рдпрд╛рдБ рдЗрддрд┐рд╣рд╛рд╕ рд╡рд░реНрдЧ рдореЗрдВ рдЬреЛрдбрд╝ рджреА рдЧрдИ рд╣реИрдВред рд╡рд░реНрддрдорд╛рдирд╕реНрдЯреНрд░реЗрдЯ () рд╡рд┐рдзрд┐ рдЦреЗрд▓ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рд╡рд╛рдкрд╕ рд▓рд╛рддреА рд╣реИ , рдкреБрд╢ () рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдо рдЪрд╛рд▓ рдЗрддрд┐рд╣рд╛рд╕ рдореЗрдВ рдПрдХ рдирдпрд╛ рд░рд╛рдЬреНрдп рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред


рдРрдк рдШрдЯрдХ рдореЗрдВ, рд╣рдордиреЗ рд░рд╛рдЬреНрдп 1 рдФрд░ рд░рд╛рдЬреНрдп 2 рдмрдЯрди рд╣рдЯрд╛ рджрд┐рдП рд╣реИрдВред рдФрд░ рдПрдХ рдкреБрд╢ рдмрдЯрди рдЬреЛрдбрд╝рд╛:


 <button on:click={() => history.push(Array(9).fill($history.current + 1))}>Push</button> 

рдЗрд╕ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рд╕реЗ рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдореЗрдВ рдПрдХ рдирдпрд╛ рд░рд╛рдЬреНрдп рдЬреБрдбрд╝ рдЬрд╛рддрд╛ рд╣реИ, рдЗрддрд┐рд╣рд╛рд╕ рд╕рд░рдгреА рдХреЗрд╡рд▓ рд╡рд░реНрддрдорд╛рди рд░рд╛рдЬреНрдп рд╕реВрдЪрдХрд╛рдВрдХ рдореВрд▓реНрдп рд╡рд░реНрддрдорд╛рди рд╕реЗ рднрд░ рдЬрд╛рддреА рд╣реИ ред


рдмреЛрд░реНрдб рдШрдЯрдХ рдореЗрдВ, рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рд╕реЗ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВред рдпрд╣рд╛рдВ рдЬрд╛рдиреЗрдВ рдХрд┐ рд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд▓рд┐рдП рдСрдЯреЛ-рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ:


 ctx.fillText($history.currentState()[k], j * cellWidth + d + 1, (i + 1) * cellHeight - d); 

рд╣рд┐рд╕реНрдЯреНрд░реА рд╕реНрдЯреЛрд░ рдХреА рдкреБрд╢ рд╡рд┐рдзрд┐ рдореЗрдВ, рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдЖрдЙрдЯрдкреБрдЯ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкреБрд╢ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдпрд╣ рдХреИрд╕реЗ рдмрджрд▓рддрд╛ рд╣реИред


 h.push(state); console.log(h); return h; 

рд╕реЗрд▓ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдирд╛

REPL рдХреЛрдб
рдРрдк рдШрдЯрдХ рдореЗрдВ, рдкреБрд╢ рдмрдЯрди рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред


рдХреНрд▓рд┐рдХрд╕реЗрд▓ рд╡рд┐рдзрд┐ рдХреЛ рдЗрддрд┐рд╣рд╛рд╕ рдХреА рджреБрдХрд╛рди рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╣рдо рдЧреЗрдо рд╕реНрдЯреЗрдЯ рдХреА рдкреВрд░реА рдХреЙрдкреА рдмрдирд╛рддреЗ рд╣реИрдВ, рдЪрдпрдирд┐рдд рд╕реЗрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрджрд▓рддреЗ рд╣реИрдВ рдФрд░ рдореВрд╡ рд╣рд┐рд╕реНрдЯреНрд░реА рдореЗрдВ рдПрдХ рдирдпрд╛ рд╕реНрдЯреЗрдЯ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:


 clickCell: (i) => update(h => { // create a copy of the current state const state = h.currentState().slice(); // change the value of the selected cell to X state[i] = 'X'; // add the new state to the history h.push(state); console.log(h.history); return h; }), 

рдмреЛрд░реНрдб рдШрдЯрдХ рдореЗрдВ, рдХреЙрд▓рдХреНрд▓рд┐рдХ () рд╕реНрдЯреЛрд░реЗрдЬ рдореЗрдердб рдХреЙрд▓ рдХреЛ рд╣реИрдВрдбрд▓рдХреНрд▓рд┐рдХ () рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛:


 history.clickCell(i); 

рдпрд╣рд╛рдВ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХрдВрд╕реЛрд▓ рдореЗрдВ рд╣рдо рдпрд╣ рднреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдорд╛рдЙрд╕ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдХреНрд▓рд┐рдХ рдХреЗ рдмрд╛рдж рдЪрд╛рд▓реЛрдВ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреА рд╕реНрдерд┐рддрд┐ рдХреИрд╕реЗ рдмрджрд▓ рдЬрд╛рддреА рд╣реИред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓реЗрдЦреЛрдВ рдореЗрдВ, рд╣рдо рдЦреЗрд▓ рдХреЛ рдХрд┐рд╕реА рднреА рдЪрд░рдг рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ / рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдФрд░ рдЪрд░рдгреЛрдВ рддрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдкрд╣реБрдБрдЪ рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде, рдЦреЗрд▓ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред рдХрдорд╛рдВрдб рдбрд┐рдЬрд╛рдЗрди рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреВрд░реНрд╡рд╡рдд рдХрд░реЗрдВ / рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ рдкреНрд░рдгрд╛рд▓реА рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдмреИрдХрдПрдВрдб рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рдЦрд┐рд▓рд╛рдбрд╝реА рдмреИрдХрдПрдВрдб рдореЗрдВ рдмреМрджреНрдзрд┐рдХ рдПрдЬреЗрдВрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рдХрд░реЗрдЧрд╛ред


рдлреНрд▓рдХреНрд╕ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛

рдЗрд╕ рдЦреЗрд▓ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ, рдлреНрд▓рдХреНрд╕ рд╡рд╛рд╕реНрддреБ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдордирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреНрд░рд┐рдпрд╛рдПрдБ рд╕реНрдЯреЛрд░ рдореЗрдВ рдЗрддрд┐рд╣рд╛рд╕ рд╕реНрдЯреЛрд░ рдкрд░рд┐рднрд╛рд╖рд╛ рдореЗрдВ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИрдВред рдЬреЗрдПрд╕ рдлрд╝рд╛рдЗрд▓ред рдПрдХ рдЗрддрд┐рд╣рд╛рд╕ рднрдВрдбрд╛рд░ рд╣реИ , рдЬрд┐рд╕реЗ рдЗрддрд┐рд╣рд╛рд╕ рд╡рд░реНрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рджреГрд╢реНрдп рдРрдк рдФрд░ рдмреЛрд░реНрдб рдШрдЯрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ ред рдореЗрд░реЗ рд▓рд┐рдП, рдпрд╣ рд╕рдм MVC рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ , рд╕рд╛рдЗрдб рд╡реНрдпреВ рдХреЗ рд╕рдорд╛рди рд╣реИред рдХреНрд░рд┐рдпрд╛рдПрдБ - рдирд┐рдпрдВрддреНрд░рдХ, рднрдВрдбрд╛рд░рдг - рдореЙрдбрд▓, рджреГрд╢реНрдп - рджреГрд╢реНрдпред рджреЛрдиреЛрдВ рд╡рд╛рд╕реНрддреБрд╢рд┐рд▓реНрдк рдХреЗ рд╡рд┐рд╡рд░рдг рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред


рдЧрд┐рдЯрд╣рдм рднрдВрдбрд╛рд░

https://github.com/nomhoi/tic-tac-toe-part1


рд╕реНрдерд╛рдиреАрдп рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рдЧреЗрдо рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд░рдирд╛:


 git clone https://github.com/nomhoi/tic-tac-toe-part1.git cd tic-tac-toe-part1 npm install npm run dev 

рд╣рдо рдкрддреЗ рдкрд░ рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЧреЗрдо рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ: http: // localhost: 5000 / ред

Source: https://habr.com/ru/post/hi458752/


All Articles