{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "184426ac",
   "metadata": {},
   "source": [
    "# 17-24 · Sterowanie klawiaturą\n",
    "\n",
    "Praktyka do [Sterowania klawiaturą](.. /.. /site/chapters/glava-17/17-24-upravlenie-klaviaturoj.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "889b3510",
   "metadata": {},
   "source": [
    "## Cel\n",
    "\n",
    "Pokaż, że klawisz '1'..' 9' prowadzi do TEGO samego attempt_move() co kliknięcie myszką."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c2fb93d",
   "metadata": {},
   "source": [
    "## Pro mainloop() w tym laptopie\n",
    "\n",
    "Zamiast `root.mainloop()` używany tutaj `root.update()` + `root.destroy()` jest takie, że aplikacja jest zbudowana dokładnie tak samo, tylko bez niekończącego się oczekiwania na końcu (zobacz wyjaśnienie w rozdziale 16)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5ba19f8",
   "metadata": {},
   "source": [
    "## Sprawa robocza"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "7504da18",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:13:15.585784Z",
     "iopub.status.busy": "2026-09-03T10:13:15.585649Z",
     "iopub.status.idle": "2026-09-03T10:13:15.685176Z",
     "shell.execute_reply": "2026-09-03T10:13:15.684654Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "board после клавиши '3': ['', '', 'X', '', '', '', '', '', '']\n",
      "Ход записан в тот же moves_log: [2]\n"
     ]
    }
   ],
   "source": [
    "import tkinter as tk\n",
    "\n",
    "root = tk.Tk()\n",
    "board = [\"\"] * 9\n",
    "current_player = [\"X\"]\n",
    "moves_log = []\n",
    "\n",
    "def attempt_move(index):\n",
    "    if board[index]:\n",
    "        return\n",
    "    board[index] = current_player[0]\n",
    "    moves_log.append(index)\n",
    "    current_player[0] = \"O\" if current_player[0] == \"X\" else \"X\"\n",
    "\n",
    "def on_key(event):\n",
    "    if event.char and event.char.isdigit():\n",
    "        n = int(event.char)\n",
    "        if 1 <= n <= 9:\n",
    "            attempt_move(n - 1)\n",
    "\n",
    "root.bind(\"<Key>\", on_key)\n",
    "root.update()\n",
    "root.focus_force()   # без фокуса окна event_generate для клавиш никуда не доставит событие\n",
    "root.update()\n",
    "\n",
    "root.event_generate(\"<Key>\", keysym=\"3\")\n",
    "root.update()\n",
    "print(\"board после клавиши '3':\", board)\n",
    "print(\"Ход записан в тот же moves_log:\", moves_log)\n",
    "root.destroy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85d4a24f",
   "metadata": {},
   "source": [
    "## Podstawowa praktyka zadań ★\n",
    "\n",
    "Sprawdź, czy `0` (poza zakresem 1-9) nie powoduje `attempt_move()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ae806241",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-09-03T10:13:15.686781Z",
     "iopub.status.busy": "2026-09-03T10:13:15.686553Z",
     "iopub.status.idle": "2026-09-03T10:13:15.767416Z",
     "shell.execute_reply": "2026-09-03T10:13:15.766739Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "После клавиши '0': ['', '', '', '', '', '', '', '', ''] | ходов: []\n",
      "После клавиши '9': ['', '', '', '', '', '', '', '', 'X'] | ходов: [8]\n",
      "В attempt_move() попадают только клавиши 1-9.\n"
     ]
    }
   ],
   "source": [
    "root = tk.Tk()\n",
    "board = [\"\"] * 9\n",
    "moves_log = []\n",
    "\n",
    "def attempt_move(index):\n",
    "    if board[index]:\n",
    "        return\n",
    "    board[index] = \"X\"\n",
    "    moves_log.append(index)\n",
    "\n",
    "def on_key(event):\n",
    "    if event.char and event.char.isdigit():\n",
    "        n = int(event.char)\n",
    "        if 1 <= n <= 9:\n",
    "            attempt_move(n - 1)\n",
    "\n",
    "root.bind(\"<Key>\", on_key)\n",
    "root.update()\n",
    "root.focus_force()\n",
    "root.update()\n",
    "\n",
    "root.event_generate(\"<Key>\", keysym=\"0\")\n",
    "root.update()\n",
    "print(\"После клавиши '0':\", board, \"| ходов:\", moves_log)\n",
    "assert moves_log == [], \"клавиша 0 вне диапазона 1-9 — ход делаться не должен\"\n",
    "\n",
    "root.event_generate(\"<Key>\", keysym=\"9\")\n",
    "root.update()\n",
    "print(\"После клавиши '9':\", board, \"| ходов:\", moves_log)\n",
    "assert moves_log == [8], \"клавиша 9 — это последняя клетка, индекс 8\"\n",
    "print(\"В attempt_move() попадают только клавиши 1-9.\")\n",
    "root.destroy()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Cartesian Python 3.14",
   "language": "python",
   "name": "cartesian-python314"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
