{"id":3943,"date":"2025-09-06T07:50:37","date_gmt":"2025-09-05T22:50:37","guid":{"rendered":"https:\/\/smilekabagon.com\/?p=3943"},"modified":"2025-12-13T20:13:38","modified_gmt":"2025-12-13T11:13:38","slug":"%e3%83%9d%e3%83%b3%e3%82%b3%e3%83%84%e5%a4%ab%e5%a9%a6%e3%81%aegame-trial-log-vol-3%ef%bc%9a%e5%b0%86%e6%a3%8b%e7%b7%a8","status":"publish","type":"post","link":"https:\/\/smilekabagon.com\/?p=3943","title":{"rendered":"\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log Vol.3\uff1a\u5c06\u68cb\u7de8"},"content":{"rendered":"\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h1 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-ae0dc43224b870c80ea9bb97481616f7\" style=\"background-color:#004b76;font-size:20px\">I. \u6311\u6226\uff1aAI\u3068\u683c\u95d8\uff01Python\u3067\u5c06\u68cb\u30b2\u30fc\u30e0\u3092\u4f5c\u6210<\/h1>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-79bf4abcbe901ab488ebf4b09bb09cae\" style=\"font-size:20px\">1. \u65b0\u3057\u3044\u6311\u6226\u3068\u30b7\u30ea\u30fc\u30ba\u306e\u30c6\u30fc\u30de<\/h3>\n\n\n\n<p>\u300cGame Trial Log\u300d\u30b7\u30ea\u30fc\u30ba Vol.3\u3078\u3088\u3046\u3053\u305d\u3002<\/p>\n\n\n\n<p>\u672c\u30b7\u30ea\u30fc\u30ba\u306e\u6838\u3068\u306a\u308b\u30c6\u30fc\u30de\u306f\u3001\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u7121\u77e5\u306a\u7b46\u8005Dr.takodemous\u304c\u3001AI\uff08Gemini\uff09\u306e\u529b\u3092\u501f\u308a\u3066\u300eAI\u30b3\u30fc\u30c0\u30fc\u300f\u3068\u3057\u3066\u3069\u3053\u307e\u3067\u901a\u7528\u3059\u308b\u304b\uff1f\u3068\u3044\u3046\u6311\u6226\u3067\u3059\u3002<\/p>\n\n\n\n<p>Vol.1\uff08\u30aa\u30bb\u30ed\uff09\u3001Vol.2\uff08\u30ca\u30f3\u30d7\u30ec\uff09\u306b\u7d9a\u304d\u3001\u4eca\u56de\u306f<strong>Python\u3067\u5c06\u68cb\u30b2\u30fc\u30e0\u306e\u4f5c\u6210<\/strong>\u306b\u6311\u307f\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-e5d5c6ac27c7530773bf6ac493e3e2c1\" style=\"font-size:19px\">2. \u5c06\u68cb\u30a2\u30d7\u30ea\u52d5\u753b\u516c\u958b\uff1a\u96e3\u984c\u306e\u672b\u306b\u5b8c\u6210\uff01<\/h3>\n\n\n\n<p>Gemini\u3068Dr.takodemous\u304c\u5171\u540c\u5236\u4f5c\u3057\u305f\u5c06\u68cb\u30a2\u30d7\u30ea\u306e\u5b8c\u6210\u7248\u3092\u3001\u52d5\u753b\u3067\u516c\u958b\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u3057\u304b\u3057\u3001\u5b8c\u6210\u307e\u3067\u306e\u9053\u306e\u308a\u306f\u3001<strong>\u3053\u308c\u307e\u3067\u306e\u30b2\u30fc\u30e0\u958b\u767a\u3092\u9065\u304b\u306b\u8d85\u3048\u308b\u96e3\u984c\u306e\u9023\u7d9a\u3067\u3057\u305f\u3002<\/strong>\u5177\u4f53\u7684\u306b\u306f\u3001<strong>\u99d2\u306e\u52d5\u304b\u3057\u65b9\u3001\u7981\u624b\u3001\u5c06\u68cb\u5185\u5bb9\u306b\u610f\u5473\u306e\u3042\u308b\u52d5\u304d\u3068\u3044\u3063\u305f\u30eb\u30fc\u30eb\u8a2d\u5b9a\u306e\u58c1\u3001\u68cb\u8b5c\u306e\u5c0e\u5165\u3001\u305d\u3057\u3066AI\u306e\u5f37\u3055\u3092\u6c7a\u3081\u308bdepth\u306e\u8a2d\u5b9a\u306e\u96e3\u89e3\u3055<\/strong>\u3001\u3055\u3089\u306b\u306fGUI\u8a2d\u5b9a\u306e\u82e6\u52b4\uff08\u99d2\u306e\u6f22\u5b57\u304c\u8aad\u307f\u8fbc\u3081\u306a\u3044\uff09\u306a\u3069\u3001\u6570\u3005\u306e\u96e3\u554f\u3092\u30af\u30ea\u30a2\u3057\u3066\u51fa\u6765\u4e0a\u304c\u3063\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u305d\u3057\u3066<strong>\u3001<strong>\u7b46\u8005\u3068AI\u3068\u306e\u5bfe\u5c40\u306f\u3001\u306a\u3093\u3068<\/strong>2\u6642\u9593\u306b\u53ca\u3076\u683c\u95d8\u306e\u672b<\/strong>\u3001Dr.takodemous\u304c\u52dd\u5229\u3057\u307e\u3057\u305f\uff01\u7de8\u96c6\u3092\u7d4c\u3066\u52d5\u753b\u306f45\u5206\u306b\u51dd\u7e2e\u3057\u3066\u3044\u307e\u3059\u304c\u3001\u307e\u3055\u306b\u6fc0\u95d8\u3067\u3057\u305f\u3002<\/p>\n\n\n\n<p>\u3057\u305f\u304c\u3063\u3066\u3001<strong>\u3053\u306e\u82e6\u6226\u683c\u95d8<\/strong>\u3053\u305d\u304c\u3001\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u521d\u5fc3\u8005\u306e\u918d\u9190\u5473\u3067\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"\u30d7\u30ed\u30f3\u30d7\u30c8\u4e00\u767a\u3067\u30b2\u30fc\u30e0\u304c\u3067\u304d\u305f!? Python\u3067\u5c06\u68cbAI\u3092\u7206\u901f\u958b\u767a\u2192Gemini\u3068\u9b3c\u30c7\u30d0\u30c3\u30b0\uff01\" width=\"525\" height=\"295\" src=\"https:\/\/www.youtube.com\/embed\/elLG7TgzEkg?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-7d44b9e9122dfdf9238a6232d3a12aa8\" style=\"font-size:19px\">3. \u3010\u885d\u6483\u306e\u7d50\u672b\u3011Redkabagon\u3001\u64ae\u5f71\u524d\u306b\u30ae\u30d6\u30a2\u30c3\u30d7\uff01\uff1f<\/h3>\n\n\n\n<p>\u305d\u3053\u3067\u3001<strong>Vol.2\u3067\u306e\u717d\u308a\u30c6\u30ed\u30c3\u30d7\u306b\u5fdc\u3048\u308b\u3079\u304f\u3001Redkabagon\u306b\u6311\u6226\u3092\u4fc3\u3057\u307e\u3057\u305f\u304c\u3001<\/strong>\u5f7c\u5973\u306f\u5c06\u68cb\u306e\u96e3\u89e3\u3055\u3092\u524d\u306b<strong>\u64ae\u5f71\u958b\u59cb\u524d\u306b\u30ae\u30d6\u30a2\u30c3\u30d7\u3092\u5ba3\u8a00<\/strong>\u3057\u307e\u3057\u305f\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u300c<strong>Redkabagon\u30ae\u30d6\u30a2\u30c3\u30d7<\/strong>\u300d\u3068\u3044\u3046\u524d\u56de\u306e\u516c\u7d04\u304c\u3001<strong>\u6311\u6226\u4ee5\u524d\u306e\u964d\u53c2<\/strong>\u3068\u3044\u3046\u5f62\u3067\u679c\u305f\u3055\u308c\u308b\u3053\u3068\u3068\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<p>\u305d\u3057\u3066\u3001<strong>\u4eca\u56de\u306f\u9650\u5b9a\u516c\u958b\u52d5\u753b\u304c\u5b58\u5728\u3057\u307e\u305b\u3093<\/strong>\u3002\u5f7c\u5973\u306e<strong>\u8fc5\u901f\u306a\u6f54\u3055<\/strong>\u3092\u901a\u3057\u3066\u3001\u5c06\u68cb\u3068\u3044\u3046\u30b2\u30fc\u30e0\u306e\u5965\u6df1\u3055\u3001\u305d\u3057\u3066\u96e3\u89e3\u3055\u304c\u4f1d\u308f\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-c9008e3a777d0cd7c8d6c7224556bd42\" style=\"background-color:#004b76;font-size:20px\">II. AI\u30b3\u30fc\u30c9\u306e\u6bd4\u8f03\u3068R60\u4e16\u4ee3\u3078\u306e\u30e1\u30c3\u30bb\u30fc\u30b8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-6d5e1e882ce4ef35d62969fc55f33102\" style=\"font-size:20px\">1. \u5c06\u68cb\u30b2\u30fc\u30e0\u306e\u96e3\u89e3\u3055\u3068\u30b3\u30fc\u30c9\u306e\u9032\u5316<\/h3>\n\n\n\n<p>\u5c06\u68cb\u306e\u3088\u3046\u306a\u8907\u96d1\u306a\u30ed\u30b8\u30c3\u30af\u3092\u6301\u3064\u30b2\u30fc\u30e0\u306f\u3001AI\u306e\u529b\u3092\u501f\u308a\u3066\u3082\u4e00\u7b4b\u7e04\u3067\u306f\u3044\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u305d\u306e\u305f\u3081\u3001\u30b3\u30fc\u30c9\u306f\u4f55\u5ea6\u3082\u30c7\u30d0\u30c3\u30b0\u306b\u906d\u9047\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u7b46\u8005\u304c\u4eca\u56de\u306e\u30a2\u30d7\u30ea\u5236\u4f5c\u3067R60\u4e16\u4ee3\u306b\u5411\u3051\u3066\u5f37\u304f\u30e1\u30c3\u30bb\u30fc\u30b8\u3057\u305f\u3044\u306e\u306f\u3001<strong>AI\u3092\u99c6\u4f7f\u3059\u308c\u3070<\/strong>\u3001\u8907\u96d1\u306a\u30b2\u30fc\u30e0\u3067\u3042\u3063\u3066\u3082\u3001\u77e5\u8b58\u30bc\u30ed\u304b\u3089\u305d\u306e**\u300c\u5916\u6bbb\u300d\u300c\u30eb\u30fc\u30eb\u8a2d\u5b9a\u300d\u300cdepth\u8a2d\u5b9a\u300d\u300cGUI\u8a2d\u5b9a\u300d\u3068\u3044\u3063\u305f\u69cb\u9020\u3092\u5b66\u3076\u3053\u3068**\u304c\u3067\u304d\u308b\u3001\u3068\u3044\u3046\u3053\u3068\u3067\u3059\u3002\u4e00\u7dd2\u306b\u3053\u306e\u672a\u77e5\u306e\u4e16\u754c\u3078\u98db\u3073\u8fbc\u307f\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-94dcd38faf1f50d5957fbabc2fa6eca3\" style=\"font-size:20px\">2. \u3010\u30b5\u30a4\u30c8\u7d39\u4ecb\u3011\u30d7\u30ed\u30b3\u30fc\u30c0\u30fc\u306e\u8133\u30c8\u30ec\u30a2\u30d7\u30ea<\/h3>\n\n\n\n<p>\u4eca\u56de\u3082\u524d\u56de\u540c\u69d8\u3001PR TIMES\u3055\u3093\u306e\u30b5\u30a4\u30c8\u3088\u308a<strong>\u30d7\u30ed\u306e\u30b3\u30fc\u30c0\u30fc\u304c\u4f5c\u6210\u3057\u305f\u8133\u30c8\u30ecWeb\u30b2\u30fc\u30e0<\/strong>\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<strong>\u3057\u305f\u304c\u3063\u3066\u3001<strong>\u5c06\u68cb\u30a2\u30d7\u30ea\u7248\u306e\u5b8c\u6210\u5ea6\u3068\u3001\u7b46\u8005\uff08AI\u3068\u5171\u540c\u5236\u4f5c\uff09\u306e<\/strong>\u30b3\u30fc\u30c9\u306e\u96e3\u89e3\u3055<\/strong>\u3092\u5bfe\u6bd4\u3055\u305b\u308b\u3053\u3068\u3067\u3001AI\u30b5\u30dd\u30fc\u30c8\u306e\u51c4\u3055\u304c\u6d6e\u304d\u5f6b\u308a\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-su-blogcard\">\n\t<article class=\"wp-blogcard\" cite=\"https:\/\/prtimes.jp\/main\/html\/rd\/p\/000000233.000006308.html\">\n\t\t<a\n\t\t\thref=\"https:\/\/prtimes.jp\/main\/html\/rd\/p\/000000233.000006308.html\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer nofollow sponsored ugc\"\n\t\t\t\t\t\tclass=\"wp-blogcard-item\"\n\t\t>\n\t\t\t\t\t\t\t<figure class=\"wp-blogcard-figure\">\n\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/prtimes.jp\/i\/6308\/233\/resize\/d6308-233-899177-0.png\" alt=\"\" aria-hidden=\"true\" \/>\n\t\t\t\t<\/figure>\n\t\t\t\t\t\t<div class=\"wp-blogcard-content\">\n\t\t\t\t<div class=\"wp-blogcard-title\">\u8a8d\u77e5\u75c7\u4e88\u9632\u306e\u8133\u30c8\u30ecWeb\u30b2\u30fc\u30e0\u300eDr.\u8133\u30c8\u30ec\u300f\u3092\u30ea\u30ea\u30fc\u30b9\u3002<\/div>\n\t\t\t\t<div class=\"wp-blogcard-description\">\u682a\u5f0f\u4f1a\u793e\uff23\uff2d\u30b5\u30a4\u30c8\u306e\u30d7\u30ec\u30b9\u30ea\u30ea\u30fc\u30b9\uff082020\u5e743\u67084\u65e5 09\u664200\u5206\uff09\u8a8d\u77e5\u75c7\u4e88\u9632\u306e\u8133\u30c8\u30ecWeb\u30b2\u30fc\u30e0\u300eDr.\u8133\u30c8\u30ec\u300f\u3092\u30ea\u30ea\u30fc\u30b9\u3002<\/div>\n\t\t\t\t<div class=\"wp-blogcard-cite\">\n\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tclass=\"wp-blogcard-favicon\"\n\t\t\t\t\t\t\tsrc=\"https:\/\/prtimes.jp\/common\/v4.1\/images\/html\/favicon\/favicon-24x24.png\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\/>\n\t\t\t\t\t\t\t\t\t\t<div class=\"wp-blogcard-domain\">prtimes.jp<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/a>\n\t<\/article>\n<\/div>\n\n\n<div class=\"wp-block-su-blogcard\">\n\t<article class=\"wp-blogcard\" cite=\"https:\/\/dr-noutore.jp\/cont\/preview\/X18.html\">\n\t\t<a\n\t\t\thref=\"https:\/\/dr-noutore.jp\/cont\/preview\/X18.html\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer nofollow sponsored ugc\"\n\t\t\t\t\t\tclass=\"wp-blogcard-item\"\n\t\t>\n\t\t\t\t\t\t<div class=\"wp-blogcard-content\">\n\t\t\t\t<div class=\"wp-blogcard-title\">\u6d77\u99ac\u3092\u935b\u3048\u308b\u8133\u30c8\u30ec\u30b2\u30fc\u30e0(\u7121\u6599)\uff5c1\u3064\u524d\u306e\u5199\u771f\u3092\u9078\u307c\u3046\uff5cDr.\u8133\u30c8\u30ec<\/div>\n\t\t\t\t<div class=\"wp-blogcard-description\">\u6d77\u99ac\u3092\u935b\u3048\u308b\u8133\u30c8\u30ec\u30b2\u30fc\u30e0(\u7121\u6599)\uff5c1\u3064\u524d\u306e\u5199\u771f\u3092\u9078\u307c\u3046\uff5c\u753b\u9762\u4e0a\u90e8\u306b\u8868\u793a\u3055\u308c\u305f\u5199\u771f\u3092\u899a\u3048\u3066\u3001\u6b21\u306e\u753b\u9762\u4e0b\u90e8\u306e\u5199\u771f\u306e\u4e2d\u304b\u3089\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002<\/div>\n\t\t\t\t<div class=\"wp-blogcard-cite\">\n\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tclass=\"wp-blogcard-favicon\"\n\t\t\t\t\t\t\tsrc=\"https:\/\/dr-noutore.jp\/favicon.ico\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\/>\n\t\t\t\t\t\t\t\t\t\t<div class=\"wp-blogcard-domain\">dr-noutore.jp<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/a>\n\t<\/article>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-57a925a0a882aa96b8ba1a2950051956\" style=\"font-size:20px\">3. \u7121\u77e5\u306aAI\u30b3\u30fc\u30c0\u30fc VS \u5c06\u68cb\u306e\u30b3\u30fc\u30c9\u7f8e<\/h3>\n\n\n\n<p>\u3057\u305f\u304c\u3063\u3066<strong>\u3001\u30d7\u30ed\u306e\u30a2\u30d7\u30ea\u306e\u6a5f\u80fd<\/strong>\u3068\u5bfe\u6bd4\u3057\u306a\u304c\u3089\u3001\u7b46\u8005\u306e<strong>\u30b3\u30fc\u30c9<\/strong>\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u672a\u7d4c\u9a13\u4ee5\u524d\u306e\u7121\u77e5\u306a\u7b46\u8005\u3067\u3082\u3001AI\u3092\u99c6\u4f7f\u3059\u308c\u3070\u3001\u30b3\u30fc\u30c0\u30fc\u3068\u8a00\u3048\u308b\u30ec\u30d9\u30eb\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u304c\u3064\u304f\u308c\u308b\u3068\u3044\u3046\u4e8b\u5b9f\u306f\u9a5a\u304d\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u4eca\u56de\u306f\u30c7\u30d0\u30c3\u30b0\u306e\u7d4c\u7def\u3092\u8ffd\u4f53\u9a13\u3057\u3066\u3044\u305f\u3060\u304f\u305f\u3081\u306b\u3001<strong>\u5916\u6bbb\u3001\u30eb\u30fc\u30eb\u8a2d\u5b9a\u3001depth\u8a2d\u5b9a\u3001GUI\u8a2d\u5b9a<\/strong>\u306e4\u3064\u306e\u6bb5\u968e\u306e\u30b3\u30fc\u30c9\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"linkcard\"><div class=\"lkc-external-wrap\"><a class=\"lkc-link no_icon\" href=\"https:\/\/www.python.jp\/install\/docs\/install_plan.html\" data-lkc-id=\"150\" target=\"_blank\" rel=\"external noopener\"><div class=\"lkc-card\"><div class=\"lkc-info\"><div class=\"lkc-favicon\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.google.com\/s2\/favicons?domain=www.python.jp\" alt=\"\" width=\"16\" height=\"16\" \/><\/div><div class=\"lkc-domain\">www.python.jp<\/div><\/div><div class=\"lkc-content\"><figure class=\"lkc-thumbnail\"><img decoding=\"async\" class=\"lkc-thumbnail-img\" src=\"\/\/smilekabagon.com\/wp-content\/uploads\/pz-linkcard\/cache\/950f2e6adde55b6e88a6022f023a9b64e8a22b4a4a0e2302e41179ba4e7ceab4.jpeg\" width=\"100px\" height=\"150px\" alt=\"\" \/><\/figure><div class=\"lkc-title\">Python\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65b9\u91dd - python.jp<\/div><div class=\"lkc-excerpt\">Python\u74b0\u5883\u69cb\u7bc9\u30ac\u30a4\u30c9 \u3067\u306f\u3001Python\u3092\u521d\u3081\u3066\u4f7f\u3046\u65b9\u306e\u5b66\u7fd2\u7528\u306b\u3001\u3067\u304d\u308b\u3060\u3051\u7c21\u5358\u3067\u6c4e\u7528\u6027\u306e\u3042\u308bPython\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u3066\u3044\u307e\u3059\u3002 \u672c\u6765\u3001Python\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u81ea\u4f53\u306f\u305d\u3046\u9762\u5012\u306a\u3053\u3068\u3067\u306f\u306a\u3044\u306e\u3067\u3059\u304c\u3001Web\u3067\u3061\u3087\u3063\u3068\u691c\u7d22\u3059\u308b\u3068\u3044\u308d\u3044\u308d\u306a\u60c5\u5831<\/div><\/div><div class=\"clear\"><\/div><\/div><\/a><\/div><\/div>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-d73baada3534cfbb4459f11da4a8b2f7 is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no1(\u5916\u6bbb\u306e\u8a2d\u5b9a)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>import tkinter as tk\n\n# \u30a6\u30a3\u30f3\u30c9\u30a6\u3068\u30ad\u30e3\u30f3\u30d0\u30b9\u306e\u30b5\u30a4\u30ba\nBOARD_SIZE = 450\nCELL_SIZE = BOARD_SIZE \/\/ 9\nSIDE_PANEL_WIDTH = 150\n\n# \u99d2\u306e\u5b9a\u6570\nEMPTY = ' '\nBLACK = '\u9ed2'\nWHITE = '\u767d'\n\n# \u99d2\u306e\u7a2e\u985e\u3068\u8868\u793a\u540d\nPIECES = {\n    'OU': '\u7389', 'HI': '\u98db', 'KA': '\u89d2', 'KI': '\u91d1',\n    'GI': '\u9280', 'KE': '\u6842', '\u9999': '\u9999', 'FU': '\u6b69',\n    'TO': '\u3068', 'N-GI': '\u6210\u9280', 'N-KE': '\u6210\u6842', 'N-KY': '\u6210\u9999',\n    'RY': '\u9f8d', 'UM': '\u99ac'\n}\n\n# \u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570\u3068\u3057\u3066\u30b2\u30fc\u30e0\u306e\u72b6\u614b\u3092\u4fdd\u6301\ngame_board = None\ncanvas = None\nselected_piece = None\noriginal_pos = None\ncurrent_player = BLACK\nblack_captures = &#091;]\nwhite_captures = &#091;]\nis_placing_piece = False\ngame_states = &#091;]\n\ndef create_initial_board():\n    \"\"\"\n    \u5c06\u68cb\u76e4\u306e\u521d\u671f\u914d\u7f6e\u3092\u8868\u73fe\u3059\u308b2\u6b21\u5143\u30ea\u30b9\u30c8\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\n    \u99d2\u306f (\u30d7\u30ec\u30a4\u30e4\u30fc, \u99d2\u306e\u7a2e\u985e) \u306e\u30bf\u30d7\u30eb\u3067\u8868\u73fe\u3057\u307e\u3059\u3002\n    \"\"\"\n    board = &#091;&#091;EMPTY] * 9 for _ in range(9)]\n\n    # \u767d\uff08\u5f8c\u624b\uff09\u306e\u99d2\u306e\u914d\u7f6e\n    board&#091;0]&#091;0] = (WHITE, '\u9999')\n    board&#091;0]&#091;1] = (WHITE, 'KE')\n    board&#091;0]&#091;2] = (WHITE, 'GI')\n    board&#091;0]&#091;3] = (WHITE, 'KI')\n    board&#091;0]&#091;4] = (WHITE, 'OU')\n    board&#091;0]&#091;5] = (WHITE, 'KI')\n    board&#091;0]&#091;6] = (WHITE, 'GI')\n    board&#091;0]&#091;7] = (WHITE, 'KE')\n    board&#091;0]&#091;8] = (WHITE, '\u9999')\n    board&#091;1]&#091;1] = (WHITE, 'HI')\n    board&#091;1]&#091;7] = (WHITE, 'KA')\n    for j in range(9):\n        board&#091;2]&#091;j] = (WHITE, 'FU')\n\n    # \u9ed2\uff08\u5148\u624b\uff09\u306e\u99d2\u306e\u914d\u7f6e\n    board&#091;8]&#091;0] = (BLACK, '\u9999')\n    board&#091;8]&#091;1] = (BLACK, 'KE')\n    board&#091;8]&#091;2] = (BLACK, 'GI')\n    board&#091;8]&#091;3] = (BLACK, 'KI')\n    board&#091;8]&#091;4] = (BLACK, 'OU')\n    board&#091;8]&#091;5] = (BLACK, 'KI')\n    board&#091;8]&#091;6] = (BLACK, 'GI')\n    board&#091;8]&#091;7] = (BLACK, 'KE')\n    board&#091;8]&#091;8] = (BLACK, '\u9999')\n    board&#091;7]&#091;1] = (BLACK, 'KA')\n    board&#091;7]&#091;7] = (BLACK, 'HI')\n    for j in range(9):\n        board&#091;6]&#091;j] = (BLACK, 'FU')\n\n    return board\n\n# --- \u99d2\u306e\u79fb\u52d5\u30eb\u30fc\u30eb (\u5909\u66f4\u306a\u3057) ---\ndef is_valid_pawn_move(start_row, start_col, end_row, end_col, player):\n    if player == BLACK:\n        return end_row == start_row - 1 and end_col == start_col\n    elif player == WHITE:\n        return end_row == start_row + 1 and end_col == start_col\n    return False\n\ndef is_valid_lance_move(start_row, start_col, end_row, end_col, player, board):\n    if end_col != start_col: return False\n    step = -1 if player == BLACK else 1\n    for r in range(start_row + step, end_row, step):\n        if board&#091;r]&#091;start_col] != EMPTY: return False\n    return True\n\ndef is_valid_king_move(start_row, start_col, end_row, end_col):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    return dx &lt;= 1 and dy &lt;= 1\n\ndef is_valid_rook_move(start_row, start_col, end_row, end_col, board):\n    if start_row == end_row:\n        step = 1 if end_col &gt; start_col else -1\n        for c in range(start_col + step, end_col, step):\n            if board&#091;start_row]&#091;c] != EMPTY: return False\n    elif start_col == end_col:\n        step = 1 if end_row &gt; start_row else -1\n        for r in range(start_row + step, end_row, step):\n            if board&#091;r]&#091;start_col] != EMPTY: return False\n    else:\n        return False\n    return True\n\ndef is_valid_bishop_move(start_row, start_col, end_row, end_col, board):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != dy or dx == 0: return False\n    step_x = 1 if end_col &gt; start_col else -1\n    step_y = 1 if end_row &gt; start_row else -1\n    for i in range(1, dx):\n        if board&#091;start_row + i * step_y]&#091;start_col + i * step_x] != EMPTY:\n            return False\n    return True\n\ndef is_valid_gold_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_silver_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_knight_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != 1 or dy != 2: return False\n    if player == BLACK:\n        return end_row == start_row - 2\n    elif player == WHITE:\n        return end_row == start_row + 2\n    return False\n# --- \u3053\u3053\u307e\u3067\u79fb\u52d5\u30eb\u30fc\u30eb\u5909\u66f4\u306a\u3057 ---\n\ndef draw_pieces():\n    \"\"\"\n    Python\u306e\u30dc\u30fc\u30c9\u60c5\u5831\u306b\u57fa\u3065\u3044\u3066\u3001canvas\u4e0a\u306b\u99d2\u3092\u63cf\u753b\u3057\u307e\u3059\u3002\n    \"\"\"\n    canvas.delete(\"all\")\n    \n    # \u76e4\u9762\u306e\u5347\u76ee\u3092\u63cf\u753b\n    for i in range(9):\n        for j in range(9):\n            x1 = j * CELL_SIZE\n            y1 = i * CELL_SIZE\n            x2 = x1 + CELL_SIZE\n            y2 = y1 + CELL_SIZE\n            canvas.create_rectangle(x1, y1, x2, y2, outline=\"black\", fill=\"#D2B48C\")\n            \n    # \u30dc\u30fc\u30c9\u4e0a\u306e\u99d2\u3092\u63cf\u753b\n    for r in range(9):\n        for c in range(9):\n            piece_data = game_board&#091;r]&#091;c]\n            if piece_data != EMPTY:\n                player, piece_type = piece_data\n                text_piece = PIECES&#091;piece_type]\n\n                x = c * CELL_SIZE + CELL_SIZE \/\/ 2\n                y = r * CELL_SIZE + CELL_SIZE \/\/ 2\n\n                color_bg = \"#E0C8A4\" if player == BLACK else \"#FFFFFF\"\n                canvas.create_rectangle(\n                    c * CELL_SIZE, r * CELL_SIZE,\n                    (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE,\n                    fill=color_bg, outline=\"black\"\n                )\n                color_text = \"black\"\n                canvas.create_text(\n                    x, y,\n                    text=text_piece,\n                    fill=color_text,\n                    font=(\"Arial\", 16)\n                )\n\n    # \u6301\u3061\u99d2\u306e\u8868\u793a\n    canvas.create_text(BOARD_SIZE + 20, 20, anchor=\"nw\", text=\"\u9ed2\u306e\u6301\u3061\u99d2\", font=(\"Arial\", 12))\n    for i, piece in enumerate(black_captures):\n        text_piece = PIECES&#091;piece&#091;1]]\n        y = 40 + i * 20\n        canvas.create_text(BOARD_SIZE + 30, y, anchor=\"nw\", text=f\"{text_piece}\", font=(\"Arial\", 12), tags=f\"black_capture_{i}\")\n\n    canvas.create_text(BOARD_SIZE + 20, 200, anchor=\"nw\", text=\"\u767d\u306e\u6301\u3061\u99d2\", font=(\"Arial\", 12))\n    for i, piece in enumerate(white_captures):\n        text_piece = PIECES&#091;piece&#091;1]]\n        y = 220 + i * 20\n        canvas.create_text(BOARD_SIZE + 30, y, anchor=\"nw\", text=f\"{text_piece}\", font=(\"Arial\", 12), tags=f\"white_capture_{i}\")\n\ndef should_promote(piece_type, player, start_row, end_row):\n    \"\"\"\n    \u99d2\u304c\u6210\u308b\u3079\u304d\u304b\u3092\u5224\u5b9a\u3059\u308b\u30d8\u30eb\u30d1\u30fc\u95a2\u6570\n    \"\"\"\n    if piece_type in &#091;'OU', 'KI', 'N-GI', 'N-KE', 'N-KY', 'RY', 'UM']:\n        return False\n    \n    if player == BLACK:\n        return end_row &lt;= 2 or start_row &lt;= 2\n    else:\n        return end_row &gt;= 6 or start_row &gt;= 6\n    \ndef get_promoted_piece(piece_type):\n    \"\"\"\n    \u99d2\u304c\u6210\u3063\u305f\u5f8c\u306e\u7a2e\u985e\u3092\u8fd4\u3059\n    \"\"\"\n    promotions = {\n        'FU': 'TO', '\u9999': 'N-KY', 'KE': 'N-KE', 'GI': 'N-GI', 'HI': 'RY', 'KA': 'UM',\n    }\n    return promotions.get(piece_type, piece_type)\n\n\ndef find_king(player):\n    \"\"\"\n    \u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u7389\u306e\u4f4d\u7f6e\u3092\u8fd4\u3059\n    \"\"\"\n    for r in range(9):\n        for c in range(9):\n            piece_data = game_board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == player and piece_data&#091;1] == 'OU':\n                return r, c\n    return None, None\n\ndef is_in_check(player, board):\n    \"\"\"\n    \u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u7389\u304c\u738b\u624b\u72b6\u614b\u306b\u3042\u308b\u304b\u3092\u5224\u5b9a\u3059\u308b\n    \"\"\"\n    king_row, king_col = find_king(player)\n    if king_row is None:\n        return False \n        \n    opponent = WHITE if player == BLACK else BLACK\n    \n    for r in range(9):\n        for c in range(9):\n            piece_data = board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == opponent:\n                piece_type = piece_data&#091;1]\n                \n                # \u76f8\u624b\u306e\u99d2\u304c\u7389\u306e\u4f4d\u7f6e\u306b\u52d5\u3051\u308b\u304b\u3092\u30c1\u30a7\u30c3\u30af\n                is_valid = False\n                if piece_type == 'FU' and is_valid_pawn_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == '\u9999' and is_valid_lance_move(r, c, king_row, king_col, opponent, board): is_valid = True\n                elif piece_type == 'HI' and is_valid_rook_move(r, c, king_row, king_col, board): is_valid = True\n                elif piece_type == 'KA' and is_valid_bishop_move(r, c, king_row, king_col, board): is_valid = True\n                elif piece_type == 'KI' and is_valid_gold_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == 'GI' and is_valid_silver_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == 'KE' and is_valid_knight_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == 'RY' and (is_valid_rook_move(r, c, king_row, king_col, board) or is_valid_king_move(r, c, king_row, king_col)): is_valid = True\n                elif piece_type == 'UM' and (is_valid_bishop_move(r, c, king_row, king_col, board) or is_valid_king_move(r, c, king_row, king_col)): is_valid = True\n                elif piece_type in &#091;'TO', 'N-GI', 'N-KE', 'N-KY'] and is_valid_gold_move(r, c, king_row, king_col, opponent): is_valid = True\n                \n                if is_valid:\n                    return True\n    return False\n\ndef is_checkmate(player, board):\n    \"\"\"\n    \u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ec\u30a4\u30e4\u30fc\u304c\u8a70\u307f\u72b6\u614b\u306b\u3042\u308b\u304b\u3092\u5224\u5b9a\u3059\u308b\n    \"\"\"\n    if not is_in_check(player, board):\n        return False\n\n    king_row, king_col = find_king(player)\n    \n    # \u7389\u306e\u5468\u308a\u306e\u3059\u3079\u3066\u306e\u30de\u30b9\u3092\u30c1\u30a7\u30c3\u30af\n    for dr in range(-1, 2):\n        for dc in range(-1, 2):\n            if dr == 0 and dc == 0: continue\n            \n            new_row, new_col = king_row + dr, king_col + dc\n            \n            if 0 &lt;= new_row &lt; 9 and 0 &lt;= new_col &lt; 9:\n                target_piece = board&#091;new_row]&#091;new_col]\n                if target_piece == EMPTY or target_piece&#091;0] != player:\n                    temp_board = &#091;row&#091;:] for row in board]\n                    temp_board&#091;new_row]&#091;new_col] = (player, 'OU')\n                    temp_board&#091;king_row]&#091;king_col] = EMPTY\n                    \n                    if not is_in_check(player, temp_board):\n                        return False\n\n    return True\n\ndef get_board_state_string():\n    \"\"\"\n    \u73fe\u5728\u306e\u76e4\u9762\u3068\u6301\u3061\u99d2\u306e\u72b6\u614b\u3092\u6587\u5b57\u5217\u3068\u3057\u3066\u8fd4\u3059\n    \"\"\"\n    state_str = \"\"\n    for row in game_board:\n        for cell in row:\n            if cell == EMPTY:\n                state_str += \"E\"\n            else:\n                state_str += cell&#091;0] + cell&#091;1]\n    \n    # \u6301\u3061\u99d2\u3092\u30bd\u30fc\u30c8\u3057\u3066\u6587\u5b57\u5217\u306b\u8ffd\u52a0\n    sorted_black_captures = sorted(&#091;p&#091;1] for p in black_captures])\n    sorted_white_captures = sorted(&#091;p&#091;1] for p in white_captures])\n    state_str += \"BC\" + \"\".join(sorted_black_captures)\n    state_str += \"WC\" + \"\".join(sorted_white_captures)\n    \n    return state_str\n\ndef on_click(event):\n    \"\"\"\n    \u30de\u30a6\u30b9\u304c\u30af\u30ea\u30c3\u30af\u3055\u308c\u305f\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\u3067\u3059\u3002\n    \"\"\"\n    global selected_piece, original_pos, is_placing_piece, current_player, game_states\n    \n    col = event.x \/\/ CELL_SIZE\n    row = event.y \/\/ CELL_SIZE\n    \n    # \u76e4\u9762\u5916\uff08\u6301\u3061\u99d2\u30a8\u30ea\u30a2\uff09\u3067\u306e\u30af\u30ea\u30c3\u30af\n    if col &gt;= 9:\n        if not is_placing_piece:\n            clicked_item = canvas.find_closest(event.x, event.y)&#091;0]\n            tags = canvas.gettags(clicked_item)\n            \n            if tags and tags&#091;0].startswith(f\"black_capture_\") and current_player == BLACK:\n                index = int(tags&#091;0].split('_')&#091;-1])\n                selected_piece = black_captures.pop(index)\n                is_placing_piece = True\n                draw_pieces()\n                \n                canvas.create_text(event.x, event.y, text=PIECES&#091;selected_piece&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\")\n                return\n            \n            if tags and tags&#091;0].startswith(f\"white_capture_\") and current_player == WHITE:\n                index = int(tags&#091;0].split('_')&#091;-1])\n                selected_piece = white_captures.pop(index)\n                is_placing_piece = True\n                draw_pieces()\n                \n                canvas.create_text(event.x, event.y, text=PIECES&#091;selected_piece&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\")\n                return\n\n    # \u76e4\u9762\u5185\u3067\u306e\u30af\u30ea\u30c3\u30af\n    if 0 &lt;= row &lt; 9 and 0 &lt;= col &lt; 9:\n        if is_placing_piece:\n            # \u6301\u3061\u99d2\u3092\u6253\u3064\u51e6\u7406\n            if game_board&#091;row]&#091;col] == EMPTY:\n                piece_type = selected_piece&#091;1]\n                player = selected_piece&#091;0]\n                \n                # \u884c\u304d\u6240\u306e\u306a\u3044\u99d2\n                if (piece_type == 'FU' or piece_type == '\u9999') and ((player == BLACK and row == 0) or (player == WHITE and row == 8)):\n                    print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u306b\u6253\u3066\u307e\u305b\u3093\u3002\")\n                    black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                    is_placing_piece = False\n                    selected_piece = None\n                    canvas.delete(\"drag_piece\")\n                    draw_pieces()\n                    return\n                if piece_type == 'KE' and ((player == BLACK and row &lt;= 1) or (player == WHITE and row &gt;= 7)):\n                    print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u306b\u6253\u3066\u307e\u305b\u3093\u3002\")\n                    black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                    is_placing_piece = False\n                    selected_piece = None\n                    canvas.delete(\"drag_piece\")\n                    draw_pieces()\n                    return\n                \n                # \u4e8c\u6b69\n                if piece_type == 'FU':\n                    is_nifu = False\n                    for r in range(9):\n                        piece_at_r = game_board&#091;r]&#091;col]\n                        if piece_at_r != EMPTY and piece_at_r&#091;0] == player and piece_at_r&#091;1] == 'FU':\n                            is_nifu = True\n                            break\n                    if is_nifu:\n                        print(\"\u305d\u306e\u7b4b\u306b\u306f\u65e2\u306b\u6b69\u304c\u3042\u308a\u307e\u3059\u3002\uff08\u4e8c\u6b69\uff09\")\n                        black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                        is_placing_piece = False\n                        selected_piece = None\n                        canvas.delete(\"drag_piece\")\n                        draw_pieces()\n                        return\n                \n                # \u6253\u3061\u6b69\u8a70\u3081\n                opponent = WHITE if player == BLACK else BLACK\n                temp_board = &#091;row&#091;:] for row in game_board]\n                temp_board&#091;row]&#091;col] = selected_piece\n                if is_in_check(opponent, temp_board) and piece_type == 'FU':\n                    if is_checkmate(opponent, temp_board):\n                        print(\"\u305d\u306e\u624b\u306f\u6253\u3061\u6b69\u8a70\u3081\u3067\u3059\u3002\")\n                        black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                        is_placing_piece = False\n                        selected_piece = None\n                        canvas.delete(\"drag_piece\")\n                        draw_pieces()\n                        return\n                \n                game_board&#091;row]&#091;col] = selected_piece\n                is_placing_piece = False\n                selected_piece = None\n\n                # \u5c40\u9762\u306e\u8a18\u9332\u3068\u5343\u65e5\u624b\u5224\u5b9a\n                current_state = get_board_state_string()\n                if game_states.count(current_state) &gt;= 3:\n                    print(\"\u5343\u65e5\u624b\u3067\u3059\uff01\u5f15\u304d\u5206\u3051\u3068\u306a\u308a\u307e\u3057\u305f\u3002\")\n                    return\n                else:\n                    game_states.append(current_state)\n\n                current_player = WHITE if current_player == BLACK else BLACK\n                \n                # \u738b\u624b\u30fb\u8a70\u307f\u5224\u5b9a\n                if is_checkmate(current_player, game_board):\n                    print(\"\u8a70\u307f\u3067\u3059\uff01\u30b2\u30fc\u30e0\u7d42\u4e86\uff01\")\n                elif is_in_check(current_player, game_board):\n                    print(\"\u738b\u624b\uff01\")\n\n            else:\n                print(\"\u305d\u306e\u30de\u30b9\u306b\u306f\u99d2\u3092\u6253\u3066\u307e\u305b\u3093\u3002\")\n                capture_list = black_captures if selected_piece&#091;0] == BLACK else white_captures\n                capture_list.append(selected_piece)\n\n            canvas.delete(\"drag_piece\")\n            draw_pieces()\n            return\n            \n        else:\n            # \u76e4\u4e0a\u306e\u99d2\u3092\u9078\u629e\u3059\u308b\u51e6\u7406\n            piece_data = game_board&#091;row]&#091;col]\n            if piece_data != EMPTY and piece_data&#091;0] == current_player:\n                selected_piece = piece_data\n                original_pos = (row, col)\n                \n                game_board&#091;row]&#091;col] = EMPTY\n                draw_pieces()\n                \n                canvas.create_text(event.x, event.y, text=PIECES&#091;piece_data&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\")\n\ndef on_drag(event):\n    \"\"\"\n    \u30de\u30a6\u30b9\u304c\u30c9\u30e9\u30c3\u30b0\u3055\u308c\u3066\u3044\u308b\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\u3067\u3059\u3002\n    \"\"\"\n    if selected_piece:\n        canvas.coords(\"drag_piece\", event.x, event.y)\n\ndef on_release(event):\n    \"\"\"\n    \u30de\u30a6\u30b9\u30dc\u30bf\u30f3\u304c\u96e2\u3055\u308c\u305f\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\u3067\u3059\u3002\n    \"\"\"\n    global selected_piece, original_pos, current_player, game_states\n    \n    if is_placing_piece:\n        return\n        \n    if selected_piece:\n        new_col = event.x \/\/ CELL_SIZE\n        new_row = event.y \/\/ CELL_SIZE\n        \n        if not (0 &lt;= new_row &lt; 9 and 0 &lt;= new_col &lt; 9):\n            game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n            selected_piece = None\n            original_pos = None\n            canvas.delete(\"drag_piece\")\n            draw_pieces()\n            return\n\n        is_valid = False\n        piece_type = selected_piece&#091;1]\n        player = selected_piece&#091;0]\n        \n        if piece_type == 'FU':\n            is_valid = is_valid_pawn_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == '\u9999':\n            is_valid = is_valid_lance_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player, game_board)\n        elif piece_type == 'OU':\n            is_valid = is_valid_king_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col)\n        elif piece_type == 'HI':\n            is_valid = is_valid_rook_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board)\n        elif piece_type == 'KA':\n            is_valid = is_valid_bishop_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board)\n        elif piece_type == 'KI':\n            is_valid = is_valid_gold_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == 'GI':\n            is_valid = is_valid_silver_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == 'KE':\n            is_valid = is_valid_knight_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == 'RY' and (is_valid_rook_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board) or is_valid_king_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col)): is_valid = True\n        elif piece_type == 'UM' and (is_valid_bishop_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board) or is_valid_king_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col)): is_valid = True\n        elif piece_type in &#091;'TO', 'N-GI', 'N-KE', 'N-KY'] and is_valid_gold_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player): is_valid = True\n        \n        target_piece = game_board&#091;new_row]&#091;new_col]\n        \n        if target_piece != EMPTY and target_piece&#091;0] == player:\n            is_valid = False\n            \n        if is_valid:\n            # \u884c\u304d\u6240\u306e\u306a\u3044\u99d2\n            if (piece_type == 'FU' or piece_type == '\u9999') and ((player == BLACK and new_row == 0) or (player == WHITE and new_row == 8)):\n                is_valid = False\n                print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u3078\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002\")\n            if piece_type == 'KE' and ((player == BLACK and new_row &lt;= 1) or (player == WHITE and new_row &gt;= 7)):\n                is_valid = False\n                print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u3078\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002\")\n        \n        if is_valid:\n            temp_board = &#091;row&#091;:] for row in game_board]\n            if target_piece != EMPTY:\n                temp_board&#091;new_row]&#091;new_col] = selected_piece\n            else:\n                temp_board&#091;new_row]&#091;new_col] = selected_piece\n            \n            if is_in_check(player, temp_board):\n                print(\"\u305d\u306e\u624b\u306f\u53cd\u5247\u3067\u3059\u3002\u81ea\u5206\u306e\u7389\u304c\u738b\u624b\u306b\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u3002\")\n                is_valid = False\n\n        if is_valid:\n            if target_piece != EMPTY:\n                captured_piece = target_piece&#091;1]\n                if player == BLACK:\n                    white_captures.append((BLACK, captured_piece))\n                else:\n                    black_captures.append((WHITE, captured_piece))\n\n            if should_promote(piece_type, player, original_pos&#091;0], new_row):\n                promoted_piece = get_promoted_piece(piece_type)\n                selected_piece = (player, promoted_piece)\n\n            game_board&#091;new_row]&#091;new_col] = selected_piece\n            \n            # \u5c40\u9762\u306e\u8a18\u9332\u3068\u5343\u65e5\u624b\u5224\u5b9a\n            current_state = get_board_state_string()\n            if game_states.count(current_state) &gt;= 3:\n                print(\"\u5343\u65e5\u624b\u3067\u3059\uff01\u5f15\u304d\u5206\u3051\u3068\u306a\u308a\u307e\u3057\u305f\u3002\")\n                return\n            else:\n                game_states.append(current_state)\n\n            current_player = WHITE if current_player == BLACK else BLACK\n            \n            # \u738b\u624b\u30fb\u8a70\u307f\u5224\u5b9a\n            if is_checkmate(current_player, game_board):\n                print(\"\u8a70\u307f\u3067\u3059\uff01\u30b2\u30fc\u30e0\u7d42\u4e86\uff01\")\n            elif is_in_check(current_player, game_board):\n                print(\"\u738b\u624b\uff01\")\n\n        else:\n            print(\"\u305d\u306e\u99d2\u306f\u305d\u3053\u306b\u52d5\u304b\u305b\u307e\u305b\u3093\u3002\")\n            game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n        \n        selected_piece = None\n        original_pos = None\n\n        canvas.delete(\"drag_piece\")\n        draw_pieces()\n\ndef create_shogi_board():\n    \"\"\"\n    tkinter\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u3068\u5c06\u68cb\u76e4\u306eGUI\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\n    \"\"\"\n    global game_board, canvas, game_states\n    \n    root = tk.Tk()\n    root.title(\"\u5c06\u68cb\u30b2\u30fc\u30e0\")\n\n    canvas = tk.Canvas(root, width=BOARD_SIZE + SIDE_PANEL_WIDTH, height=BOARD_SIZE, bg=\"#D2B48C\")\n    canvas.pack()\n    \n    canvas.bind(\"&lt;Button-1&gt;\", on_click)\n    canvas.bind(\"&lt;B1-Motion&gt;\", on_drag)\n    canvas.bind(\"&lt;ButtonRelease-1&gt;\", on_release)\n            \n    game_board = create_initial_board()\n    \n    # \u6700\u521d\u306e\u5c40\u9762\u3092\u8a18\u9332\n    game_states.append(get_board_state_string())\n\n    draw_pieces()\n\n    root.mainloop()\n\nif __name__ == \"__main__\":\n    create_shogi_board()<\/code><\/pre>\n<\/details>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-4fb9601f72434f7c6b6d48fbd35a6134 is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no2(\u30eb\u30fc\u30eb\u8a2d\u5b9a)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>import tkinter as tk\n\n# \u30a6\u30a3\u30f3\u30c9\u30a6\u3068\u30ad\u30e3\u30f3\u30d0\u30b9\u306e\u30b5\u30a4\u30ba\nBOARD_SIZE = 450\nCELL_SIZE = BOARD_SIZE \/\/ 9\nSIDE_PANEL_WIDTH = 150\n\n# \u99d2\u306e\u5b9a\u6570\nEMPTY = ' '\nBLACK = '\u9ed2'\nWHITE = '\u767d'\n\n# \u99d2\u306e\u7a2e\u985e\u3068\u8868\u793a\u540d\nPIECES = {\n    'OU': '\u7389', 'HI': '\u98db', 'KA': '\u89d2', 'KI': '\u91d1',\n    'GI': '\u9280', 'KE': '\u6842', '\u9999': '\u9999', 'FU': '\u6b69',\n    'TO': '\u3068', 'N-GI': '\u6210\u9280', 'N-KE': '\u6210\u6842', 'N-KY': '\u6210\u9999',\n    'RY': '\u9f8d', 'UM': '\u99ac'\n}\n\n# \u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570\u3068\u3057\u3066\u30b2\u30fc\u30e0\u306e\u72b6\u614b\u3092\u4fdd\u6301\ngame_board = None\ncanvas = None\nselected_piece = None\noriginal_pos = None\ncurrent_player = BLACK\nblack_captures = &#091;]\nwhite_captures = &#091;]\nis_placing_piece = False\n\ndef create_initial_board():\n    \"\"\"\n    \u5c06\u68cb\u76e4\u306e\u521d\u671f\u914d\u7f6e\u3092\u8868\u73fe\u3059\u308b2\u6b21\u5143\u30ea\u30b9\u30c8\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\n    \u99d2\u306f (\u30d7\u30ec\u30a4\u30e4\u30fc, \u99d2\u306e\u7a2e\u985e) \u306e\u30bf\u30d7\u30eb\u3067\u8868\u73fe\u3057\u307e\u3059\u3002\n    \"\"\"\n    board = &#091;&#091;EMPTY] * 9 for _ in range(9)]\n\n    # \u767d\uff08\u5f8c\u624b\uff09\u306e\u99d2\u306e\u914d\u7f6e\n    board&#091;0]&#091;0] = (WHITE, '\u9999')\n    board&#091;0]&#091;1] = (WHITE, 'KE')\n    board&#091;0]&#091;2] = (WHITE, 'GI')\n    board&#091;0]&#091;3] = (WHITE, 'KI')\n    board&#091;0]&#091;4] = (WHITE, 'OU')\n    board&#091;0]&#091;5] = (WHITE, 'KI')\n    board&#091;0]&#091;6] = (WHITE, 'GI')\n    board&#091;0]&#091;7] = (WHITE, 'KE')\n    board&#091;0]&#091;8] = (WHITE, '\u9999')\n    board&#091;1]&#091;1] = (WHITE, 'HI')\n    board&#091;1]&#091;7] = (WHITE, 'KA')\n    for j in range(9):\n        board&#091;2]&#091;j] = (WHITE, 'FU')\n\n    # \u9ed2\uff08\u5148\u624b\uff09\u306e\u99d2\u306e\u914d\u7f6e\n    board&#091;8]&#091;0] = (BLACK, '\u9999')\n    board&#091;8]&#091;1] = (BLACK, 'KE')\n    board&#091;8]&#091;2] = (BLACK, 'GI')\n    board&#091;8]&#091;3] = (BLACK, 'KI')\n    board&#091;8]&#091;4] = (BLACK, 'OU')\n    board&#091;8]&#091;5] = (BLACK, 'KI')\n    board&#091;8]&#091;6] = (BLACK, 'GI')\n    board&#091;8]&#091;7] = (BLACK, 'KE')\n    board&#091;8]&#091;8] = (BLACK, '\u9999')\n    board&#091;7]&#091;1] = (BLACK, 'KA')\n    board&#091;7]&#091;7] = (BLACK, 'HI')\n    for j in range(9):\n        board&#091;6]&#091;j] = (BLACK, 'FU')\n\n    return board\n\n# --- \u99d2\u306e\u79fb\u52d5\u30eb\u30fc\u30eb (\u5909\u66f4\u306a\u3057) ---\ndef is_valid_pawn_move(start_row, start_col, end_row, end_col, player):\n    if player == BLACK:\n        return end_row == start_row - 1 and end_col == start_col\n    elif player == WHITE:\n        return end_row == start_row + 1 and end_col == start_col\n    return False\n\ndef is_valid_lance_move(start_row, start_col, end_row, end_col, player, board):\n    if end_col != start_col: return False\n    step = -1 if player == BLACK else 1\n    for r in range(start_row + step, end_row, step):\n        if board&#091;r]&#091;start_col] != EMPTY: return False\n    return True\n\ndef is_valid_king_move(start_row, start_col, end_row, end_col):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    return dx &lt;= 1 and dy &lt;= 1\n\ndef is_valid_rook_move(start_row, start_col, end_row, end_col, board):\n    if start_row == end_row:\n        step = 1 if end_col &gt; start_col else -1\n        for c in range(start_col + step, end_col, step):\n            if board&#091;start_row]&#091;c] != EMPTY: return False\n    elif start_col == end_col:\n        step = 1 if end_row &gt; start_row else -1\n        for r in range(start_row + step, end_row, step):\n            if board&#091;r]&#091;start_col] != EMPTY: return False\n    else:\n        return False\n    return True\n\ndef is_valid_bishop_move(start_row, start_col, end_row, end_col, board):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != dy or dx == 0: return False\n    step_x = 1 if end_col &gt; start_col else -1\n    step_y = 1 if end_row &gt; start_row else -1\n    for i in range(1, dx):\n        if board&#091;start_row + i * step_y]&#091;start_col + i * step_x] != EMPTY:\n            return False\n    return True\n\ndef is_valid_gold_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_silver_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_knight_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != 1 or dy != 2: return False\n    if player == BLACK:\n        return end_row == start_row - 2\n    elif player == WHITE:\n        return end_row == start_row + 2\n    return False\n# --- \u3053\u3053\u307e\u3067\u79fb\u52d5\u30eb\u30fc\u30eb\u5909\u66f4\u306a\u3057 ---\n\ndef draw_pieces():\n    \"\"\"\n    Python\u306e\u30dc\u30fc\u30c9\u60c5\u5831\u306b\u57fa\u3065\u3044\u3066\u3001canvas\u4e0a\u306b\u99d2\u3092\u63cf\u753b\u3057\u307e\u3059\u3002\n    \"\"\"\n    canvas.delete(\"all\")\n    \n    # \u76e4\u9762\u306e\u5347\u76ee\u3092\u63cf\u753b\n    for i in range(9):\n        for j in range(9):\n            x1 = j * CELL_SIZE\n            y1 = i * CELL_SIZE\n            x2 = x1 + CELL_SIZE\n            y2 = y1 + CELL_SIZE\n            canvas.create_rectangle(x1, y1, x2, y2, outline=\"black\", fill=\"#D2B48C\")\n            \n    # \u30dc\u30fc\u30c9\u4e0a\u306e\u99d2\u3092\u63cf\u753b\n    for r in range(9):\n        for c in range(9):\n            piece_data = game_board&#091;r]&#091;c]\n            if piece_data != EMPTY:\n                player, piece_type = piece_data\n                text_piece = PIECES&#091;piece_type]\n\n                x = c * CELL_SIZE + CELL_SIZE \/\/ 2\n                y = r * CELL_SIZE + CELL_SIZE \/\/ 2\n\n                color_bg = \"#E0C8A4\" if player == BLACK else \"#FFFFFF\"\n                canvas.create_rectangle(\n                    c * CELL_SIZE, r * CELL_SIZE,\n                    (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE,\n                    fill=color_bg, outline=\"black\"\n                )\n                color_text = \"black\"\n                canvas.create_text(\n                    x, y,\n                    text=text_piece,\n                    fill=color_text,\n                    font=(\"Arial\", 16)\n                )\n\n    # \u6301\u3061\u99d2\u306e\u8868\u793a\n    canvas.create_text(BOARD_SIZE + 20, 20, anchor=\"nw\", text=\"\u9ed2\u306e\u6301\u3061\u99d2\", font=(\"Arial\", 12))\n    for i, piece in enumerate(black_captures):\n        text_piece = PIECES&#091;piece&#091;1]]\n        y = 40 + i * 20\n        canvas.create_text(BOARD_SIZE + 30, y, anchor=\"nw\", text=f\"{text_piece}\", font=(\"Arial\", 12), tags=f\"black_capture_{i}\")\n\n    canvas.create_text(BOARD_SIZE + 20, 200, anchor=\"nw\", text=\"\u767d\u306e\u6301\u3061\u99d2\", font=(\"Arial\", 12))\n    for i, piece in enumerate(white_captures):\n        text_piece = PIECES&#091;piece&#091;1]]\n        y = 220 + i * 20\n        canvas.create_text(BOARD_SIZE + 30, y, anchor=\"nw\", text=f\"{text_piece}\", font=(\"Arial\", 12), tags=f\"white_capture_{i}\")\n\ndef should_promote(piece_type, player, start_row, end_row):\n    \"\"\"\n    \u99d2\u304c\u6210\u308b\u3079\u304d\u304b\u3092\u5224\u5b9a\u3059\u308b\u30d8\u30eb\u30d1\u30fc\u95a2\u6570\n    \"\"\"\n    if piece_type in &#091;'OU', 'KI', 'N-GI', 'N-KE', 'N-KY', 'RY', 'UM']:\n        return False\n    \n    if player == BLACK:\n        return end_row &lt;= 2 or start_row &lt;= 2\n    else:\n        return end_row &gt;= 6 or start_row &gt;= 6\n    \ndef get_promoted_piece(piece_type):\n    \"\"\"\n    \u99d2\u304c\u6210\u3063\u305f\u5f8c\u306e\u7a2e\u985e\u3092\u8fd4\u3059\n    \"\"\"\n    promotions = {\n        'FU': 'TO', '\u9999': 'N-KY', 'KE': 'N-KE', 'GI': 'N-GI', 'HI': 'RY', 'KA': 'UM',\n    }\n    return promotions.get(piece_type, piece_type)\n\n\ndef find_king(player):\n    \"\"\"\n    \u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u7389\u306e\u4f4d\u7f6e\u3092\u8fd4\u3059\n    \"\"\"\n    for r in range(9):\n        for c in range(9):\n            piece_data = game_board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == player and piece_data&#091;1] == 'OU':\n                return r, c\n    return None, None\n\ndef is_in_check(player, board):\n    \"\"\"\n    \u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u7389\u304c\u738b\u624b\u72b6\u614b\u306b\u3042\u308b\u304b\u3092\u5224\u5b9a\u3059\u308b\n    \"\"\"\n    king_row, king_col = find_king(player)\n    if king_row is None:\n        return False \n        \n    opponent = WHITE if player == BLACK else BLACK\n    \n    for r in range(9):\n        for c in range(9):\n            piece_data = board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == opponent:\n                piece_type = piece_data&#091;1]\n                \n                # \u76f8\u624b\u306e\u99d2\u304c\u7389\u306e\u4f4d\u7f6e\u306b\u52d5\u3051\u308b\u304b\u3092\u30c1\u30a7\u30c3\u30af\n                is_valid = False\n                if piece_type == 'FU' and is_valid_pawn_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == '\u9999' and is_valid_lance_move(r, c, king_row, king_col, opponent, board): is_valid = True\n                elif piece_type == 'HI' and is_valid_rook_move(r, c, king_row, king_col, board): is_valid = True\n                elif piece_type == 'KA' and is_valid_bishop_move(r, c, king_row, king_col, board): is_valid = True\n                elif piece_type == 'KI' and is_valid_gold_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == 'GI' and is_valid_silver_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == 'KE' and is_valid_knight_move(r, c, king_row, king_col, opponent): is_valid = True\n                elif piece_type == 'RY' and (is_valid_rook_move(r, c, king_row, king_col, board) or is_valid_king_move(r, c, king_row, king_col)): is_valid = True\n                elif piece_type == 'UM' and (is_valid_bishop_move(r, c, king_row, king_col, board) or is_valid_king_move(r, c, king_row, king_col)): is_valid = True\n                elif piece_type in &#091;'TO', 'N-GI', 'N-KE', 'N-KY'] and is_valid_gold_move(r, c, king_row, king_col, opponent): is_valid = True\n                \n                if is_valid:\n                    return True\n    return False\n\ndef is_checkmate(player, board):\n    \"\"\"\n    \u6307\u5b9a\u3055\u308c\u305f\u30d7\u30ec\u30a4\u30e4\u30fc\u304c\u8a70\u307f\u72b6\u614b\u306b\u3042\u308b\u304b\u3092\u5224\u5b9a\u3059\u308b\n    \"\"\"\n    if not is_in_check(player, board):\n        return False\n\n    king_row, king_col = find_king(player)\n    \n    # \u7389\u306e\u5468\u308a\u306e\u3059\u3079\u3066\u306e\u30de\u30b9\u3092\u30c1\u30a7\u30c3\u30af\n    for dr in range(-1, 2):\n        for dc in range(-1, 2):\n            if dr == 0 and dc == 0: continue\n            \n            new_row, new_col = king_row + dr, king_col + dc\n            \n            if 0 &lt;= new_row &lt; 9 and 0 &lt;= new_col &lt; 9:\n                target_piece = board&#091;new_row]&#091;new_col]\n                if target_piece == EMPTY or target_piece&#091;0] != player:\n                    temp_board = &#091;row&#091;:] for row in board]\n                    temp_board&#091;new_row]&#091;new_col] = (player, 'OU')\n                    temp_board&#091;king_row]&#091;king_col] = EMPTY\n                    \n                    if not is_in_check(player, temp_board):\n                        return False\n\n    return True\n\ndef on_click(event):\n    \"\"\"\n    \u30de\u30a6\u30b9\u304c\u30af\u30ea\u30c3\u30af\u3055\u308c\u305f\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\u3067\u3059\u3002\n    \"\"\"\n    global selected_piece, original_pos, is_placing_piece, current_player\n    \n    col = event.x \/\/ CELL_SIZE\n    row = event.y \/\/ CELL_SIZE\n    \n    # \u76e4\u9762\u5916\uff08\u6301\u3061\u99d2\u30a8\u30ea\u30a2\uff09\u3067\u306e\u30af\u30ea\u30c3\u30af\n    if col &gt;= 9:\n        if not is_placing_piece:\n            clicked_item = canvas.find_closest(event.x, event.y)&#091;0]\n            tags = canvas.gettags(clicked_item)\n            \n            if tags and tags&#091;0].startswith(f\"black_capture_\") and current_player == BLACK:\n                index = int(tags&#091;0].split('_')&#091;-1])\n                selected_piece = black_captures.pop(index)\n                is_placing_piece = True\n                draw_pieces()\n                \n                canvas.create_text(event.x, event.y, text=PIECES&#091;selected_piece&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\")\n                return\n            \n            if tags and tags&#091;0].startswith(f\"white_capture_\") and current_player == WHITE:\n                index = int(tags&#091;0].split('_')&#091;-1])\n                selected_piece = white_captures.pop(index)\n                is_placing_piece = True\n                draw_pieces()\n                \n                canvas.create_text(event.x, event.y, text=PIECES&#091;selected_piece&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\")\n                return\n\n    # \u76e4\u9762\u5185\u3067\u306e\u30af\u30ea\u30c3\u30af\n    if 0 &lt;= row &lt; 9 and 0 &lt;= col &lt; 9:\n        if is_placing_piece:\n            # \u6301\u3061\u99d2\u3092\u6253\u3064\u51e6\u7406\n            if game_board&#091;row]&#091;col] == EMPTY:\n                piece_type = selected_piece&#091;1]\n                player = selected_piece&#091;0]\n                \n                # \u884c\u304d\u6240\u306e\u306a\u3044\u99d2\n                if (piece_type == 'FU' or piece_type == '\u9999') and ((player == BLACK and row == 0) or (player == WHITE and row == 8)):\n                    print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u306b\u6253\u3066\u307e\u305b\u3093\u3002\")\n                    black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                    is_placing_piece = False\n                    selected_piece = None\n                    canvas.delete(\"drag_piece\")\n                    draw_pieces()\n                    return\n                if piece_type == 'KE' and ((player == BLACK and row &lt;= 1) or (player == WHITE and row &gt;= 7)):\n                    print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u306b\u6253\u3066\u307e\u305b\u3093\u3002\")\n                    black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                    is_placing_piece = False\n                    selected_piece = None\n                    canvas.delete(\"drag_piece\")\n                    draw_pieces()\n                    return\n                \n                # \u4e8c\u6b69\n                if piece_type == 'FU':\n                    is_nifu = False\n                    for r in range(9):\n                        piece_at_r = game_board&#091;r]&#091;col]\n                        if piece_at_r != EMPTY and piece_at_r&#091;0] == player and piece_at_r&#091;1] == 'FU':\n                            is_nifu = True\n                            break\n                    if is_nifu:\n                        print(\"\u305d\u306e\u7b4b\u306b\u306f\u65e2\u306b\u6b69\u304c\u3042\u308a\u307e\u3059\u3002\uff08\u4e8c\u6b69\uff09\")\n                        black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                        is_placing_piece = False\n                        selected_piece = None\n                        canvas.delete(\"drag_piece\")\n                        draw_pieces()\n                        return\n                \n                # \u6253\u3061\u6b69\u8a70\u3081\n                if is_in_check(WHITE if current_player == BLACK else BLACK, game_board) and piece_type == 'FU':\n                    temp_board = &#091;row&#091;:] for row in game_board]\n                    temp_board&#091;row]&#091;col] = selected_piece\n                    if is_checkmate(WHITE if current_player == BLACK else BLACK, temp_board):\n                        print(\"\u305d\u306e\u624b\u306f\u6253\u3061\u6b69\u8a70\u3081\u3067\u3059\u3002\")\n                        black_captures.append(selected_piece) if player == BLACK else white_captures.append(selected_piece)\n                        is_placing_piece = False\n                        selected_piece = None\n                        canvas.delete(\"drag_piece\")\n                        draw_pieces()\n                        return\n                \n                game_board&#091;row]&#091;col] = selected_piece\n                is_placing_piece = False\n                selected_piece = None\n                \n                current_player = WHITE if current_player == BLACK else BLACK\n                \n                # \u738b\u624b\u30fb\u8a70\u307f\u5224\u5b9a\n                if is_checkmate(current_player, game_board):\n                    print(\"\u8a70\u307f\u3067\u3059\uff01\u30b2\u30fc\u30e0\u7d42\u4e86\uff01\")\n                elif is_in_check(current_player, game_board):\n                    print(\"\u738b\u624b\uff01\")\n\n            else:\n                print(\"\u305d\u306e\u30de\u30b9\u306b\u306f\u99d2\u3092\u6253\u3066\u307e\u305b\u3093\u3002\")\n                capture_list = black_captures if selected_piece&#091;0] == BLACK else white_captures\n                capture_list.append(selected_piece)\n\n            canvas.delete(\"drag_piece\")\n            draw_pieces()\n            return\n            \n        else:\n            # \u76e4\u4e0a\u306e\u99d2\u3092\u9078\u629e\u3059\u308b\u51e6\u7406\n            piece_data = game_board&#091;row]&#091;col]\n            if piece_data != EMPTY and piece_data&#091;0] == current_player:\n                selected_piece = piece_data\n                original_pos = (row, col)\n                \n                game_board&#091;row]&#091;col] = EMPTY\n                draw_pieces()\n                \n                canvas.create_text(event.x, event.y, text=PIECES&#091;piece_data&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\")\n\ndef on_drag(event):\n    \"\"\"\n    \u30de\u30a6\u30b9\u304c\u30c9\u30e9\u30c3\u30b0\u3055\u308c\u3066\u3044\u308b\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\u3067\u3059\u3002\n    \"\"\"\n    if selected_piece:\n        canvas.coords(\"drag_piece\", event.x, event.y)\n\ndef on_release(event):\n    \"\"\"\n    \u30de\u30a6\u30b9\u30dc\u30bf\u30f3\u304c\u96e2\u3055\u308c\u305f\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\u3067\u3059\u3002\n    \"\"\"\n    global selected_piece, original_pos, current_player\n    \n    if is_placing_piece:\n        return\n        \n    if selected_piece:\n        new_col = event.x \/\/ CELL_SIZE\n        new_row = event.y \/\/ CELL_SIZE\n        \n        if not (0 &lt;= new_row &lt; 9 and 0 &lt;= new_col &lt; 9):\n            game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n            selected_piece = None\n            original_pos = None\n            canvas.delete(\"drag_piece\")\n            draw_pieces()\n            return\n\n        is_valid = False\n        piece_type = selected_piece&#091;1]\n        player = selected_piece&#091;0]\n        \n        if piece_type == 'FU':\n            is_valid = is_valid_pawn_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == '\u9999':\n            is_valid = is_valid_lance_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player, game_board)\n        elif piece_type == 'OU':\n            is_valid = is_valid_king_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col)\n        elif piece_type == 'HI':\n            is_valid = is_valid_rook_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board)\n        elif piece_type == 'KA':\n            is_valid = is_valid_bishop_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board)\n        elif piece_type == 'KI':\n            is_valid = is_valid_gold_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == 'GI':\n            is_valid = is_valid_silver_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == 'KE':\n            is_valid = is_valid_knight_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player)\n        elif piece_type == 'RY' and (is_valid_rook_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board) or is_valid_king_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col)): is_valid = True\n        elif piece_type == 'UM' and (is_valid_bishop_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, game_board) or is_valid_king_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col)): is_valid = True\n        elif piece_type in &#091;'TO', 'N-GI', 'N-KE', 'N-KY'] and is_valid_gold_move(original_pos&#091;0], original_pos&#091;1], new_row, new_col, player): is_valid = True\n        \n        target_piece = game_board&#091;new_row]&#091;new_col]\n        \n        if target_piece != EMPTY and target_piece&#091;0] == player:\n            is_valid = False\n            \n        if is_valid:\n            # \u884c\u304d\u6240\u306e\u306a\u3044\u99d2\n            if (piece_type == 'FU' or piece_type == '\u9999') and ((player == BLACK and new_row == 0) or (player == WHITE and new_row == 8)):\n                is_valid = False\n                print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u3078\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002\")\n            if piece_type == 'KE' and ((player == BLACK and new_row &lt;= 1) or (player == WHITE and new_row &gt;= 7)):\n                is_valid = False\n                print(\"\u305d\u306e\u99d2\u306f\u884c\u304d\u6240\u306e\u306a\u3044\u30de\u30b9\u3078\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002\")\n        \n        if is_valid:\n            temp_board = &#091;row&#091;:] for row in game_board]\n            if target_piece != EMPTY:\n                temp_board&#091;new_row]&#091;new_col] = selected_piece\n            else:\n                temp_board&#091;new_row]&#091;new_col] = selected_piece\n            \n            if is_in_check(player, temp_board):\n                print(\"\u305d\u306e\u624b\u306f\u53cd\u5247\u3067\u3059\u3002\u81ea\u5206\u306e\u7389\u304c\u738b\u624b\u306b\u306a\u3063\u3066\u3057\u307e\u3044\u307e\u3059\u3002\")\n                is_valid = False\n\n        if is_valid:\n            if target_piece != EMPTY:\n                captured_piece = target_piece&#091;1]\n                if player == BLACK:\n                    white_captures.append((BLACK, captured_piece))\n                else:\n                    black_captures.append((WHITE, captured_piece))\n\n            if should_promote(piece_type, player, original_pos&#091;0], new_row):\n                promoted_piece = get_promoted_piece(piece_type)\n                selected_piece = (player, promoted_piece)\n\n            game_board&#091;new_row]&#091;new_col] = selected_piece\n            \n            current_player = WHITE if current_player == BLACK else BLACK\n            \n            # \u738b\u624b\u30fb\u8a70\u307f\u5224\u5b9a\n            if is_checkmate(current_player, game_board):\n                print(\"\u8a70\u307f\u3067\u3059\uff01\u30b2\u30fc\u30e0\u7d42\u4e86\uff01\")\n            elif is_in_check(current_player, game_board):\n                print(\"\u738b\u624b\uff01\")\n\n        else:\n            print(\"\u305d\u306e\u99d2\u306f\u305d\u3053\u306b\u52d5\u304b\u305b\u307e\u305b\u3093\u3002\")\n            game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n        \n        selected_piece = None\n        original_pos = None\n\n        canvas.delete(\"drag_piece\")\n        draw_pieces()\n\ndef create_shogi_board():\n    \"\"\"\n    tkinter\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u3068\u5c06\u68cb\u76e4\u306eGUI\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\n    \"\"\"\n    global game_board, canvas\n    \n    root = tk.Tk()\n    root.title(\"\u5c06\u68cb\u30b2\u30fc\u30e0\")\n\n    canvas = tk.Canvas(root, width=BOARD_SIZE + SIDE_PANEL_WIDTH, height=BOARD_SIZE, bg=\"#D2B48C\")\n    canvas.pack()\n    \n    canvas.bind(\"&lt;Button-1&gt;\", on_click)\n    canvas.bind(\"&lt;B1-Motion&gt;\", on_drag)\n    canvas.bind(\"&lt;ButtonRelease-1&gt;\", on_release)\n            \n    game_board = create_initial_board()\n    draw_pieces()\n\n    root.mainloop()\n\nif __name__ == \"__main__\":\n    create_shogi_board()<\/code><\/pre>\n<\/details>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-f1ff71b35d7f13ecae5699cd4aec25c8 is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no3(<strong>Depth\u8a2d\u5b9a<\/strong>)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>#DEPTH2\u5909\u66f4\nimport tkinter as tk\nfrom collections import Counter\nfrom tkinter import messagebox\nimport sys\nimport random\nimport copy\nimport time \n\n# \u30a6\u30a3\u30f3\u30c9\u30a6\u3068\u30ad\u30e3\u30f3\u30d0\u30b9\u306e\u30b5\u30a4\u30ba\nBOARD_SIZE = 450\nCELL_SIZE = BOARD_SIZE \/\/ 9\nSIDE_PANEL_WIDTH = 150\nCAPTURE_CELL_HEIGHT = 25 \n\n# \u99d2\u306e\u5b9a\u6570\nEMPTY = ' '\nBLACK = '\u9ed2'\nWHITE = '\u767d'\n\n# \u99d2\u306e\u7a2e\u985e\u3068\u8868\u793a\u540d\nPIECES = {\n    'OU': '\u7389', 'HI': '\u98db', 'KA': '\u89d2', 'KI': '\u91d1',\n    'GI': '\u9280', 'KE': '\u6842', '\u9999': '\u9999', 'FU': '\u6b69',\n    'TO': '\u3068', 'N-GI': '\u6210\u9280', 'N-KE': '\u6210\u6842', 'N-KY': '\u6210\u9999',\n    'RY': '\u9f8d', 'UM': '\u99ac'\n}\n\n# \u99d2\u306e\u4e26\u3073\u9806 (\u99d2\u53f0\u8868\u793a\u7528)\nPIECE_ORDER = &#091;'HI', 'KA', 'RY', 'UM', 'KI', 'GI', 'KE', '\u9999', 'FU'] \n\n# \u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570\ngame_board = None\ncanvas = None\nroot = None \nselected_piece = None\noriginal_pos = None\ncurrent_player = BLACK\nblack_captures = &#091;]\nwhite_captures = &#091;]\nis_placing_piece = False\ngame_states = &#091;] # \u5343\u65e5\u624b\u5224\u5b9a\u7528\u306e\u7c21\u6613\u5c65\u6b74 (Minimax\u7528)\nhighlight_moves = &#091;] \ngame_running = True\nAI_PLAYER = WHITE\nkifu_text = None # \u2605 \u68cb\u8b5c\u8868\u793a\u7528\u30a6\u30a3\u30b8\u30a7\u30c3\u30c8\n\n# \u30b2\u30fc\u30e0\u5c65\u6b74 (Undo\u7528)\nhistory = &#091;] \n\nking_flash_job = None\nis_flashing = False\n\n# AI\u306e\u63a2\u7d22\u6df1\u3055 (\u8abf\u6574\u53ef\u80fd)\nSEARCH_DEPTH = 2 \n\n# \u99d2\u306e\u57fa\u672c\u8a55\u4fa1\u5024 \nPIECE_VALUES = {\n    'OU': 10000, \n    'HI': 1000, 'KA': 800, \n    'KI': 500, 'GI': 400, \n    'KE': 300, '\u9999': 200, 'FU': 100,\n    'RY': 1300, 'UM': 1000, \n    'TO': 600, 'N-GI': 500, 'N-KE': 400, 'N-KY': 300\n}\n\n# --- \u68cb\u8b5c\u8868\u793a\u7528\u30ed\u30b8\u30c3\u30af ---\n\n# \u65e5\u672c\u8a9e\u306e\u7b4b\u30fb\u6bb5\nKANJI_COLUMNS = &#091;\"\uff19\", \"\uff18\", \"\uff17\", \"\uff16\", \"\uff15\", \"\uff14\", \"\uff13\", \"\uff12\", \"\uff11\"]\nKANJI_ROWS = &#091;\"\u4e00\", \"\u4e8c\", \"\u4e09\", \"\u56db\", \"\u4e94\", \"\u516d\", \"\u4e03\", \"\u516b\", \"\u4e5d\"]\n\ndef coords_to_kifu(r, c):\n    \"\"\"\u5ea7\u6a19 (row, col) \u3092\u68cb\u8b5c\u306e\u6bb5\u30fb\u7b4b\u306b\u5909\u63db\u3059\u308b (\u4f8b: 7, 7 -&gt; 3\u4e8c)\"\"\"\n    return KANJI_COLUMNS&#091;c] + KANJI_ROWS&#091;r]\n\ndef piece_type_to_kifu(piece_type):\n    \"\"\"\u99d2\u306e\u7a2e\u985e\u3092\u68cb\u8b5c\u8868\u793a\u7528\u306e\u540d\u524d\u306b\u5909\u63db\u3059\u308b\"\"\"\n    return PIECES.get(piece_type, piece_type)\n\ndef format_move_to_kifu(move_details, current_player, board_before_move):\n    \"\"\"\u6307\u3057\u624b\u3092\u68cb\u8b5c\u306e\u6587\u5b57\u5217\u306b\u5909\u63db\u3059\u308b\"\"\"\n    move_type = move_details&#091;0]\n    \n    if move_type == 'move':\n        _, start_r, start_c, end_r, end_c, promote = move_details\n        \n        # \u79fb\u52d5\u524d\u306e\u99d2\u30bf\u30a4\u30d7\u3092\u53d6\u5f97\n        piece_data = board_before_move&#091;start_r]&#091;start_c]\n        if piece_data == EMPTY: return \"\" # \u30a8\u30e9\u30fc\u56de\u907f\n        piece_type = piece_data&#091;1] \n        \n        kifu_piece = piece_type_to_kifu(piece_type)\n        kifu_end_pos = coords_to_kifu(end_r, end_c)\n        kifu_promote = \"\u6210\" if promote else \"\"\n        \n        return f\"{kifu_end_pos}{kifu_piece}{kifu_promote}\"\n\n    elif move_type == 'drop':\n        _, piece_type, end_r, end_c = move_details\n        \n        kifu_piece = piece_type_to_kifu(piece_type)\n        kifu_end_pos = coords_to_kifu(end_r, end_c)\n        \n        return f\"{kifu_end_pos}{kifu_piece}\u6253\"\n        \n    return \"\"\n\ndef append_kifu(kifu_string):\n    \"\"\"GUI\u306e\u30c6\u30ad\u30b9\u30c8\u30a8\u30ea\u30a2\u306b\u68cb\u8b5c\u3092\u8ffd\u8a18\u3059\u308b\"\"\"\n    global kifu_text\n    if kifu_text:\n        kifu_text.config(state=tk.NORMAL)\n        kifu_text.insert(tk.END, kifu_string + \"\\n\")\n        kifu_text.see(tk.END)\n        kifu_text.config(state=tk.DISABLED)\n\n# --- \u521d\u671f\u5316 ---\n\ndef create_initial_board():\n    \"\"\"\u5c06\u68cb\u76e4\u306e\u521d\u671f\u914d\u7f6e\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\"\"\"\n    board = &#091;&#091;EMPTY] * 9 for _ in range(9)]\n\n    # \u767d\uff08\u5f8c\u624b\uff09\u306e\u99d2\u306e\u914d\u7f6e\n    board&#091;0]&#091;0] = (WHITE, '\u9999'); board&#091;0]&#091;1] = (WHITE, 'KE'); board&#091;0]&#091;2] = (WHITE, 'GI'); board&#091;0]&#091;3] = (WHITE, 'KI'); board&#091;0]&#091;4] = (WHITE, 'OU'); board&#091;0]&#091;5] = (WHITE, 'KI'); board&#091;0]&#091;6] = (WHITE, 'GI'); board&#091;0]&#091;7] = (WHITE, 'KE'); board&#091;0]&#091;8] = (WHITE, '\u9999')\n    board&#091;1]&#091;1] = (WHITE, 'HI'); board&#091;1]&#091;7] = (WHITE, 'KA') \n    for j in range(9): board&#091;2]&#091;j] = (WHITE, 'FU')\n\n    # \u9ed2\uff08\u5148\u624b\uff09\u306e\u99d2\u306e\u914d\u7f6e\n    board&#091;8]&#091;0] = (BLACK, '\u9999'); board&#091;8]&#091;1] = (BLACK, 'KE'); board&#091;8]&#091;2] = (BLACK, 'GI'); board&#091;8]&#091;3] = (BLACK, 'KI'); board&#091;8]&#091;4] = (BLACK, 'OU'); board&#091;8]&#091;5] = (BLACK, 'KI'); board&#091;8]&#091;6] = (BLACK, 'GI'); board&#091;8]&#091;7] = (BLACK, 'KE'); board&#091;8]&#091;8] = (BLACK, '\u9999')\n    board&#091;7]&#091;7] = (BLACK, 'HI'); board&#091;7]&#091;1] = (BLACK, 'KA')\n    for j in range(9): board&#091;6]&#091;j] = (BLACK, 'FU')\n\n    return board\n\n# --- \u99d2\u306e\u79fb\u52d5\u30eb\u30fc\u30eb (\u9999\u8eca\u4fee\u6b63\u6e08\u307f) ---\n\ndef is_valid_pawn_move(start_row, start_col, end_row, end_col, player):\n    if player == BLACK: return end_row == start_row - 1 and end_col == start_col\n    elif player == WHITE: return end_row == start_row + 1 and end_col == start_col\n    return False\n\ndef is_valid_lance_move(start_row, start_col, end_row, end_col, player, board):\n    \"\"\"\u9999\u8eca\u306e\u79fb\u52d5\u30ed\u30b8\u30c3\u30af (\u9593\u306b\u99d2\u304c\u306a\u3044\u304b\u30c1\u30a7\u30c3\u30af)\"\"\"\n    if end_col != start_col: return False\n    \n    # \u9999\u8eca\u306f\u5f8c\u9000\u3067\u304d\u306a\u3044\n    if player == BLACK and end_row &gt;= start_row: return False\n    if player == WHITE and end_row &lt;= start_row: return False\n    \n    step = -1 if player == BLACK else 1\n    \n    # \u9014\u4e2d\u306e\u30de\u30b9\u306b\u99d2\u304c\u306a\u3044\u304b\u30c1\u30a7\u30c3\u30af\n    for r in range(start_row + step, end_row, step):\n        if board&#091;r]&#091;start_col] != EMPTY: \n            return False\n\n    # \u76ee\u7684\u5730 (end_row, end_col) \u306e\u30c1\u30a7\u30c3\u30af\n    target_piece = board&#091;end_row]&#091;end_col]\n    \n    # \u81ea\u99d2\u304c\u3042\u308c\u3070\u79fb\u52d5\u4e0d\u53ef\n    if target_piece != EMPTY and target_piece&#091;0] == player:\n        return False\n        \n    return True \n\ndef is_valid_king_move(start_row, start_col, end_row, end_col):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    return dx &lt;= 1 and dy &lt;= 1\n\ndef is_valid_rook_move(start_row, start_col, end_row, end_col, board):\n    if start_row == end_row:\n        step = 1 if end_col &gt; start_col else -1\n        for c in range(start_col + step, end_col, step):\n            if board&#091;start_row]&#091;c] != EMPTY: return False\n    elif start_col == end_col:\n        step = 1 if end_row &gt; start_row else -1\n        for r in range(start_row + step, end_row, step):\n            if board&#091;r]&#091;start_col] != EMPTY: return False\n    else: return False\n    return True\n\ndef is_valid_bishop_move(start_row, start_col, end_row, end_col, board):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != dy or dx == 0: return False\n    step_x = 1 if end_col &gt; start_col else -1\n    step_y = 1 if end_row &gt; start_row else -1\n    for i in range(1, dx):\n        if board&#091;start_row + i * step_y]&#091;start_col + i * step_x] != EMPTY: return False\n    return True\n\ndef is_valid_gold_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_silver_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_knight_move(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != 1 or dy != 2: return False\n    if player == BLACK: return end_row == start_row - 2\n    elif player == WHITE: return end_row == start_row + 2\n    return False\n\ndef is_valid_move_logic(start_row, start_col, end_row, end_col, piece_type, player, board):\n    if piece_type == 'FU': return is_valid_pawn_move(start_row, start_col, end_row, end_col, player)\n    elif piece_type == '\u9999': return is_valid_lance_move(start_row, start_col, end_row, end_col, player, board)\n    elif piece_type == 'OU': return is_valid_king_move(start_row, start_col, end_row, end_col)\n    elif piece_type == 'HI': return is_valid_rook_move(start_row, start_col, end_row, end_col, board)\n    elif piece_type == 'KA': return is_valid_bishop_move(start_row, start_col, end_row, end_col, board)\n    elif piece_type == 'KI': return is_valid_gold_move(start_row, start_col, end_row, end_col, player)\n    elif piece_type == 'GI': return is_valid_silver_move(start_row, start_col, end_row, end_col, player)\n    elif piece_type == 'KE': return is_valid_knight_move(start_row, start_col, end_row, end_col, player)\n    elif piece_type == 'RY': return is_valid_rook_move(start_row, start_col, end_row, end_col, board) or is_valid_king_move(start_row, start_col, end_row, end_col)\n    elif piece_type == 'UM': return is_valid_bishop_move(start_row, start_col, end_row, end_col, board) or is_valid_king_move(start_row, start_col, end_row, end_col)\n    elif piece_type in &#091;'TO', 'N-GI', 'N-KE', 'N-KY']: return is_valid_gold_move(start_row, start_col, end_row, end_col, player)\n    return False\n\n# --- \u738b\u624b\u30fb\u8a70\u307f\u5224\u5b9a ---\n\ndef find_king(player, board):\n    for r in range(9):\n        for c in range(9):\n            piece_data = board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == player and piece_data&#091;1] == 'OU':\n                return r, c\n    return None, None\n\ndef is_in_check(player, board):\n    king_row, king_col = find_king(player, board)\n    if king_row is None: return False \n    opponent = WHITE if player == BLACK else BLACK\n    for r in range(9):\n        for c in range(9):\n            piece_data = board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == opponent:\n                piece_type = piece_data&#091;1]\n                if is_valid_move_logic(r, c, king_row, king_col, piece_type, opponent, board):\n                    return True\n    return False\n\ndef is_promoted_piece(piece_type):\n    return piece_type in &#091;'TO', 'N-KY', 'N-KE', 'N-GI', 'RY', 'UM']\n\ndef should_promote(piece_type, player, start_row, end_row):\n    if piece_type in &#091;'OU', 'KI'] or is_promoted_piece(piece_type): return False\n    if player == BLACK: \n        return end_row &lt;= 2 or start_row &lt;= 2\n    else: \n        return end_row &gt;= 6 or start_row &gt;= 6\n\ndef get_promoted_piece(piece_type):\n    promotions = {'FU': 'TO', '\u9999': 'N-KY', 'KE': 'N-KE', 'GI': 'N-GI', 'HI': 'RY', 'KA': 'UM'}\n    return promotions.get(piece_type, piece_type)\n\ndef get_valid_moves(r, c, board, current_captures):\n    if board&#091;r]&#091;c] == EMPTY: return &#091;]\n    player, piece_type = board&#091;r]&#091;c]\n    valid_moves = &#091;]\n    \n    for end_r in range(9):\n        for end_c in range(9):\n            if r == end_r and c == end_c: continue\n            target_piece = board&#091;end_r]&#091;end_c]\n            if target_piece != EMPTY and target_piece&#091;1] == 'OU': continue\n            if target_piece != EMPTY and target_piece&#091;0] == player: continue\n            if not is_valid_move_logic(r, c, end_r, end_c, piece_type, player, board): continue\n            if piece_type in &#091;'FU', '\u9999'] and ((player == BLACK and end_r == 0) or (player == WHITE and end_r == 8)): continue\n            if piece_type == 'KE' and ((player == BLACK and end_r &lt;= 1) or (player == WHITE and end_r &gt;= 7)): continue\n\n            temp_board = &#091;row&#091;:] for row in board]\n            temp_board&#091;end_r]&#091;end_c] = (player, piece_type)\n            temp_board&#091;r]&#091;c] = EMPTY\n            \n            if not is_in_check(player, temp_board):\n                valid_moves.append((end_r, end_c))\n\n    return valid_moves\n\ndef get_all_legal_moves(player, board, black_captures_in, white_captures_in):\n    all_moves = &#091;]\n    \n    # 1. \u76e4\u4e0a\u306e\u99d2\u306e\u79fb\u52d5\n    for r in range(9):\n        for c in range(9):\n            piece_data = board&#091;r]&#091;c]\n            if piece_data != EMPTY and piece_data&#091;0] == player:\n                piece_type = piece_data&#091;1]\n                valid_ends = get_valid_moves(r, c, board, black_captures_in if player == BLACK else white_captures_in) \n                \n                for end_r, end_c in valid_ends:\n                    is_forced_promotion = False\n                    if piece_type in &#091;'FU', '\u9999'] and ((player == BLACK and end_r == 0) or (player == WHITE and end_r == 8)): is_forced_promotion = True\n                    if piece_type == 'KE' and ((player == BLACK and end_r &lt;= 1) or (player == WHITE and end_r &gt;= 7)): is_forced_promotion = True\n                    \n                    can_promote_option = should_promote(piece_type, player, r, end_r) and not is_forced_promotion\n\n                    if is_promoted_piece(piece_type):\n                        all_moves.append(('move', r, c, end_r, end_c, False))\n                        continue\n                        \n                    if is_forced_promotion:\n                        all_moves.append(('move', r, c, end_r, end_c, True))\n                    elif can_promote_option:\n                        all_moves.append(('move', r, c, end_r, end_c, True)) \n                        all_moves.append(('move', r, c, end_r, end_c, False)) \n                    else:\n                        all_moves.append(('move', r, c, end_r, end_c, False)) \n                        \n    # 2. \u6301\u3061\u99d2\u306e\u6253\u3061\u8fbc\u307f\n    capture_list = black_captures_in if player == BLACK else white_captures_in\n    available_drop_pieces = set(&#091;p&#091;1] for p in capture_list])\n    \n    for piece_type in available_drop_pieces:\n        for r in range(9):\n            for c in range(9):\n                if board&#091;r]&#091;c] == EMPTY:\n                    is_valid_drop = True\n                    \n                    if (piece_type == 'FU' or piece_type == '\u9999') and ((player == BLACK and r == 0) or (player == WHITE and r == 8)): is_valid_drop = False\n                    if piece_type == 'KE' and ((player == BLACK and r &lt;= 1) or (player == WHITE and r &gt;= 7)): is_valid_drop = False\n                    \n                    if piece_type == 'FU':\n                        for r_check in range(9):\n                            piece_at_r = board&#091;r_check]&#091;c]\n                            if piece_at_r != EMPTY and piece_at_r&#091;0] == player and piece_at_r&#091;1] == 'FU':\n                                is_valid_drop = False; break\n                    \n                    if is_valid_drop:\n                        temp_board = &#091;row&#091;:] for row in board]\n                        temp_board&#091;r]&#091;c] = (player, piece_type)\n                        opponent = WHITE if player == BLACK else BLACK\n                        \n                        temp_caps_b = black_captures_in&#091;:]\n                        temp_caps_w = white_captures_in&#091;:]\n                        temp_capture_list = temp_caps_b if player == BLACK else temp_caps_w\n                        \n                        try:\n                             temp_capture_list.remove((player, piece_type))\n                        except ValueError:\n                             pass\n                            \n                        # \u6253\u3061\u6b69\u8a70\u3081\u30c1\u30a7\u30c3\u30af\n                        if piece_type == 'FU' and is_in_check(opponent, temp_board) and is_checkmate(opponent, temp_board, temp_caps_b, temp_caps_w):\n                            is_valid_drop = False \n                            \n                        # \u738b\u624b\u653e\u7f6e\u30c1\u30a7\u30c3\u30af \n                        if is_in_check(player, temp_board):\n                            is_valid_drop = False\n\n                    if is_valid_drop:\n                        all_moves.append(('drop', piece_type, r, c))\n                        \n    return all_moves\n\ndef is_checkmate(player, board, black_captures_in, white_captures_in):\n    if not is_in_check(player, board):\n        return False\n    legal_moves = get_all_legal_moves(player, board, black_captures_in, white_captures_in)\n    return len(legal_moves) == 0\n\n# --- \u5f37\u5316AI\u30ed\u30b8\u30c3\u30af (Minimax) ---\n\ndef apply_move(board, captures_black, captures_white, move, player):\n    new_board = &#091;row&#091;:] for row in board]\n    new_caps_b = captures_black&#091;:]\n    new_caps_w = captures_white&#091;:]\n    \n    capture_list_player = new_caps_b if player == BLACK else new_caps_w\n\n    move_type = move&#091;0]\n\n    if move_type == 'move':\n        _, start_r, start_c, end_r, end_c, promote = move\n        \n        piece_data = new_board&#091;start_r]&#091;start_c]\n        piece_type = piece_data&#091;1]\n        target_piece = new_board&#091;end_r]&#091;end_c]\n        \n        if target_piece != EMPTY:\n            captured_piece = target_piece&#091;1]\n            demotion = {'TO': 'FU', 'N-KY': '\u9999', 'N-KE': 'KE', 'N-GI': 'GI', 'RY': 'HI', 'UM': 'KA'}\n            captured_piece = demotion.get(captured_piece, captured_piece)\n            capture_list_player.append((player, captured_piece))\n\n        if promote: piece_type = get_promoted_piece(piece_type)\n            \n        new_board&#091;end_r]&#091;end_c] = (player, piece_type)\n        new_board&#091;start_r]&#091;start_c] = EMPTY\n        \n    elif move_type == 'drop':\n        _, piece_type, end_r, end_c = move\n        \n        try:\n            capture_list_player.remove((player, piece_type))\n        except ValueError:\n            return new_board, new_caps_b, new_caps_w\n\n        new_board&#091;end_r]&#091;end_c] = (player, piece_type)\n\n    return new_board, new_caps_b, new_caps_w\n\ndef evaluate_board(board, captures_black, captures_white, player):\n    score = 0\n    \n    for r in range(9):\n        for c in range(9):\n            piece_data = board&#091;r]&#091;c]\n            if piece_data != EMPTY:\n                value = PIECE_VALUES.get(piece_data&#091;1], 0)\n                if piece_data&#091;0] == WHITE:\n                    score += value\n                else: \n                    score -= value\n                    \n    for _, piece_type in captures_white:\n        score += PIECE_VALUES.get(piece_type, 0)\n    for _, piece_type in captures_black:\n        score -= PIECE_VALUES.get(piece_type, 0)\n        \n    if is_in_check(WHITE, board):\n        score -= 900 \n    if is_in_check(BLACK, board):\n        score += 900 \n        \n    if is_checkmate(WHITE, board, captures_black, captures_white):\n        return -float('inf') \n    if is_checkmate(BLACK, board, captures_black, captures_white):\n        return float('inf') \n\n    return score\n\ndef minimax(board, captures_black, captures_white, depth, is_maximizing_player, alpha, beta):\n    current_player_minimax = WHITE if is_maximizing_player else BLACK\n    \n    if depth == 0:\n        return evaluate_board(board, captures_black, captures_white, current_player_minimax), None\n\n    if is_checkmate(WHITE, board, captures_black, captures_white):\n        return -float('inf'), None\n    if is_checkmate(BLACK, board, captures_black, captures_white):\n        return float('inf'), None\n\n    legal_moves = get_all_legal_moves(current_player_minimax, board, captures_black, captures_white)\n\n    if not legal_moves:\n        return evaluate_board(board, captures_black, captures_white, current_player_minimax), None\n\n    best_move = None\n    \n    if is_maximizing_player: \n        max_eval = -float('inf')\n        random.shuffle(legal_moves)\n        for move in legal_moves:\n            new_board, new_caps_b, new_caps_w = apply_move(board, captures_black, captures_white, move, WHITE)\n            current_eval, _ = minimax(new_board, new_caps_b, new_caps_w, depth - 1, False, alpha, beta)\n            \n            if current_eval &gt; max_eval:\n                max_eval = current_eval\n                best_move = move\n            \n            alpha = max(alpha, max_eval)\n            if beta &lt;= alpha:\n                break\n        return max_eval, best_move\n        \n    else: \n        min_eval = float('inf')\n        random.shuffle(legal_moves)\n        for move in legal_moves:\n            new_board, new_caps_b, new_caps_w = apply_move(board, captures_black, captures_white, move, BLACK)\n            current_eval, _ = minimax(new_board, new_caps_b, new_caps_w, depth - 1, True, alpha, beta)\n            \n            if current_eval &lt; min_eval:\n                min_eval = current_eval\n                best_move = move\n                \n            beta = min(beta, min_eval)\n            if beta &lt;= alpha:\n                break\n        return min_eval, best_move\n\ndef find_best_move(board, captures_black, captures_white, player, depth):\n    start_time = time.time()\n    _, best_move = minimax(board, captures_black, captures_white, depth, True, -float('inf'), float('inf'))\n    end_time = time.time()\n    print(f\"Minimax\u63a2\u7d22\u6642\u9593: {end_time - start_time:.2f}\u79d2 (\u6df1\u3055: {depth})\")\n    return best_move\n\n# --- AI\u6a5f\u80fd\u306e\u66f4\u65b0 ---\n\ndef make_ai_move():\n    global game_board, white_captures, black_captures, current_player, game_running, game_states\n    \n    if not game_running or current_player != AI_PLAYER: return\n    \n    ai_player = AI_PLAYER\n    opponent = BLACK\n    \n    # \u68cb\u8b5c\u8a18\u9332\u7528\u306b\u79fb\u52d5\u524d\u306e\u76e4\u9762\u3092\u30b3\u30d4\u30fc\n    board_before_move = copy.deepcopy(game_board)\n\n    chosen_move = find_best_move(game_board, black_captures, white_captures, ai_player, SEARCH_DEPTH)\n    \n    if chosen_move is None:\n        if is_in_check(ai_player, game_board):\n            messagebox.showinfo(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", f\"AI ({ai_player}) \u306f\u8a70\u307f\u3067\u3059\u3002{opponent}\u306e\u52dd\u5229\uff01\")\n        else:\n             messagebox.showinfo(\"\u8b66\u544a\", f\"AI ({ai_player}) \u306f\u5408\u6cd5\u624b\u3092\u898b\u3064\u3051\u3089\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002\")\n        game_running = False\n        return\n\n    move_type = chosen_move&#091;0]\n    \n    if move_type == 'move':\n        _, start_r, start_c, end_r, end_c, promote = chosen_move\n        player, piece_type = game_board&#091;start_r]&#091;start_c]\n        target_piece = game_board&#091;end_r]&#091;end_c]\n        \n        if target_piece != EMPTY:\n            captured_piece = target_piece&#091;1]\n            demotion = {'TO': 'FU', 'N-KY': '\u9999', 'N-KE': 'KE', 'N-GI': 'GI', 'RY': 'HI', 'UM': 'KA'}\n            captured_piece = demotion.get(captured_piece, captured_piece)\n            white_captures.append((ai_player, captured_piece))\n\n        if promote: piece_type = get_promoted_piece(piece_type)\n            \n        game_board&#091;end_r]&#091;end_c] = (player, piece_type)\n        game_board&#091;start_r]&#091;start_c] = EMPTY\n        \n    elif move_type == 'drop':\n        _, piece_type, end_r, end_c = chosen_move\n        \n        capture_list_ref = white_captures\n        for i, (p, p_type) in enumerate(capture_list_ref):\n            if p_type == piece_type:\n                capture_list_ref.pop(i)\n                break\n                \n        game_board&#091;end_r]&#091;end_c] = (ai_player, piece_type)\n\n    # \u2605 \u68cb\u8b5c\u306e\u8a18\u9332 (AI\u306e\u624b\u306f\u5947\u6570\u624b)\n    move_details = chosen_move\n    turn_count = (len(history) \/\/ 2) + 1 \n    kifu_str = format_move_to_kifu(move_details, ai_player, board_before_move)\n\n    append_kifu(f\"   \u2616{kifu_str}\")\n    # \u2605 --------------------------\n\n    handle_end_turn(opponent)\n\n\n# --- \u30a4\u30d9\u30f3\u30c8\u30cf\u30f3\u30c9\u30e9 (\u5c65\u6b74\u4fdd\u5b58\u3068Undo) ---\n\ndef get_simple_state_string(board, player):\n    state_str = \"\".join(\"E\" if cell == EMPTY else cell&#091;0] + cell&#091;1] for row in board for cell in row)\n    state_str += \"T\" + player\n    return state_str\n\ndef save_state():\n    \"\"\"\u73fe\u5728\u306e\u30b2\u30fc\u30e0\u72b6\u614b\u3092\u30c7\u30a3\u30fc\u30d7\u30b3\u30d4\u30fc\u3057\u3066\u5c65\u6b74\u306b\u4fdd\u5b58\u3059\u308b\"\"\"\n    global history\n    state = (\n        copy.deepcopy(game_board),\n        copy.deepcopy(black_captures),\n        copy.deepcopy(white_captures),\n        current_player,\n        copy.deepcopy(game_states) \n    )\n    history.append(state)\n\ndef undo_move():\n    \"\"\"\u4e00\u624b\u524d\u306e\u72b6\u614b\u306b\u623b\u3059 (\u6301\u3061\u99d2\u5897\u52a0\u30d0\u30b0\u4fee\u6b63\u6e08\u307f)\"\"\"\n    global game_board, black_captures, white_captures, current_player, game_states, game_running\n    global selected_piece, original_pos, is_placing_piece, highlight_moves\n\n    if len(history) &lt;= 1:\n        messagebox.showinfo(\"\u8b66\u544a\", \"\u521d\u671f\u72b6\u614b\u306e\u305f\u3081\u3001\u3053\u308c\u4ee5\u4e0a\u623b\u305b\u307e\u305b\u3093\u3002\")\n        return\n    \n    if current_player == AI_PLAYER:\n        messagebox.showinfo(\"\u8b66\u544a\", \"AI\u306e\u624b\u756a\u4e2d\u306fUndo\u3067\u304d\u307e\u305b\u3093\u3002\")\n        return\n\n    stop_flashing()\n\n    # \u81ea\u5206\u306e\u6307\u3057\u305f\u4e00\u624b\u3068\u305d\u306e\u7d50\u679c\u306e\u30bf\u30fc\u30f3 (\u8a082\u3064\u306e\u5c65\u6b74) \u3092\u524a\u9664\n    if len(history) &gt;= 2:\n        history.pop() \n        history.pop() \n    else:\n         history.pop() \n\n    if history:\n        prev_state = history&#091;-1]\n        \n        game_board = copy.deepcopy(prev_state&#091;0])\n        black_captures = copy.deepcopy(prev_state&#091;1])\n        white_captures = copy.deepcopy(prev_state&#091;2])\n        current_player = prev_state&#091;3]\n        game_states = copy.deepcopy(prev_state&#091;4])\n\n        # \u2605 \u68cb\u8b5c\u8868\u793a\u306e\u66f4\u65b0 (\u5168\u6d88\u3057\uff06\u518d\u69cb\u7bc9\u304c\u6700\u3082\u5b89\u5168)\n        if kifu_text:\n            kifu_text.config(state=tk.NORMAL)\n            kifu_text.delete(1.0, tk.END)\n            kifu_text.config(state=tk.DISABLED)\n            \n            # \u7c21\u7565\u5316\u306e\u305f\u3081\u3001Undo\u5f8c\u306e\u68cb\u8b5c\u306f\u8868\u793a\u3057\u306a\u3044\n            # \u6b63\u78ba\u306b\u5b9f\u88c5\u3059\u308b\u306b\u306f\u3001history\u304b\u3089\u68cb\u8b5c\u3092\u518d\u69cb\u7bc9\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\n    else:\n        # \u521d\u671f\u72b6\u614b\u306b\u623b\u3059\n        game_board = create_initial_board()\n        black_captures = &#091;]\n        white_captures = &#091;]\n        current_player = BLACK\n        game_states = &#091;get_simple_state_string(game_board, BLACK)]\n        save_state()\n        if kifu_text:\n            kifu_text.config(state=tk.NORMAL)\n            kifu_text.delete(1.0, tk.END)\n            kifu_text.config(state=tk.DISABLED)\n\n    selected_piece = None\n    original_pos = None\n    is_placing_piece = False\n    highlight_moves = &#091;]\n    game_running = True \n\n    draw_pieces()\n    if is_in_check(current_player, game_board):\n        flash_king()\n\n    print(f\"\u4e00\u624b\u623b\u3057\u307e\u3057\u305f\u3002\u73fe\u5728\u306e\u30d7\u30ec\u30a4\u30e4\u30fc: {current_player}\")\n    \n    if current_player == AI_PLAYER and game_running:\n        canvas.after(500, make_ai_move)\n\ndef handle_end_turn(next_player):\n    \"\"\"\u30bf\u30fc\u30f3\u306e\u7d42\u308f\u308a\u306b\u547c\u3070\u308c\u308b\u5171\u901a\u51e6\u7406\"\"\"\n    global current_player, game_running\n    \n    current_player = next_player\n    \n    current_state = get_simple_state_string(game_board, current_player)\n    game_states.append(current_state)\n    \n    save_state()\n\n    stop_flashing()\n    \n    if game_running:\n        draw_pieces()\n        \n        if is_checkmate(current_player, game_board, black_captures, white_captures):\n            winner = BLACK if current_player == WHITE else WHITE\n            messagebox.showinfo(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", f\"\u8a70\u307f\u3067\u3059\uff01{winner}\u306e\u52dd\u5229\uff01\")\n            game_running = False\n        \n        elif is_in_check(current_player, game_board):\n            print(f\"\u738b\u624b\uff01({current_player}\u7389)\")\n            flash_king() \n\n        if current_player == AI_PLAYER and game_running:\n            canvas.after(500, make_ai_move)\n\n# --- \u63cf\u753b\u30fbUI\u3001\u30de\u30a6\u30b9\u64cd\u4f5c ---\n\n# ... (draw_pieces, draw_captured_pieces, flash_king, on_drag, on_click, on_release \u306e\u63cf\u753b\u3068\u30de\u30a6\u30b9\u64cd\u4f5c\u306b\u95a2\u3059\u308b\u95a2\u6570\u306f\u3001\n# \u30b3\u30fc\u30c9\u304c\u9577\u5927\u306b\u306a\u308b\u305f\u3081\u7701\u7565\u3057\u307e\u3059\u304c\u3001\u524d\u56de\u306e\u30b3\u30fc\u30c9\u3068\u307b\u307c\u540c\u3058\u5185\u5bb9\u3067\u3059\u3002\n# \u305f\u3060\u3057\u3001on_click \u3068 on_release \u306b\u306f\u68cb\u8b5c\u8a18\u9332\u306e\u30ed\u30b8\u30c3\u30af\u304c\u8ffd\u52a0\u3055\u308c\u3066\u3044\u307e\u3059\u3002)\n# \u3053\u3053\u3067\u306f\u3001\u68cb\u8b5c\u8a18\u9332\u306e\u8ffd\u52a0\u3055\u308c\u305f on_release \u306e\u307f\u8a18\u8f09\u3057\u307e\u3059\u3002\n\ndef on_release(event):\n    global selected_piece, original_pos, current_player, is_placing_piece, highlight_moves, game_running\n    \n    if not game_running or current_player == AI_PLAYER: return\n\n    if is_placing_piece:\n        canvas.delete(\"drag_piece\")\n        return\n        \n    if selected_piece:\n        new_col = event.x \/\/ CELL_SIZE\n        new_row = event.y \/\/ CELL_SIZE\n        \n        if not (0 &lt;= new_row &lt; 9 and 0 &lt;= new_col &lt; 9) or (new_row, new_col) not in highlight_moves:\n            game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n            \n        elif (new_row, new_col) in highlight_moves:\n            \n            # \u68cb\u8b5c\u8a18\u9332\u7528\u306b\u79fb\u52d5\u524d\u306e\u60c5\u5831\u3092\u4fdd\u5b58\n            board_before_move = copy.deepcopy(game_board)\n            piece_type_before_promotion = selected_piece&#091;1]\n            \n            target_piece = game_board&#091;new_row]&#091;new_col]\n            player = selected_piece&#091;0]\n            \n            if target_piece != EMPTY:\n                captured_piece = target_piece&#091;1]\n                demotion = {'TO': 'FU', 'N-KY': '\u9999', 'N-KE': 'KE', 'N-GI': 'GI', 'RY': 'HI', 'UM': 'KA'}\n                captured_piece = demotion.get(captured_piece, captured_piece)\n\n                capture_list = black_captures if player == BLACK else white_captures\n                capture_list.append((player, captured_piece))\n\n            can_promote_check = should_promote(piece_type_before_promotion, player, original_pos&#091;0], new_row)\n            \n            is_forced_promotion = False\n            if piece_type_before_promotion == 'FU' and ((player == BLACK and new_row == 0) or (player == WHITE and new_row == 8)): is_forced_promotion = True\n            if piece_type_before_promotion == '\u9999' and ((player == BLACK and new_row == 0) or (player == WHITE and new_row == 8)): is_forced_promotion = True\n            if piece_type_before_promotion == 'KE' and ((player == BLACK and new_row &lt;= 1) or (player == WHITE and new_row &gt;= 7)): is_forced_promotion = True\n\n            promote_flag = False\n            if is_forced_promotion:\n                promoted_piece = get_promoted_piece(piece_type_before_promotion)\n                selected_piece = (player, promoted_piece)\n                promote_flag = True\n            \n            elif can_promote_check:\n                result = messagebox.askyesno(\"\u6210\u308a\", \"\u6210\u308a\u307e\u3059\u304b\uff1f (\u300c\u3044\u3044\u3048\u300d\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u6210\u308a\u307e\u305b\u3093\u3002)\")\n                if result:\n                    promoted_piece = get_promoted_piece(piece_type_before_promotion)\n                    selected_piece = (player, promoted_piece)\n                    promote_flag = True\n\n            game_board&#091;new_row]&#091;new_col] = selected_piece\n            \n            # \u2605 \u68cb\u8b5c\u306e\u8a18\u9332 (\u4eba\u9593: \u9ed2\u306f\u5076\u6570\u624b\u3067\u8a18\u9332\u3055\u308c\u308b)\n            move_details = ('move', original_pos&#091;0], original_pos&#091;1], new_row, new_col, promote_flag)\n            turn_count = (len(history) \/\/ 2) + 1 \n            kifu_str = format_move_to_kifu(move_details, player, board_before_move)\n            \n            # \u5947\u6570\u624b (1., 3., 5. ...) \u306e\u958b\u59cb\n            append_kifu(f\"{turn_count}. \u2617{kifu_str}\")\n            # \u2605 --------------------------\n\n            handle_end_turn(WHITE if current_player == BLACK else BLACK)\n\n        selected_piece = None\n        original_pos = None\n        highlight_moves = &#091;]\n\n        canvas.delete(\"drag_piece\")\n        draw_pieces()\n\n# on_click, on_drag, draw_pieces, count_captured_pieces, stop_flashing, flash_king, draw_board_cell \u306e\u5b9a\u7fa9\u3092\u8ffd\u8a18\u3059\u308b\n# (\u3053\u308c\u3089\u306f\u524d\u56de\u306e\u30b3\u30fc\u30c9\u306e\u5185\u5bb9\u3068\u540c\u3058\u3067\u3059)\n# -------------------------------------------------------------------------------------------------------\n\ndef count_captured_pieces(captures_list):\n    piece_types = &#091;piece&#091;1] for piece in captures_list]\n    counts = Counter(piece_types)\n    sorted_counts = {\n        piece_type: counts&#091;piece_type] for piece_type in PIECE_ORDER if piece_type in counts\n    }\n    return sorted_counts\n\ndef stop_flashing():\n    global king_flash_job, is_flashing\n    if king_flash_job:\n        canvas.after_cancel(king_flash_job)\n        king_flash_job = None\n    is_flashing = False\n    \n    king_r, king_c = find_king(current_player, game_board)\n    if king_r is not None:\n        draw_board_cell(king_r, king_c, fill_color=\"#D2B48C\") \n        \ndef draw_board_cell(r, c, fill_color, tags=None):\n    x1 = c * CELL_SIZE\n    y1 = r * CELL_SIZE\n    x2 = x1 + CELL_SIZE\n    y2 = y1 + CELL_SIZE\n    \n    canvas.delete(f\"cell_{r}_{c}\")\n    \n    canvas.create_rectangle(x1, y1, x2, y2, outline=\"black\", fill=fill_color, tags=(f\"cell_{r}_{c}\", tags))\n\ndef flash_king(is_on=True):\n    global king_flash_job, is_flashing\n    \n    if not game_running:\n        stop_flashing()\n        return\n\n    player_in_check = current_player\n    king_r, king_c = find_king(player_in_check, game_board)\n\n    if king_r is not None and is_in_check(player_in_check, game_board):\n        if is_on:\n            draw_board_cell(king_r, king_c, fill_color=\"#FF4C4C\", tags=\"king_flash\")\n        else:\n            draw_board_cell(king_r, king_c, fill_color=\"#D2B48C\", tags=\"king_flash\")\n        \n        king_flash_job = canvas.after(300, flash_king, not is_on)\n        is_flashing = True\n    else:\n        stop_flashing()\n        draw_pieces()\n\ndef draw_pieces():\n    canvas.delete(\"board_piece\")\n    canvas.delete(\"capture_area\")\n    canvas.delete(\"highlight\")\n    \n    for i in range(9):\n        for j in range(9):\n            fill_color = \"#D2B48C\"\n            draw_board_cell(i, j, fill_color)\n            \n    for r, c in highlight_moves:\n        center_x = c * CELL_SIZE + CELL_SIZE \/\/ 2\n        center_y = r * CELL_SIZE + CELL_SIZE \/\/ 2\n        radius = CELL_SIZE \/\/ 3\n        \n        if game_board&#091;r]&#091;c] == EMPTY:\n            canvas.create_oval(center_x - radius, center_y - radius, center_x + radius, center_y + radius, fill=\"#8CBB7D\", width=0, tags=\"highlight\")\n        else:\n            canvas.create_rectangle(c * CELL_SIZE, r * CELL_SIZE, (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE, outline=\"#FF0000\", width=4, tags=\"highlight\")\n\n    for r in range(9):\n        for c in range(9):\n            piece_data = game_board&#091;r]&#091;c]\n            if piece_data != EMPTY:\n                player, piece_type = piece_data\n                text_piece = PIECES&#091;piece_type]\n                x = c * CELL_SIZE + CELL_SIZE \/\/ 2\n                y = r * CELL_SIZE + CELL_SIZE \/\/ 2\n                \n                if selected_piece and original_pos == (r, c):\n                    fill_color = \"yellow\"\n                    canvas.create_rectangle(c * CELL_SIZE, r * CELL_SIZE, (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE, fill=fill_color, outline=\"black\")\n                \n                angle = 180 if player == WHITE else 0\n                canvas.create_text(x, y, text=text_piece, fill=\"black\", font=(\"Arial\", 16), angle=angle, tags=\"board_piece\")\n\n    draw_captured_pieces(WHITE)\n    draw_captured_pieces(BLACK)\n\ndef draw_captured_pieces(player):\n    capture_list = white_captures if player == WHITE else black_captures\n    counted_captures = count_captured_pieces(capture_list)\n    \n    start_x = BOARD_SIZE + 5\n    start_y = 10 if player == WHITE else BOARD_SIZE - CAPTURE_CELL_HEIGHT * (len(counted_captures) + 1)\n    \n    if player == WHITE:\n        canvas.create_text(start_x + (SIDE_PANEL_WIDTH \/\/ 2) - 5, start_y, anchor=\"n\", text=\"\u767d\u306e\u6301\u3061\u99d2\", font=(\"Arial\", 12), tags=\"capture_area\")\n        y_offset = start_y + 20\n    else:\n        canvas.create_text(start_x + (SIDE_PANEL_WIDTH \/\/ 2) - 5, start_y - 20, anchor=\"n\", text=\"\u9ed2\u306e\u6301\u3061\u99d2\", font=(\"Arial\", 12), tags=\"capture_area\")\n        y_offset = start_y\n    \n    piece_index = 0\n    for piece_type, count in counted_captures.items():\n        text_piece = PIECES&#091;piece_type]\n        \n        y1 = y_offset + piece_index * CAPTURE_CELL_HEIGHT\n        y2 = y1 + CAPTURE_CELL_HEIGHT\n        \n        fill_color = \"#E0C8A4\"\n        if is_placing_piece and selected_piece and selected_piece&#091;1] == piece_type:\n            fill_color = \"#FFFF8C\"\n            \n        canvas.create_rectangle(start_x, y1, BOARD_SIZE + SIDE_PANEL_WIDTH - 5, y2, \n                                fill=fill_color, outline=\"black\", tags=(\"capture_area\", f\"{player}_capture_{piece_type}\"))\n        \n        angle = 180 if player == WHITE else 0\n        text_y = y1 + CAPTURE_CELL_HEIGHT \/\/ 2\n        \n        display_text = f\"{text_piece}\"\n        if count &gt; 1: display_text += f\" x {count}\"\n\n        canvas.create_text(start_x + (SIDE_PANEL_WIDTH \/\/ 2) - 5, text_y, anchor=\"center\", \n                           text=display_text, font=(\"Arial\", 14), angle=angle, tags=\"capture_area\")\n        \n        piece_index += 1\n\ndef on_click(event):\n    global selected_piece, original_pos, is_placing_piece, current_player, highlight_moves, game_running\n    \n    if not game_running or current_player == AI_PLAYER: return\n\n    col = event.x \/\/ CELL_SIZE\n    row = event.y \/\/ CELL_SIZE\n    \n    if col &gt;= 9:\n        capture_list = black_captures if current_player == BLACK else white_captures\n        counted_captures = count_captured_pieces(capture_list)\n        if not counted_captures: return\n\n        selected_piece_type = None\n        piece_order = list(counted_captures.keys())\n        click_y = event.y\n        \n        start_y = 10 + 20 \n        if current_player == BLACK:\n            black_capture_y_start = BOARD_SIZE - CAPTURE_CELL_HEIGHT * (len(counted_captures) + 1)\n            start_y = black_capture_y_start \n        \n        y_step = CAPTURE_CELL_HEIGHT\n        \n        if start_y &lt;= click_y &lt; start_y + len(piece_order) * y_step:\n            index = (click_y - start_y) \/\/ y_step\n            if 0 &lt;= index &lt; len(piece_order):\n                selected_piece_type = piece_order&#091;index]\n        \n        if selected_piece_type:\n            if selected_piece and original_pos:\n                game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n                original_pos = None\n\n            temp_piece = (current_player, selected_piece_type)\n            \n            if is_placing_piece and selected_piece == temp_piece:\n                capture_list.append(selected_piece)\n                selected_piece = None\n                is_placing_piece = False\n                highlight_moves = &#091;]\n                draw_pieces()\n                return\n\n            if temp_piece in capture_list:\n                capture_list.remove(temp_piece)\n                selected_piece = temp_piece\n                is_placing_piece = True\n            \n                highlight_moves = &#091;]\n                for r_h in range(9):\n                    for c_h in range(9):\n                        if game_board&#091;r_h]&#091;c_h] == EMPTY:\n                            is_valid_drop = True\n                            \n                            if (selected_piece_type == 'FU' or selected_piece_type == '\u9999') and ((current_player == BLACK and r_h == 0) or (current_player == WHITE and r_h == 8)): is_valid_drop = False\n                            if selected_piece_type == 'KE' and ((current_player == BLACK and r_h &lt;= 1) or (current_player == WHITE and r_h &gt;= 7)): is_valid_drop = False\n                            \n                            if selected_piece_type == 'FU':\n                                for r_check in range(9):\n                                    piece_at_r = game_board&#091;r_check]&#091;c_h]\n                                    if piece_at_r != EMPTY and piece_at_r&#091;0] == current_player and piece_at_r&#091;1] == 'FU':\n                                        is_valid_drop = False\n                                        break\n                            \n                            if selected_piece_type == 'FU' and is_valid_drop:\n                                opponent = WHITE if current_player == BLACK else BLACK\n                                temp_board = &#091;row&#091;:] for row in game_board]\n                                temp_board&#091;r_h]&#091;c_h] = selected_piece\n                                \n                                temp_caps_b = black_captures&#091;:]\n                                temp_caps_w = white_captures&#091;:]\n                                temp_capture_list = temp_caps_b if current_player == BLACK else temp_caps_w\n                                \n                                try:\n                                     temp_capture_list.remove(selected_piece)\n                                except ValueError:\n                                     pass \n                                \n                                if is_in_check(opponent, temp_board) and is_checkmate(opponent, temp_board, temp_caps_b, temp_caps_w):\n                                    is_valid_drop = False\n                            \n                            if is_valid_drop:\n                                temp_board = &#091;row&#091;:] for row in game_board]\n                                temp_board&#091;r_h]&#091;c_h] = selected_piece\n                                if is_in_check(current_player, temp_board):\n                                    is_valid_drop = False\n\n                            if is_valid_drop:\n                                highlight_moves.append((r_h, c_h))\n                        \n                if not highlight_moves and is_placing_piece:\n                    capture_list.append(selected_piece)\n                    selected_piece = None\n                    is_placing_piece = False\n                    messagebox.showinfo(\"\u8b66\u544a\", f\"{PIECES&#091;selected_piece_type]}\u3092\u6253\u3066\u308b\u5408\u6cd5\u306a\u30de\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002\")\n\n            draw_pieces()\n            if selected_piece:\n                angle = 180 if current_player == WHITE else 0\n                canvas.create_text(event.x, event.y, text=PIECES&#091;selected_piece_type], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\", angle=angle)\n            return\n\n        if selected_piece and is_placing_piece:\n            capture_list.append(selected_piece)\n            selected_piece = None\n            is_placing_piece = False\n            highlight_moves = &#091;]\n            draw_pieces()\n            return\n\n    if 0 &lt;= row &lt; 9 and 0 &lt;= col &lt; 9:\n        if is_placing_piece:\n            \n            # \u68cb\u8b5c\u8a18\u9332\u7528\u306b\u79fb\u52d5\u524d\u306e\u60c5\u5831\u3092\u4fdd\u5b58\n            board_before_move = copy.deepcopy(game_board)\n            move_details = ('drop', selected_piece&#091;1], row, col)\n            \n            if (row, col) in highlight_moves:\n                game_board&#091;row]&#091;col] = selected_piece\n                \n                # \u2605 \u68cb\u8b5c\u306e\u8a18\u9332 (\u6253\u3061\u8fbc\u307f)\n                turn_count = (len(history) \/\/ 2) + 1 \n                kifu_str = format_move_to_kifu(move_details, current_player, board_before_move)\n                \n                # \u5947\u6570\u624b (1., 3., 5. ...) \u306e\u958b\u59cb\n                append_kifu(f\"{turn_count}. \u2617{kifu_str}\")\n                # \u2605 --------------------------\n                \n                handle_end_turn(WHITE if current_player == BLACK else BLACK)\n            else:\n                capture_list = black_captures if selected_piece&#091;0] == BLACK else white_captures\n                capture_list.append(selected_piece)\n            \n            is_placing_piece = False\n            selected_piece = None\n            highlight_moves = &#091;]\n            canvas.delete(\"drag_piece\")\n            draw_pieces()\n            return\n            \n        else:\n            piece_data = game_board&#091;row]&#091;col]\n            \n            if selected_piece and original_pos == (row, col):\n                 game_board&#091;row]&#091;col] = selected_piece \n                 selected_piece = None\n                 original_pos = None\n                 highlight_moves = &#091;]\n                 draw_pieces()\n                 return\n                 \n            if piece_data != EMPTY and piece_data&#091;0] == current_player:\n                \n                if selected_piece: game_board&#091;original_pos&#091;0]]&#091;original_pos&#091;1]] = selected_piece\n                \n                highlight_moves = get_valid_moves(row, col, game_board, black_captures if current_player == BLACK else white_captures) \n                \n                selected_piece = piece_data\n                original_pos = (row, col)\n                game_board&#091;row]&#091;col] = EMPTY \n                \n                draw_pieces()\n                \n                angle = 180 if current_player == WHITE else 0\n                canvas.create_text(event.x, event.y, text=PIECES&#091;piece_data&#091;1]], fill=\"red\", font=(\"Arial\", 16), tags=\"drag_piece\", angle=angle)\n\ndef on_drag(event):\n    if selected_piece and game_running and current_player != AI_PLAYER:\n        canvas.coords(\"drag_piece\", event.x, event.y)\n\n# -------------------------------------------------------------------------------------------------------\n\ndef create_shogi_board():\n    global game_board, canvas, root, kifu_text # kifu_text\u3092\u8ffd\u52a0\n    \n    root = tk.Tk()\n    root.title(f\"\u5c06\u68cb\u30b2\u30fc\u30e0 (AI\u6df1\u3055: {SEARCH_DEPTH})\")\n\n    canvas = tk.Canvas(root, width=BOARD_SIZE + SIDE_PANEL_WIDTH, height=BOARD_SIZE, bg=\"#D2B48C\")\n    canvas.pack(side=tk.LEFT)\n    \n    control_frame = tk.Frame(root, width=SIDE_PANEL_WIDTH)\n    control_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=10, pady=10)\n    \n    undo_button = tk.Button(control_frame, text=\"\u4e00\u624b\u623b\u308b (Undo)\", command=undo_move, \n                            height=2, bg=\"#B0C4DE\", fg=\"black\")\n    undo_button.pack(pady=5)\n    \n    tk.Label(control_frame, text=f\"AI\u63a2\u7d22\u6df1\u3055: {SEARCH_DEPTH}\").pack(pady=5)\n    \n    # \u2605 \u68cb\u8b5c\u8868\u793a\u30a8\u30ea\u30a2\u306e\u8ffd\u52a0\n    tk.Label(control_frame, text=\"--- \u68cb\u8b5c ---\").pack(pady=(10, 0))\n    kifu_text = tk.Text(control_frame, height=20, width=20, wrap=tk.WORD, state=tk.DISABLED, font=(\"Arial\", 10))\n    kifu_text.pack(fill=tk.Y)\n    # \u2605 --------------------------\n    \n    canvas.bind(\"&lt;Button-1&gt;\", on_click)\n    canvas.bind(\"&lt;B1-Motion&gt;\", on_drag)\n    canvas.bind(\"&lt;ButtonRelease-1&gt;\", on_release)\n            \n    game_board = create_initial_board()\n    \n    game_states.append(get_simple_state_string(game_board, BLACK))\n    save_state()\n\n    draw_pieces()\n\n    def on_closing():\n        stop_flashing() \n        root.destroy()\n        sys.exit()\n        \n    root.protocol(\"WM_DELETE_WINDOW\", on_closing)\n\n    root.mainloop()\n\nif __name__ == \"__main__\":\n    create_shogi_board()<\/code><\/pre>\n<\/details>\n\n\n\n<p>\u3057\u3066\u3001\u3053\u306e\u30d7\u30ed\u30f3\u30d7\u30c8 No.3\u307e\u3067\u3067\u3001AI\u306f\u300c\u99d2\u306e\u57fa\u672c\u4fa1\u5024\u300d\u300c\u99d2\u306e\u4f4d\u7f6e\uff08PST\uff09\u300d\u300c\u53cd\u5247\u30c1\u30a7\u30c3\u30af\u300d\u300c \u7389\u306e\u5805\u3055 \u300d\u306e4\u3064\u306e\u8981\u7d20\u3092\u8003\u616e\u3057\u3066\u6307\u3057\u624b\u3092\u9078\u3076\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f \u3002\u3057\u304b\u3057\u3001AI\u306f\u3055\u3089\u306b\u5f37\u5316\u304c\u53ef\u80fd\u3067\u3059\u3002\u4f8b\u3048\u3070\u3001\u63a2\u7d22\u6df1\u3055\u30923\u30844\u306b\u5897\u3084\u3057\u305f\u308a \u3001\u738b\u624b\u3084\u99d2\u306e\u53d6\u308a\u5408\u3044\u304c\u767a\u751f\u3057\u3066\u3044\u308b\u5c40\u9762\u3067\u63a2\u7d22\u3092\u6df1\u304f\u3059\u308b\u9759\u7684\u63a2\u7d22\u306e\u5c0e\u5165 \u3001\u5927\u5c40\u7684\u306a\u6226\u578b\u8a55\u4fa1\u306e\u8ffd\u52a0 \u3068\u3044\u3063\u305f\u30b9\u30c6\u30c3\u30d7\u304c\u8003\u3048\u3089\u308c\u307e\u3059 \u3002\u8aad\u8005\u306e\u7686\u3055\u3093\u306e\u597d\u5947\u5fc3\u306b\u5408\u308f\u305b\u3066\u3001\u305c\u3072\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u306b\u6311\u6226\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-b6b09c4351bfeddbea547f9641fcc3da is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no4(<strong><strong>GUI\u8a2d\u5b9a<\/strong><\/strong>)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>#Version 8.0\nimport tkinter as tk\nfrom collections import Counter\nfrom tkinter import messagebox\nimport sys\nimport copy\n\n# ==============================================================================\n# 1. \u5b9a\u6570 (\u5909\u66f4\u306a\u3057)\n# ==============================================================================\nBOARD_SIZE = 450\nCELL_SIZE = BOARD_SIZE \/\/ 9\nSIDE_PANEL_WIDTH = 150\nCAPTURE_CELL_HEIGHT = 25 \n\nEMPTY = ' '\nBLACK = '\u9ed2'\nWHITE = '\u767d'\n\nPIECES = {\n    'OU': '\u7389', 'HI': '\u98db', 'KA': '\u89d2', 'KI': '\u91d1',\n    'GI': '\u9280', 'KE': '\u6842', '\u9999': '\u9999', 'FU': '\u6b69',\n    'TO': '\u3068', 'N-GI': '\u6210\u9280', 'N-KE': '\u6210\u6842', 'N-KY': '\u6210\u9999',\n    'RY': '\u9f8d', 'UM': '\u99ac'\n}\n\nPIECE_ORDER = &#091;'HI', 'KA', 'RY', 'UM', 'KI', 'GI', 'KE', '\u9999', 'FU'] \nAI_PLAYER = WHITE\nSEARCH_DEPTH = 2 \n\nKANJI_COLUMNS = &#091;\"\uff19\", \"\uff18\", \"\uff17\", \"\uff16\", \"\uff15\", \"\uff14\", \"\uff13\", \"\uff12\", \"\uff11\"]\nKANJI_ROWS = &#091;\"\u4e00\", \"\u4e8c\", \"\u4e09\", \"\u56db\", \"\u4e94\", \"\u516d\", \"\u4e03\", \"\u516b\", \"\u4e5d\"]\n\n# \u99d2\u306e\u57fa\u672c\u4fa1\u5024 (\u5909\u66f4\u306a\u3057)\nPIECE_VALUES = {\n    'OU': 10000, \n    'HI': 1000, 'KA': 800, \n    'KI': 500, 'GI': 400, \n    'KE': 300, '\u9999': 200, 'FU': 100,\n    'RY': 1300, 'UM': 1000, \n    'TO': 600, 'N-GI': 500, 'N-KE': 400, 'N-KY': 300\n}\n\n# Piece-Square Tables (PST) (\u5909\u66f4\u306a\u3057)\nPST_HI = &#091;\n    &#091; 0,  5, 10, 15, 15, 15, 10,  5,  0], &#091; 5, 10, 15, 20, 20, 20, 15, 10,  5],\n    &#091;10, 15, 20, 25, 25, 25, 20, 15, 10], &#091;15, 20, 25, 30, 30, 30, 25, 20, 15],\n    &#091;15, 20, 25, 30, 30, 30, 25, 20, 15], &#091;10, 15, 20, 25, 25, 25, 20, 15,  5],\n    &#091; 5, 10, 15, 20, 20, 20, 15, 10,  5], &#091; 0,  5, 10, 15, 15, 15, 10,  5,  0],\n    &#091;-5,  0,  5, 10, 10, 10,  5,  0, -5]\n]\nPST_KA = &#091;\n    &#091; 0,  0,  5, 10, 10, 10,  5,  0,  0], &#091; 0, 10, 15, 20, 20, 20, 15, 10,  0],\n    &#091; 5, 15, 25, 30, 30, 30, 25, 15,  5], &#091;10, 20, 30, 35, 35, 35, 30, 20, 10],\n    &#091;10, 20, 30, 35, 35, 35, 30, 20, 10], &#091; 5, 15, 25, 30, 30, 30, 25, 15,  5],\n    &#091; 0, 10, 15, 20, 20, 20, 15, 10,  0], &#091; 0,  0,  5, 10, 10, 10,  5,  0,  0],\n    &#091;-5, -5,  0,  5,  5,  5,  0, -5, -5]\n]\nPST_FU = &#091;\n    &#091; 40, 40, 40, 40, 40, 40, 40, 40, 40], &#091; 30, 30, 30, 30, 30, 30, 30, 30, 30],\n    &#091; 20, 20, 20, 20, 20, 20, 20, 20, 20], &#091; 10, 10, 10, 10, 10, 10, 10, 10, 10],\n    &#091;  5,  5,  5,  5,  5,  5,  5,  5,  5], &#091;  0,  0,  0,  0,  0,  0,  0,  0,  0],\n    &#091; -5, -5, -5, -5, -5, -5, -5, -5, -5], &#091;-10,-10,-10,-10,-10,-10,-10,-10,-10],\n    &#091;-20,-20,-20,-20,-20,-20,-20,-20,-20]\n]\nPST_KE = &#091;\n    &#091; 10, 15, 20, 20, 20, 20, 20, 15, 10], &#091; 10, 15, 20, 20, 20, 20, 20, 15, 10],\n    &#091;  5, 10, 15, 15, 15, 15, 15, 10,  5], &#091;  0,  5, 10, 10, 10, 10, 10,  5,  0],\n    &#091; -5,  0,  5,  5,  5,  5,  5,  0, -5], &#091;-10, -5,  0,  0,  0,  0,  0, -5,-10],\n    &#091;-15,-10, -5, -5, -5, -5, -5,-10,-15], &#091;-20,-15,-10,-10,-10,-10,-10,-15,-20],\n    &#091;-20,-15,-10,-10,-10,-10,-10,-15,-20]\n]\n\n\n# ==============================================================================\n# 2. \u9759\u7684\/\u30d8\u30eb\u30d1\u30fc\u95a2\u6570 (\u5909\u66f4\u306a\u3057)\n# ==============================================================================\ndef is_promoted_piece(piece_type):\n    return piece_type in &#091;'TO', 'N-KY', 'N-KE', 'N-GI', 'RY', 'UM']\n\ndef get_promoted_piece(piece_type):\n    promotions = {'FU': 'TO', '\u9999': 'N-KY', 'KE': 'N-KE', 'GI': 'N-GI', 'HI': 'RY', 'KA': 'UM'}\n    return promotions.get(piece_type, piece_type)\n\ndef get_demoted_piece(piece_type):\n    demotions = {'TO': 'FU', 'N-KY': '\u9999', 'N-KE': 'KE', 'N-GI': 'GI', 'RY': 'HI', 'UM': 'KA'}\n    return demotions.get(piece_type, piece_type)\n\ndef should_promote(piece_type, player, start_row, end_row):\n    if piece_type in &#091;'OU', 'KI'] or is_promoted_piece(piece_type): return False\n    if player == BLACK: \n        return end_row &lt;= 2 or start_row &lt;= 2\n    else: \n        return end_row &gt;= 6 or start_row &gt;= 6\n        \ndef coords_to_kifu(r, c):\n    return KANJI_COLUMNS&#091;c] + KANJI_ROWS&#091;r]\n\ndef piece_type_to_kifu(piece_type):\n    return PIECES.get(piece_type, piece_type)\n\ndef format_move_to_kifu_static(move_details, current_player, board_before_move):\n    move_type = move_details&#091;0]\n    \n    if move_type == 'move':\n        _, start_r, start_c, end_r, end_c, promote = move_details\n        piece_data = board_before_move&#091;start_r]&#091;start_c]\n        if piece_data == EMPTY: return \"\"\n        piece_type = piece_data&#091;1] \n        kifu_piece = piece_type_to_kifu(piece_type)\n        kifu_end_pos = coords_to_kifu(end_r, end_c)\n        kifu_promote = \"\u6210\" if promote else \"\"\n        return f\"{kifu_end_pos}{kifu_piece}{kifu_promote}\"\n\n    elif move_type == 'drop':\n        _, piece_type, end_r, end_c = move_details\n        kifu_piece = piece_type_to_kifu(piece_type)\n        kifu_end_pos = coords_to_kifu(end_r, end_c)\n        return f\"{kifu_end_pos}{kifu_piece}\"\n            \n    return \"\"\n\ndef get_simple_state_string_static(board, captures_b, captures_w, player):\n    # \u76e4\u9762\u3001\u6301\u3061\u99d2\uff08\u30bd\u30fc\u30c8\uff09\u3001\u624b\u756a\u3092\u542b\u3080\u30cf\u30c3\u30b7\u30e5\u30ad\u30fc\n    state_str = \"\".join(\"E\" if cell == EMPTY else cell&#091;0] + cell&#091;1] for row in board for cell in row)\n    b_caps_str = \"\".join(sorted(&#091;t for p, t in captures_b]))\n    w_caps_str = \"\".join(sorted(&#091;t for p, t in captures_w]))\n    state_str += f\"B{b_caps_str}W{w_caps_str}\"\n    state_str += \"T\" + player\n    return state_str\n\ndef count_captured_pieces(captures_list):\n    piece_types = &#091;piece&#091;1] for piece in captures_list]\n    counts = Counter(piece_types)\n    sorted_counts = {\n        piece_type: counts&#091;piece_type] for piece_type in PIECE_ORDER if piece_type in counts\n    }\n    return sorted_counts\n\n# \u99d2\u306e\u79fb\u52d5\u30ed\u30b8\u30c3\u30af (\u5909\u66f4\u306a\u3057)\ndef is_valid_pawn_move_static(start_row, start_col, end_row, end_col, player):\n    if player == BLACK: return end_row == start_row - 1 and end_col == start_col\n    elif player == WHITE: return end_row == start_row + 1 and end_col == start_col\n    return False\n\ndef is_valid_lance_move_static(start_row, start_col, end_row, end_col, player, board):\n    if end_col != start_col: return False\n    if player == BLACK and end_row &gt;= start_row: return False\n    if player == WHITE and end_row &lt;= start_row: return False\n    step = -1 if player == BLACK else 1\n    for r in range(start_row + step, end_row, step):\n        if board&#091;r]&#091;start_col] != EMPTY: return False\n    return True \n\ndef is_valid_king_move_static(start_row, start_col, end_row, end_col):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    return dx &lt;= 1 and dy &lt;= 1\n\ndef is_valid_rook_move_static(start_row, start_col, end_row, end_col, board):\n    if start_row == end_row:\n        step = 1 if end_col &gt; start_col else -1\n        for c in range(start_col + step, end_col, step):\n            if board&#091;start_row]&#091;c] != EMPTY: return False\n    elif start_col == end_col:\n        step = 1 if end_row &gt; start_row else -1\n        for r in range(start_row + step, end_row, step):\n            if board&#091;r]&#091;start_col] != EMPTY: return False\n    else: return False\n    return True\n\ndef is_valid_bishop_move_static(start_row, start_col, end_row, end_col, board):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != dy or dx == 0: return False\n    step_x = 1 if end_col &gt; start_col else -1\n    step_y = 1 if end_row &gt; start_row else -1\n    for i in range(1, dx):\n        if board&#091;start_row + i * step_y]&#091;start_col + i * step_x] != EMPTY: return False\n    return True\n\ndef is_valid_gold_move_static(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 0: return True\n        if dy == 0 and dx == 1: return True\n        if dy == 1 and dx == 1 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_silver_move_static(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if player == BLACK:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &gt; end_row: return True\n    elif player == WHITE:\n        if dy == 1 and dx == 1: return True\n        if dy == 1 and dx == 0 and start_row &lt; end_row: return True\n    return False\n\ndef is_valid_knight_move_static(start_row, start_col, end_row, end_col, player):\n    dx = abs(start_col - end_col)\n    dy = abs(start_row - end_row)\n    if dx != 1 or dy != 2: return False\n    if player == BLACK: return end_row == start_row - 2\n    elif player == WHITE: return end_row == start_row + 2\n    return False\n\ndef is_valid_move_logic_static(start_row, start_col, end_row, end_col, piece_type, player, board):\n    if piece_type == 'FU': return is_valid_pawn_move_static(start_row, start_col, end_row, end_col, player)\n    elif piece_type == '\u9999': return is_valid_lance_move_static(start_row, start_col, end_row, end_col, player, board)\n    elif piece_type == 'OU': return is_valid_king_move_static(start_row, start_col, end_row, end_col)\n    elif piece_type == 'HI': return is_valid_rook_move_static(start_row, start_col, end_row, end_col, board)\n    elif piece_type == 'KA': return is_valid_bishop_move_static(start_row, start_col, end_row, end_col, board)\n    elif piece_type == 'KI': return is_valid_gold_move_static(start_row, start_col, end_row, end_col, player)\n    elif piece_type == 'GI': return is_valid_silver_move_static(start_row, start_col, end_row, end_col, player)\n    elif piece_type == 'KE': return is_valid_knight_move_static(start_row, start_col, end_row, end_col, player)\n    elif piece_type == 'RY': return is_valid_rook_move_static(start_row, start_col, end_row, end_col, board) or is_valid_king_move_static(start_row, start_col, end_row, end_col)\n    elif piece_type == 'UM': return is_valid_bishop_move_static(start_row, start_col, end_row, end_col, board) or is_valid_king_move_static(start_row, start_col, end_row, end_col)\n    elif piece_type in &#091;'TO', 'N-GI', 'N-KE', 'N-KY']: return is_valid_gold_move_static(start_row, start_col, end_row, end_col, player)\n    return False\n\n\n# ==============================================================================\n# 3. Model: ShogiGame \u30af\u30e9\u30b9 \n# ==============================================================================\n\nclass ShogiGame:\n    def __init__(self):\n        self.board = self._create_initial_board()\n        self.black_captures = &#091;]\n        self.white_captures = &#091;]\n        self.current_player = BLACK\n        self.game_states = &#091;] \n        self.history = &#091;] \n\n    def _create_initial_board(self):\n        board = &#091;&#091;EMPTY] * 9 for _ in range(9)]\n        board&#091;0]&#091;0] = (WHITE, '\u9999'); board&#091;0]&#091;1] = (WHITE, 'KE'); board&#091;0]&#091;2] = (WHITE, 'GI'); board&#091;0]&#091;3] = (WHITE, 'KI'); board&#091;0]&#091;4] = (WHITE, 'OU'); board&#091;0]&#091;5] = (WHITE, 'KI'); board&#091;0]&#091;6] = (WHITE, 'GI'); board&#091;0]&#091;7] = (WHITE, 'KE'); board&#091;0]&#091;8] = (WHITE, '\u9999')\n        board&#091;1]&#091;1] = (WHITE, 'HI'); board&#091;1]&#091;7] = (WHITE, 'KA') \n        for j in range(9): board&#091;2]&#091;j] = (WHITE, 'FU')\n        board&#091;8]&#091;0] = (BLACK, '\u9999'); board&#091;8]&#091;1] = (BLACK, 'KE'); board&#091;8]&#091;2] = (BLACK, 'GI'); board&#091;8]&#091;3] = (BLACK, 'KI'); board&#091;8]&#091;4] = (BLACK, 'OU'); board&#091;8]&#091;5] = (BLACK, 'KI'); board&#091;8]&#091;6] = (BLACK, 'GI'); board&#091;8]&#091;7] = (BLACK, 'KE'); board&#091;8]&#091;8] = (BLACK, '\u9999')\n        board&#091;7]&#091;7] = (BLACK, 'HI'); board&#091;7]&#091;1] = (BLACK, 'KA')\n        for j in range(9): board&#091;6]&#091;j] = (BLACK, 'FU')\n        return board\n    \n    def find_king(self, player, board_state):\n        for r in range(9):\n            for c in range(9):\n                piece_data = board_state&#091;r]&#091;c]\n                if piece_data != EMPTY and piece_data&#091;0] == player and piece_data&#091;1] == 'OU':\n                    return r, c\n        return None, None\n        \n    def is_in_check(self, player, board_state):\n        king_row, king_col = self.find_king(player, board_state)\n        if king_row is None: return False \n        opponent = WHITE if player == BLACK else BLACK\n        for r in range(9):\n            for c in range(9):\n                piece_data = board_state&#091;r]&#091;c]\n                if piece_data != EMPTY and piece_data&#091;0] == opponent:\n                    piece_type = piece_data&#091;1]\n                    if is_valid_move_logic_static(r, c, king_row, king_col, piece_type, opponent, board_state):\n                        return True\n        return False\n    \n    def is_check(self, board, player):\n        \"\"\"\u6307\u5b9a\u30d7\u30ec\u30a4\u30e4\u30fc\u304c\u76f8\u624b\u306b\u738b\u624b\u3092\u304b\u3051\u3066\u3044\u308b\u304b\u5224\u5b9a (\u9759\u7684\u63a2\u7d22\u7528\u30d8\u30eb\u30d1\u30fc)\"\"\"\n        opponent = WHITE if player == BLACK else BLACK\n        k_r, k_c = self.find_king(opponent, board)\n        if k_r is None: return False\n        \n        for r in range(9):\n            for c in range(9):\n                piece_data = board&#091;r]&#091;c]\n                if piece_data != EMPTY and piece_data&#091;0] == player:\n                    piece_type = piece_data&#091;1]\n                    if is_valid_move_logic_static(r, c, k_r, k_c, piece_type, player, board):\n                        return True\n        return False\n        \n    def get_valid_moves(self, r, c, board, player):\n        if board&#091;r]&#091;c] == EMPTY: return &#091;]\n        player, piece_type = board&#091;r]&#091;c]\n        valid_moves = &#091;]\n        \n        for end_r in range(9):\n            for end_c in range(9):\n                if r == end_r and c == end_c: continue\n                target_piece = board&#091;end_r]&#091;end_c]\n                if target_piece != EMPTY and target_piece&#091;0] == player: continue\n\n                if not is_valid_move_logic_static(r, c, end_r, end_c, piece_type, player, board): continue\n                \n                temp_board = &#091;row&#091;:] for row in board]\n                captured_piece_temp = temp_board&#091;end_r]&#091;end_c]\n                new_piece_type = piece_type\n                \n                temp_board&#091;end_r]&#091;end_c] = (player, new_piece_type)\n                temp_board&#091;r]&#091;c] = EMPTY\n                \n                # \u79fb\u52d5\u5f8c\u306e\u81ea\u7389\u306e\u738b\u624b\u30c1\u30a7\u30c3\u30af\n                if not self.is_in_check(player, temp_board):\n                    valid_moves.append((end_r, end_c))\n\n        return valid_moves\n        \n    def get_all_legal_moves(self, player, board, black_captures_in, white_captures_in):\n        legal_moves = &#091;]\n        \n        # 1. \u76e4\u4e0a\u306e\u99d2\u306e\u79fb\u52d5\n        for r in range(9):\n            for c in range(9):\n                piece_data = board&#091;r]&#091;c]\n                if piece_data != EMPTY and piece_data&#091;0] == player:\n                    piece_type = piece_data&#091;1]\n                    moves = self.get_valid_moves(r, c, board, player)\n                    for end_r, end_c in moves:\n                        can_promote = should_promote(piece_type, player, r, end_r) and not is_promoted_piece(piece_type)\n                        is_forced = (\n                            (piece_type in &#091;'FU', '\u9999'] and ((player == BLACK and end_r == 0) or (player == WHITE and end_r == 8))) or\n                            (piece_type == 'KE' and ((player == BLACK and end_r &lt;= 1) or (player == WHITE and end_r &gt;= 7)))\n                        )\n                        \n                        if is_forced or not can_promote:\n                            legal_moves.append(('move', r, c, end_r, end_c, is_forced))\n                        elif can_promote:\n                            legal_moves.append(('move', r, c, end_r, end_c, True))\n                            if not is_forced:\n                                legal_moves.append(('move', r, c, end_r, end_c, False))\n        \n        # 2. \u6301\u3061\u99d2\u306e\u6253\u3061\u8fbc\u307f\n        captures_list = black_captures_in if player == BLACK else white_captures_in\n        piece_counts = count_captured_pieces(captures_list)\n        opponent = WHITE if player == BLACK else BLACK\n        \n        for piece_type in piece_counts.keys():\n            if piece_counts&#091;piece_type] == 0: continue\n            if is_promoted_piece(piece_type) or piece_type == 'OU': continue \n            \n            for r in range(9):\n                for c in range(9):\n                    if board&#091;r]&#091;c] == EMPTY:\n                        \n                        # \u884c\u304d\u6240\u306e\u306a\u3044\u99d2\u306e\u6253\u3061\u8fbc\u307f\u7981\u6b62\n                        if piece_type == 'FU' and ((player == BLACK and r == 0) or (player == WHITE and r == 8)): continue\n                        if piece_type == '\u9999' and ((player == BLACK and r == 0) or (player == WHITE and r == 8)): continue\n                        if piece_type == 'KE' and ((player == BLACK and r &lt;= 1) or (player == WHITE and r &gt;= 7)): continue\n                        \n                        # \u4e8c\u6b69\u30c1\u30a7\u30c3\u30af\n                        if piece_type == 'FU':\n                            pawn_in_col = False\n                            for row in range(9):\n                                cell = board&#091;row]&#091;c]\n                                if cell != EMPTY and cell&#091;0] == player and cell&#091;1] == 'FU':\n                                    pawn_in_col = True\n                                    break\n                            if pawn_in_col: continue\n\n                        # \u6253\u3061\u99d2\u306b\u3088\u308b\u738b\u624b\u30fb\u8a70\u307f\u30c1\u30a7\u30c3\u30af \n                        temp_board = &#091;row&#091;:] for row in board]\n                        temp_board&#091;r]&#091;c] = (player, piece_type)\n                        \n                        # 1. \u81ea\u7389\u304c\u738b\u624b\u306b\u306a\u308b\u624b\u306f\u975e\u5408\u6cd5 \n                        if self.is_in_check(player, temp_board):\n                            continue \n\n                        # 2. \u76f8\u624b\u7389\u306b\u738b\u624b\u304c\u304b\u304b\u308b\u304b\u30c1\u30a7\u30c3\u30af\n                        if self.is_in_check(opponent, temp_board):\n                            \n                            # 2-a. \u305d\u308c\u304c\u6b69\u306b\u3088\u308b\u738b\u624b\u304b\uff1f (\u6253\u3061\u6b69\u8a70\u3081\u30c1\u30a7\u30c3\u30af)\n                            if piece_type == 'FU':\n                                \n                                # \u5b9f\u969b\u306e\u624b\u3092\u9069\u7528\u3057\u3066\u3001\u76f8\u624b\u304c\u8a70\u3093\u3067\u3044\u308b\u304b\u78ba\u8a8d\u3059\u308b\n                                new_board_after_drop, new_caps_b, new_caps_w = self.apply_move(board, black_captures_in, white_captures_in, ('drop', piece_type, r, c), player)\n                                \n                                # \u8a70\u307f\u3067\u3042\u308c\u3070\u3001\u6253\u3061\u6b69\u8a70\u3081\u3068\u3057\u3066\u9664\u5916 (continue)\n                                if self.is_checkmate(opponent, new_board_after_drop, new_caps_b, new_caps_w):\n                                    continue\n                                \n                            # 2-b. \u6253\u3061\u6b69\u8a70\u3081\u3067\u306f\u306a\u3044\u3001\u307e\u305f\u306f\u6b69\u4ee5\u5916\u306e\u99d2\u3067\u306e\u738b\u624b\u306f\u5408\u6cd5\u624b\n                        \n                        # 3. 2-a\u3067continue\u3055\u308c\u306a\u304b\u3063\u305f\u5834\u5408\u3001\u5408\u6cd5\u624b\u3068\u3057\u3066\u8ffd\u52a0\n                        legal_moves.append(('drop', piece_type, r, c))\n                            \n        return legal_moves\n\n    def get_tactical_moves(self, player, board, captures_b, captures_w):\n        \"\"\"\u99d2\u53d6\u308a\u307e\u305f\u306f\u738b\u624b\u306b\u306a\u308b\u624b\u3092\u62bd\u51fa\u3059\u308b (\u9759\u7684\u63a2\u7d22\u7528)\"\"\"\n        all_legal_moves = self.get_all_legal_moves(player, board, captures_b, captures_w)\n        tactical_moves = &#091;]\n        \n        for move in all_legal_moves:\n            \n            # 1. \u99d2\u53d6\u308a\u306b\u306a\u308b\u624b\n            is_capture = False\n            if move&#091;0] == 'move':\n                _, _, _, end_r, end_c, _ = move\n                if board&#091;end_r]&#091;end_c] != EMPTY:\n                    is_capture = True\n                    \n            # 2. \u738b\u624b\u3001\u6210\u308a\u3001\u6253\u3061\n            is_check_or_promote = False\n            new_board, _, _ = self.apply_move(board, captures_b, captures_w, move, player)\n            if self.is_check(new_board, player):\n                 is_check_or_promote = True\n            \n            if move&#091;0] == 'move':\n                _, _, _, _, _, promote = move\n                if promote: is_check_or_promote = True\n            if move&#091;0] == 'drop':\n                is_check_or_promote = True\n\n            if is_capture or is_check_or_promote:\n                tactical_moves.append(move)\n\n        return tactical_moves\n\n    def is_checkmate(self, player, board, black_captures_in, white_captures_in):\n        if not self.is_in_check(player, board):\n            return False\n        # \u8a70\u307f\u5224\u5b9a\u306f\u3001\u305d\u306e\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u6b21\u306e\u5408\u6cd5\u624b\u304c\u5b58\u5728\u3057\u306a\u3044\u3053\u3068\n        legal_moves = self.get_all_legal_moves(player, board, black_captures_in, white_captures_in)\n        return len(legal_moves) == 0\n\n    def apply_move(self, board, captures_black, captures_white, move, player):\n        new_board = &#091;row&#091;:] for row in board]\n        new_caps_b = captures_black&#091;:]\n        new_caps_w = captures_white&#091;:]\n        capture_list_player = new_caps_b if player == BLACK else new_caps_w\n        \n        move_type = move&#091;0]\n        if move_type == 'move':\n            _, start_r, start_c, end_r, end_c, promote = move\n            piece_data = new_board&#091;start_r]&#091;start_c]\n            piece_type = piece_data&#091;1]\n            target_piece = new_board&#091;end_r]&#091;end_c]\n            \n            if target_piece != EMPTY:\n                captured_piece = get_demoted_piece(target_piece&#091;1])\n                capture_list_player.append((player, captured_piece))\n                \n            if promote: piece_type = get_promoted_piece(piece_type)\n            new_board&#091;end_r]&#091;end_c] = (player, piece_type)\n            new_board&#091;start_r]&#091;start_c] = EMPTY\n            \n        elif move_type == 'drop':\n            _, piece_type, end_r, end_c = move\n            \n            temp_list = &#091;]\n            removed = False\n            \n            target_list = new_caps_b if player == BLACK else new_caps_w\n            \n            # \u6301\u3061\u99d2\u304b\u3089\u4e00\u3064\u524a\u9664\n            for p, t in target_list:\n                if t == piece_type and not removed:\n                    removed = True\n                else:\n                    temp_list.append((p, t))\n            \n            if player == BLACK: \n                new_caps_b = temp_list\n            else: \n                new_caps_w = temp_list\n            \n            new_board&#091;end_r]&#091;end_c] = (player, piece_type)\n            \n        return new_board, new_caps_b, new_caps_w\n\n    # --- King Safety\u8a55\u4fa1\u30d8\u30eb\u30d1\u30fc\u95a2\u6570 (\u5909\u66f4\u306a\u3057) ---\n\n    def calculate_defender_score(self, kr, kc, player, board):\n        \"\"\"\u7389\u306e\u5468\u56f21\u30de\u30b9\u306b\u3044\u308b\u81ea\u99d2\u306e\u5b88\u308a\u8a55\u4fa1\u3092\u8a08\u7b97\u3059\u308b\"\"\"\n        score = 0\n        for dr in &#091;-1, 0, 1]:\n            for dc in &#091;-1, 0, 1]:\n                if dr == 0 and dc == 0: continue\n                r, c = kr + dr, kc + dc\n                \n                if 0 &lt;= r &lt; 9 and 0 &lt;= c &lt; 9:\n                    piece_data = board&#091;r]&#091;c]\n                    if piece_data != EMPTY and piece_data&#091;0] == player:\n                        piece_type = piece_data&#091;1]\n                        if piece_type in &#091;'KI', 'GI', 'TO', 'N-GI', 'UM', 'RY']:\n                            score += 80 \n                        elif piece_type in &#091;'KE', '\u9999', 'FU']:\n                            score += 30 \n                            \n        return score\n\n    def calculate_proximity_penalty(self, kr, kc, opponent, board):\n        \"\"\"\u6575\u99d2\u304c\u7389\u306e\u5468\u56f23\u30de\u30b9\u306b\u63a5\u8fd1\u3057\u3066\u3044\u308b\u3053\u3068\u306b\u3088\u308b\u30da\u30ca\u30eb\u30c6\u30a3\u3092\u8a08\u7b97\u3059\u308b\"\"\"\n        penalty = 0\n        for dr in range(-3, 4):\n            for dc in range(-3, 4):\n                if dr == 0 and dc == 0: continue\n                r, c = kr + dr, kc + dc\n                \n                if 0 &lt;= r &lt; 9 and 0 &lt;= c &lt; 9:\n                    piece_data = board&#091;r]&#091;c]\n                    \n                    if piece_data != EMPTY and piece_data&#091;0] == opponent:\n                        piece_type = piece_data&#091;1]\n                        distance = max(abs(dr), abs(dc)) \n                        \n                        base_penalty = PIECE_VALUES.get(piece_type, 100) \/ (distance + 0.5) \n                        \n                        if piece_type in &#091;'RY', 'UM', 'HI', 'KA']:\n                             base_penalty *= 1.5\n                        \n                        penalty += base_penalty\n                        \n        return int(penalty) \n\n    def evaluate_board(self, board, captures_black, captures_white, player):\n        score = 0\n        opponent = WHITE if player == BLACK else BLACK\n        \n        # 1. \u99d2\u306e\u57fa\u672c\u4fa1\u5024\u3068\u4f4d\u7f6e\u306b\u3088\u308b\u8a55\u4fa1 (PST)\n        for r in range(9):\n            for c in range(9):\n                piece_data = board&#091;r]&#091;c]\n                if piece_data != EMPTY:\n                    p, t = piece_data\n                    value = PIECE_VALUES.get(t, 0)\n                    pst_score = 0\n                    \n                    if t == 'HI': pst_table = PST_HI\n                    elif t == 'KA': pst_table = PST_KA\n                    elif t == 'FU': pst_table = PST_FU\n                    elif t == 'KE': pst_table = PST_KE\n                    else: pst_table = None\n                        \n                    if pst_table:\n                        if p == BLACK:\n                            pst_score = pst_table&#091;r]&#091;c]\n                        else: \n                            pst_score = pst_table&#091;8 - r]&#091;c] \n                    \n                    total_value = value + pst_score\n                    score += total_value if p == player else -total_value\n\n        # 2. \u6301\u3061\u99d2\u306e\u4fa1\u5024\u8a55\u4fa1\n        for _, t in captures_black:\n            score += PIECE_VALUES.get(t, 0) if BLACK == player else -PIECE_VALUES.get(t, 0)\n        for _, t in captures_white:\n            score += PIECE_VALUES.get(t, 0) if WHITE == player else -PIECE_VALUES.get(t, 0)\n            \n        # 3. \u7389\u306e\u5805\u3055\u306e\u8a55\u4fa1 (King Safety)\n        king_row, king_col = self.find_king(player, board)\n        if king_row is not None:\n            \n            defender_score = self.calculate_defender_score(king_row, king_col, player, board)\n            score += defender_score \n\n            proximity_penalty = self.calculate_proximity_penalty(king_row, king_col, opponent, board)\n            score -= proximity_penalty \n            \n            # \u521d\u671f\u4f4d\u7f6e\u30da\u30ca\u30eb\u30c6\u30a3 (\u30b2\u30fc\u30e0\u5e8f\u76e4\u306e\u307f\u6709\u52b9)\n            if (player == BLACK and king_row == 8 and king_col == 4) or (player == WHITE and king_row == 0 and king_col == 4):\n                score -= 50 \n        \n        # 4. \u738b\u624b\/\u8a70\u307f\u8a55\u4fa1\n        if self.is_in_check(player, board):\n            score -= 500 \n        if self.is_in_check(opponent, board):\n            score += 500 \n        # \u8a70\u307f\u306f\u975e\u5e38\u306b\u5927\u304d\u306a\u5024\u3067\u5373\u5ea7\u306b\u8a55\u4fa1\u3092\u78ba\u5b9a\u3055\u305b\u308b\n        if self.is_checkmate(opponent, board, captures_black, captures_white):\n            score += 100000 \n            \n        return score\n    \n    # --- \u9759\u7684\u63a2\u7d22 (Quiescence Search) ---\n    def quiesce(self, board, captures_b, captures_w, alpha, beta, player, depth_limit=3):\n        \n        # AI\u306e\u8996\u70b9\u304b\u3089\u8a55\u4fa1\u5024\u3092\u8a08\u7b97\n        current_score = self.evaluate_board(board, captures_b, captures_w, AI_PLAYER)\n        \n        # \u8a55\u4fa1\u5024\u304c\u95be\u5024\u3092\u8d85\u3048\u305f\u3089\u76f4\u3061\u306b\u6253\u3061\u5207\u308b (\u30d9\u30fc\u30bf\u30ab\u30c3\u30c8)\n        if current_score &gt;= beta:\n            return beta\n        if current_score &gt; alpha:\n            alpha = current_score\n        \n        # \u63a2\u7d22\u9650\u754c\u3092\u8d85\u3048\u305f\u3089\u7d42\u4e86\n        if depth_limit &lt;= 0:\n            return current_score\n\n        # \u653b\u6483\u7684\u306a\u624b\u3092\u5168\u3066\u53d6\u5f97 (\u738b\u624b\u3001\u99d2\u53d6\u308a\u3001\u6210\u308a\/\u6253\u3061)\n        tactical_moves = self.get_tactical_moves(player, board, captures_b, captures_w)\n\n        # \u653b\u6483\u7684\u306a\u624b\u304c\u306a\u3051\u308c\u3070\u3001\u8a55\u4fa1\u5024\u3092\u8fd4\u3057\u3066\u7d42\u4e86\uff08\u5c40\u9762\u304c\u9759\u304b\u306b\u306a\u3063\u305f\u3068\u5224\u65ad\uff09\n        if not tactical_moves:\n            return current_score\n            \n        # \u653b\u6483\u7684\u306a\u624b\u306b\u3064\u3044\u3066\u306e\u307f\u518d\u5e30\u7684\u306b\u63a2\u7d22\n        opponent = WHITE if player == BLACK else BLACK\n        is_maximizing = (player == AI_PLAYER)\n        \n        # Move Ordering\u306e\u9069\u7528\n        ordered_tactical_moves = self.order_moves(tactical_moves, board, captures_b, captures_w, player)\n        \n        for move in ordered_tactical_moves:\n            new_board, new_caps_b, new_caps_w = self.apply_move(board, captures_b, captures_w, move, player)\n            \n            # \u81ea\u7389\u304c\u738b\u624b\u306b\u306a\u3063\u3066\u3044\u306a\u3044\u304b\u30c1\u30a7\u30c3\u30af (\u5408\u6cd5\u624b\u306a\u306e\u3067\u4e0d\u8981\u3060\u304c\u5ff5\u306e\u305f\u3081)\n            if self.is_in_check(player, new_board): continue\n\n            # \u518d\u5e30\u30b3\u30fc\u30eb\n            if is_maximizing:\n                score = self.quiesce(new_board, new_caps_b, new_caps_w, alpha, beta, opponent, depth_limit - 1)\n                alpha = max(alpha, score)\n                if alpha &gt;= beta:\n                    return beta\n            else:\n                score = self.quiesce(new_board, new_caps_b, new_caps_w, alpha, beta, opponent, depth_limit - 1)\n                beta = min(beta, score)\n                if alpha &gt;= beta:\n                    return alpha\n\n        return alpha if is_maximizing else beta\n\n    # --- Move Ordering\u306e\u305f\u3081\u306e\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9 (\u5909\u66f4\u306a\u3057) ---\n    def score_move(self, move, board, captures_b, captures_w, player):\n        \"\"\"Move Ordering\u306e\u305f\u3081\u306e\u66ab\u5b9a\u7684\u306a\u30b9\u30b3\u30a2\u3092\u8a08\u7b97\"\"\"\n        score = 0\n        \n        move_type = move&#091;0]\n        if move_type == 'move':\n            _, start_r, start_c, end_r, end_c, promote = move\n            \n            # 1. \u99d2\u53d6\u308a (Capture) \u306e\u8a55\u4fa1\n            target_piece_data = board&#091;end_r]&#091;end_c]\n            if target_piece_data != EMPTY:\n                target_piece_type = target_piece_data&#091;1]\n                # \u6355\u7372\u3055\u308c\u308b\u99d2\u306e\u4fa1\u5024\u3092\u512a\u5148 (MVV-LVA\u306e\u7c21\u7565\u7248)\n                score += 500 + PIECE_VALUES.get(target_piece_type, 0)\n                \n            # 2. \u6210\u308a (Promotion) \u306e\u8a55\u4fa1\n            if promote:\n                score += 300\n                \n        elif move_type == 'drop':\n             # 3. \u6253\u3061\u8fbc\u307f (Drop) \u306f\u4e00\u822c\u306b\u5f37\u529b\n             score += 400\n\n        # 4. \u738b\u624b (Check) \u306b\u306a\u308b\u624b\u306f\u512a\u5148\n        temp_board, _, _ = self.apply_move(board, captures_b, captures_w, move, player)\n        if self.is_check(temp_board, player):\n            score += 200\n            \n        return score\n\n    def order_moves(self, legal_moves, board, captures_b, captures_w, player):\n        \"\"\"\u5408\u6cd5\u624b\u3092\u30b9\u30b3\u30a2\u306e\u9ad8\u3044\u9806\u306b\u4e26\u3073\u66ff\u3048\u308b\"\"\"\n        scored_moves = &#091;]\n        for move in legal_moves:\n            score = self.score_move(move, board, captures_b, captures_w, player)\n            scored_moves.append((score, move))\n            \n        # \u30b9\u30b3\u30a2\u3092\u964d\u9806\u306b\u30bd\u30fc\u30c8\n        scored_moves.sort(key=lambda x: x&#091;0], reverse=True)\n        return &#091;move for score, move in scored_moves]\n\n    # --- Minimax\u95a2\u6570 (Transposition Table\u306e\u5c0e\u5165) ---\n    def minimax(self, board, captures_b, captures_w, depth, is_maximizing, alpha, beta, history_states, transposition_table):\n        current_player = AI_PLAYER if is_maximizing else BLACK\n        opponent = BLACK if is_maximizing else AI_PLAYER\n        \n        # 1. \u30cf\u30c3\u30b7\u30e5\u5024\u3092\u751f\u6210\u3057\u3001TT\u3092\u691c\u7d22\n        current_state_hash = get_simple_state_string_static(board, captures_b, captures_w, current_player)\n        \n        if current_state_hash in transposition_table and transposition_table&#091;current_state_hash]&#091;'depth'] &gt;= depth:\n             entry = transposition_table&#091;current_state_hash]\n             return entry&#091;'score'], entry.get('move', None)\n\n        # 2. \u63a2\u7d22\u6df1\u3055\u304c0\u306b\u9054\u3057\u305f\u3001\u307e\u305f\u306f\u8a70\u307f\u306e\u5834\u5408\u3001\u9759\u7684\u63a2\u7d22\u306b\u79fb\u884c\n        if depth == 0 or self.is_checkmate(current_player, board, captures_b, captures_w) or self.is_checkmate(opponent, board, captures_b, captures_w):\n            score = self.quiesce(board, captures_b, captures_w, alpha, beta, current_player)\n            # TT\u306b\u4fdd\u5b58 (\u6700\u5584\u624b\u306fNone)\n            transposition_table&#091;current_state_hash] = {'depth': depth, 'score': score, 'move': None}\n            return score, None\n            \n        # 3. \u5343\u65e5\u624b\u30c1\u30a7\u30c3\u30af\n        repetition_count = history_states.count(current_state_hash)\n        if repetition_count &gt;= 3:\n            return -1000000 if is_maximizing else 1000000, None\n\n        legal_moves = self.get_all_legal_moves(current_player, board, captures_b, captures_w)\n        \n        # 4. Move Ordering\u306e\u9069\u7528\n        ordered_moves = self.order_moves(legal_moves, board, captures_b, captures_w, current_player)\n        \n        best_move = None\n        next_history_states = history_states + &#091;current_state_hash] \n        best_eval = -sys.maxsize if is_maximizing else sys.maxsize\n\n        # 5. Minimax\u63a2\u7d22\n        for move in ordered_moves:\n            new_board, new_caps_b, new_caps_w = self.apply_move(board, captures_b, captures_w, move, current_player)\n            \n            # \u5343\u65e5\u624b\u5224\u5b9a\u306e\u305f\u3081\u306e\u30cf\u30c3\u30b7\u30e5\u5024\n            next_state_hash = get_simple_state_string_static(new_board, new_caps_b, new_caps_w, opponent) \n            repetition_count_after_move = next_history_states.count(next_state_hash)\n            \n            if repetition_count_after_move &gt;= 3:\n                eval_val = -1000000 if is_maximizing else 1000000\n            else:\n                # TT\u3092\u518d\u5e30\u547c\u3073\u51fa\u3057\u306b\u6e21\u3059\n                eval_val, _ = self.minimax(new_board, new_caps_b, new_caps_w, depth - 1, not is_maximizing, alpha, beta, next_history_states, transposition_table)\n            \n            if is_maximizing:\n                if eval_val &gt; best_eval:\n                    best_eval = eval_val\n                    best_move = move\n                alpha = max(alpha, eval_val)\n                if beta &lt;= alpha:\n                    break\n            else: # Minimizing\n                if eval_val &lt; best_eval:\n                    best_eval = eval_val\n                    best_move = move\n                beta = min(beta, eval_val)\n                if beta &lt;= alpha:\n                    break\n        \n        # 6. TT\u306b\u7d50\u679c\u3092\u4fdd\u5b58\n        transposition_table&#091;current_state_hash] = {'depth': depth, 'score': best_eval, 'move': best_move}\n        \n        return best_eval, best_move\n        \n    # --- find_best_move\u306e\u5909\u66f4 (TT\u306e\u521d\u671f\u5316) ---\n    def find_best_move(self, board, captures_black, captures_white, player, depth):\n        if player != AI_PLAYER: return None\n        legal_moves = self.get_all_legal_moves(player, board, captures_black, captures_white)\n        if not legal_moves: return None\n        \n        # \u30c8\u30e9\u30f3\u30dd\u30b8\u30b7\u30e7\u30f3\u30c6\u30fc\u30d6\u30eb\u3092\u521d\u671f\u5316\n        transposition_table = {} \n        \n        # minimax\u306bTT\u3092\u6e21\u3059\n        _, best_move = self.minimax(board, captures_black, captures_white, depth, True, \n                                    -sys.maxsize, sys.maxsize, self.game_states, \n                                    transposition_table) \n        return best_move\n    \n    # ... (save_state, undo_state\u306f\u5909\u66f4\u306a\u3057) ...\n    def save_state(self):\n        state = (\n            copy.deepcopy(self.board),\n            copy.deepcopy(self.black_captures),\n            copy.deepcopy(self.white_captures),\n            self.current_player,\n            copy.deepcopy(self.game_states) \n        )\n        self.history.append(state)\n\n    def undo_state(self):\n        if len(self.history) &lt;= 1: return False \n        \n        if len(self.history) &gt;= 2:\n             self.history.pop() \n             self.history.pop() \n        else:\n             self.history.pop() \n\n        if self.history:\n            prev_state = self.history&#091;-1]\n            self.board = copy.deepcopy(prev_state&#091;0])\n            self.black_captures = copy.deepcopy(prev_state&#091;1])\n            self.white_captures = copy.deepcopy(prev_state&#091;2])\n            self.current_player = prev_state&#091;3]\n            self.game_states = copy.deepcopy(prev_state&#091;4])\n            return True\n        self.current_player = BLACK\n        self.game_states = &#091;]\n        return False\n\n# ==============================================================================\n# 4. View &amp; Controller: ShogiApp \u30af\u30e9\u30b9 (\u5909\u66f4\u306a\u3057)\n# ==============================================================================\nclass ShogiApp:\n    def __init__(self, master):\n        self.root = master\n        self.root.title(\"Shogi AI\")\n        self.game = ShogiGame() \n        self.game_running = True\n        \n        self.selected_piece = None \n        self.original_pos = None \n        self.highlight_moves = &#091;] \n        self.is_placing_piece = False \n\n        self.king_flash_job = None\n        self.is_flashing = False\n        self.kifu_text = None \n\n        self.setup_ui()\n        self.game.save_state()\n\n    def setup_ui(self):\n        main_frame = tk.Frame(self.root)\n        main_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True) \n\n        main_frame.grid_columnconfigure(0, weight=0) \n        main_frame.grid_columnconfigure(1, weight=1) \n        main_frame.grid_columnconfigure(2, weight=0) \n        main_frame.grid_rowconfigure(0, weight=1)    \n        main_frame.grid_rowconfigure(1, weight=0)    \n\n        capture_white_frame = tk.Frame(main_frame, width=SIDE_PANEL_WIDTH)\n        capture_white_frame.grid(row=0, column=0, rowspan=1, padx=(0, 10), sticky=tk.N+tk.S) \n        capture_white_frame.grid_propagate(False) \n\n        self.white_capture_canvas = tk.Canvas(capture_white_frame, width=SIDE_PANEL_WIDTH)\n        self.white_capture_canvas.pack(fill=tk.BOTH, expand=True, pady=10) \n        self._draw_capture_area(self.white_capture_canvas, WHITE)\n        self.white_capture_canvas.bind(\"&lt;Button-1&gt;\", self.on_capture_click) \n\n        board_frame = tk.Frame(main_frame)\n        board_frame.grid(row=0, column=1, padx=5, sticky=tk.N+tk.S) \n\n        self.canvas = tk.Canvas(board_frame, width=BOARD_SIZE, height=BOARD_SIZE, bg=\"#D2B48C\")\n        self.canvas.pack() \n        self.draw_board_grid(self.canvas)\n        \n        self.canvas.bind(\"&lt;Button-1&gt;\", self.on_click)\n        self.canvas.bind(\"&lt;B1-Motion&gt;\", self.on_drag)\n        self.canvas.bind(\"&lt;ButtonRelease-1&gt;\", self.on_release)\n\n        capture_black_frame = tk.Frame(main_frame, width=SIDE_PANEL_WIDTH)\n        capture_black_frame.grid(row=0, column=2, rowspan=1, padx=(10, 0), sticky=tk.N+tk.S)\n        capture_black_frame.grid_propagate(False) \n\n        capture_black_frame.grid_rowconfigure(0, weight=1) \n        capture_black_frame.grid_rowconfigure(1, weight=0) \n        capture_black_frame.grid_rowconfigure(2, weight=1) \n\n        self.black_capture_canvas = tk.Canvas(capture_black_frame, width=SIDE_PANEL_WIDTH)\n        self.black_capture_canvas.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W, pady=10, padx=5) \n        self._draw_capture_area(self.black_capture_canvas, BLACK)\n        self.black_capture_canvas.bind(\"&lt;Button-1&gt;\", self.on_capture_click) \n        \n        kifu_label = tk.Label(capture_black_frame, text=\"\u68cb\u8b5c\", font=('Arial', 12, 'bold'))\n        kifu_label.grid(row=1, column=0, pady=(5, 0), sticky=tk.N)\n\n        self.kifu_text = tk.Text(capture_black_frame, height=10, width=20, state=tk.DISABLED)\n        self.kifu_text.grid(row=2, column=0, sticky=tk.N+tk.S+tk.E+tk.W, padx=5) \n\n        control_frame = tk.Frame(main_frame)\n        control_frame.grid(row=1, column=1, pady=10, sticky=tk.N) \n\n        self.turn_label = tk.Label(control_frame, text=\"\", font=('Arial', 14, 'bold'))\n        self.turn_label.pack(side=tk.LEFT, padx=10) \n        \n        undo_button = tk.Button(control_frame, text=\"\u4e00\u624b\u623b\u3059 (Undo)\", command=self.undo_move)\n        undo_button.pack(side=tk.LEFT, padx=10) \n\n        self.draw_pieces()\n        self.draw_captured_pieces()\n        self.update_turn_indicator()\n\n    def draw_board_grid(self, canvas):\n        canvas.delete(\"grid\")\n        for i in range(10):\n            canvas.create_line(0, i * CELL_SIZE, BOARD_SIZE, i * CELL_SIZE, tags=\"grid\", width=1)\n            canvas.create_line(i * CELL_SIZE, 0, i * CELL_SIZE, BOARD_SIZE, tags=\"grid\", width=1)\n        \n        for i, kanji in enumerate(KANJI_COLUMNS):\n            canvas.create_text((8 - i) * CELL_SIZE + CELL_SIZE \/\/ 2, -10, text=kanji, fill='gray')\n            canvas.create_text(i * CELL_SIZE + CELL_SIZE \/\/ 2, BOARD_SIZE + 10, text=KANJI_ROWS&#091;i], fill='gray')\n\n    def _draw_capture_area(self, canvas, player):\n        canvas.delete(tk.ALL)\n        canvas.create_text(canvas.winfo_reqwidth() \/\/ 2, 15, \n            text=f\"\u6301\u3061\u99d2 ({player})\", font=('Arial', 10, 'bold'), fill='black')\n\n    def draw_pieces(self):\n        self.canvas.delete(\"piece\")\n        self.canvas.delete(\"highlight\")\n        \n        for r in range(9):\n            for c in range(9):\n                if (r, c) in self.highlight_moves:\n                    color = \"#FFFF00\" if self.game.board&#091;r]&#091;c] == EMPTY else \"#FF8080\"\n                    self.canvas.create_rectangle(c * CELL_SIZE, r * CELL_SIZE, \n                                                 (c + 1) * CELL_SIZE, (r + 1) * CELL_SIZE, \n                                                 fill=color, stipple=\"gray25\", tags=\"highlight\")\n                \n                piece_data = self.game.board&#091;r]&#091;c]\n                if piece_data != EMPTY:\n                    player, piece_type = piece_data\n                    text_piece = PIECES&#091;piece_type]\n                    \n                    fill_color = 'red' if piece_type == 'OU' and player == self.game.current_player and self.is_flashing else 'black'\n                    \n                    angle = 180 if player == WHITE else 0\n                    \n                    self.draw_board_cell(r, c, text_piece, fill_color, angle, player, piece_type)\n\n    def draw_board_cell(self, r, c, text_piece, fill_color, angle, player, piece_type):\n        tags = (\"piece\", f\"{player}_{piece_type}\")\n        center_x = c * CELL_SIZE + CELL_SIZE \/\/ 2\n        center_y = r * CELL_SIZE + CELL_SIZE \/\/ 2\n        \n        font_size = int(CELL_SIZE \/\/ 3.3) \n        \n        self.canvas.create_text(center_x, center_y, \n            text=text_piece, \n            font=('Arial', font_size), \n            fill=fill_color, \n            angle=angle, \n            tags=tags)\n\n    def draw_captured_pieces(self):\n        self._draw_captured_pieces_on_canvas(self.black_capture_canvas, self.game.black_captures, BLACK)\n        self._draw_captured_pieces_on_canvas(self.white_capture_canvas, self.game.white_captures, WHITE)\n\n    def _draw_captured_pieces_on_canvas(self, canvas, captures_list, player):\n        canvas_width = canvas.winfo_width() if canvas.winfo_width() &gt; 1 else SIDE_PANEL_WIDTH\n        canvas_height = canvas.winfo_height() if canvas.winfo_height() &gt; 1 else BOARD_SIZE\n        \n        canvas.delete(f\"piece_{player}\")\n        self._draw_capture_area(canvas, player)\n        \n        piece_counts = count_captured_pieces(captures_list)\n        \n        if player == BLACK:\n            start_x = 10\n            anchor_type = tk.W\n            count_text_offset = 30 \n            count_anchor = tk.W\n        else: \n            start_x = 40 \n            anchor_type = tk.W\n            count_text_offset = 30 \n            count_anchor = tk.W\n\n        current_y = 15 + CAPTURE_CELL_HEIGHT \n        max_y = canvas_height - 20 \n        \n        pieces_per_column_threshold = max(4, int(canvas_height \/ CAPTURE_CELL_HEIGHT \/ 2.5)) \n        col_count = 0 \n        \n        for piece_type in PIECE_ORDER:\n            count = piece_counts.get(piece_type, 0)\n            if count &gt; 0:\n                text_piece = PIECES&#091;piece_type]\n                \n                if col_count &gt;= pieces_per_column_threshold:\n                    if player == BLACK:\n                        start_x = canvas_width \/\/ 2 + 10 \n                    else:\n                        start_x = 10 + (canvas_width \/\/ 2)\n                        \n                    current_y = 15 + CAPTURE_CELL_HEIGHT \n                    pieces_per_column_threshold = 99 \n                    \n                fill_color = 'black'\n                if self.is_placing_piece and self.selected_piece and self.selected_piece&#091;1] == piece_type and player == BLACK:\n                    fill_color = 'blue'\n                \n                angle = 180 if player == WHITE else 0\n                \n                canvas.create_text(start_x, current_y, \n                    text=text_piece, \n                    font=('Arial', CELL_SIZE \/\/ 3), \n                    fill=fill_color, \n                    angle=angle, \n                    anchor=anchor_type, \n                    tags=(f\"piece_{player}\", f\"{player}_{piece_type}\"))\n                \n                count_text_x = start_x + count_text_offset \n                \n                canvas.create_text(count_text_x, current_y, \n                    text=f\"x{count}\", \n                    font=('Arial', CELL_SIZE \/\/ 5), \n                    fill='black', \n                    anchor=count_anchor,\n                    tags=f\"{player}_count\")\n                \n                current_y += CAPTURE_CELL_HEIGHT\n                col_count += 1\n                \n                if current_y &gt; max_y:\n                    break\n\n    def update_turn_indicator(self):\n        text = f\"\u624b\u756a: {self.game.current_player}\"\n        if self.game.current_player == BLACK:\n            self.turn_label.config(text=text, fg='blue')\n        else:\n            self.turn_label.config(text=text, fg='red')\n\n    def stop_flashing(self):\n        if self.king_flash_job:\n            self.root.after_cancel(self.king_flash_job)\n        self.is_flashing = False\n        self.king_flash_job = None\n        self.draw_pieces()\n\n    def flash_king(self, state=True):\n        self.is_flashing = state\n        self.draw_pieces()\n        self.king_flash_job = self.root.after(500, lambda: self.flash_king(not state))\n\n    def on_capture_click(self, event):\n        if not self.game_running: return\n        \n        is_white_capture_click = event.widget == self.white_capture_canvas\n        if is_white_capture_click:\n            player_in_panel = WHITE\n        else:\n            player_in_panel = BLACK\n\n        if player_in_panel == WHITE:\n            self.selected_piece = None\n            self.is_placing_piece = False\n            self.highlight_moves = &#091;]\n            self.draw_pieces()\n            self.draw_captured_pieces()\n            return\n            \n        if self.game.current_player != BLACK: return\n\n        if self.selected_piece and self.original_pos and not self.is_placing_piece:\n            self.game.board&#091;self.original_pos&#091;0]]&#091;self.original_pos&#091;1]] = self.selected_piece\n            self.original_pos = None\n\n        clicked_item = self.black_capture_canvas.find_closest(event.x, event.y)&#091;0]\n        tags = self.black_capture_canvas.gettags(clicked_item)\n        \n        target_piece_type = None\n        for tag in tags:\n            if tag.startswith(f\"{BLACK}_\") and tag != f\"{BLACK}_count\" and tag != f\"piece_{BLACK}\":\n                target_piece_type = tag.split('_')&#091;1]\n                break\n        \n        if target_piece_type:\n            piece_counts = count_captured_pieces(self.game.black_captures)\n            if piece_counts.get(target_piece_type, 0) &gt; 0:\n                \n                if self.is_placing_piece and self.selected_piece and self.selected_piece&#091;1] == target_piece_type:\n                    self.selected_piece = None\n                    self.is_placing_piece = False\n                    self.highlight_moves = &#091;]\n                else:\n                    self.selected_piece = (BLACK, target_piece_type)\n                    self.is_placing_piece = True\n                    self.original_pos = None\n                    \n                    legal_moves_raw = self.game.get_all_legal_moves(BLACK, self.game.board, self.game.black_captures, self.game.white_captures)\n                    \n                    self.highlight_moves = &#091;]\n                    for move in legal_moves_raw:\n                        if move&#091;0] == 'drop':\n                            move_type, p_type, r, c = move\n                            if p_type == target_piece_type:\n                                self.highlight_moves.append((r, c))\n                    \n                    if not self.highlight_moves:\n                        self.selected_piece = None\n                        self.is_placing_piece = False\n                        messagebox.showinfo(\"\u7121\u52b9\u306a\u624b\", \"\u305d\u306e\u99d2\u3092\u6253\u3066\u308b\u5834\u6240\u306f\u3042\u308a\u307e\u305b\u3093\u3002\", icon='warning')\n                        \n                self.draw_pieces()\n                self.draw_captured_pieces()\n                return\n\n        self.selected_piece = None\n        self.is_placing_piece = False\n        self.highlight_moves = &#091;]\n        self.draw_pieces()\n        self.draw_captured_pieces()\n\n\n    def on_click(self, event):\n        r, c = event.y \/\/ CELL_SIZE, event.x \/\/ CELL_SIZE\n        \n        if not (0 &lt;= r &lt; 9 and 0 &lt;= c &lt; 9 and self.game_running and self.game.current_player != AI_PLAYER):\n            return\n\n        if self.is_placing_piece:\n            if (r, c) in self.highlight_moves:\n                self.handle_drop_move(r, c)\n                return \n            else:\n                self.selected_piece = None\n                self.is_placing_piece = False\n                self.highlight_moves = &#091;]\n                self.draw_pieces()\n                self.draw_captured_pieces()\n                return\n\n        current_piece_data = self.game.board&#091;r]&#091;c]\n\n        if self.selected_piece and self.original_pos == (r, c):\n            self.game.board&#091;r]&#091;c] = self.selected_piece \n            self.selected_piece = None\n            self.original_pos = None\n            self.highlight_moves = &#091;]\n            self.draw_pieces()\n        \n        elif current_piece_data != EMPTY and current_piece_data&#091;0] == self.game.current_player:\n            if self.selected_piece and self.original_pos:\n                self.game.board&#091;self.original_pos&#091;0]]&#091;self.original_pos&#091;1]] = self.selected_piece\n            \n            self.selected_piece = current_piece_data\n            self.original_pos = (r, c)\n            \n            self.highlight_moves = self.game.get_valid_moves(r, c, self.game.board, self.game.current_player)\n            \n            if not self.highlight_moves:\n                self.game.board&#091;r]&#091;c] = self.selected_piece \n                self.selected_piece = None\n                self.original_pos = None\n            else:\n                self.game.board&#091;r]&#091;c] = EMPTY \n                \n            self.draw_pieces()\n        \n        else:\n            if self.selected_piece and self.original_pos:\n                self.game.board&#091;self.original_pos&#091;0]]&#091;self.original_pos&#091;1]] = self.selected_piece\n                \n            self.selected_piece = None\n            self.original_pos = None\n            self.highlight_moves = &#091;]\n            self.draw_pieces()\n\n    def on_drag(self, event):\n        if self.selected_piece and not self.is_placing_piece:\n            self.canvas.delete(\"drag_piece\")\n            player, piece_type = self.selected_piece\n            text_piece = PIECES&#091;piece_type]\n            angle = 180 if player == WHITE else 0\n            \n            font_size = int(CELL_SIZE \/\/ 3.3)\n            \n            self.canvas.create_text(event.x, event.y, \n                text=text_piece, \n                font=('Arial', font_size), \n                fill='black', \n                angle=angle, \n                tags=\"drag_piece\")\n    \n    def on_release(self, event):\n        if self.is_placing_piece:\n            self.canvas.delete(\"drag_piece\")\n            return\n\n        if not self.game_running or self.game.current_player == AI_PLAYER:\n            self.canvas.delete(\"drag_piece\")\n            if self.selected_piece and self.original_pos:\n                self.game.board&#091;self.original_pos&#091;0]]&#091;self.original_pos&#091;1]] = self.selected_piece\n            self.selected_piece = None\n            self.original_pos = None\n            self.is_placing_piece = False\n            return\n\n        if self.selected_piece and self.original_pos:\n            new_col = event.x \/\/ CELL_SIZE\n            new_row = event.y \/\/ CELL_SIZE\n            \n            is_valid_area = 0 &lt;= new_row &lt; 9 and 0 &lt;= new_col &lt; 9\n            is_valid_move = is_valid_area and (new_row, new_col) in self.highlight_moves\n            \n            player = self.selected_piece&#091;0]\n            \n            if is_valid_move:\n                \n                board_before_move = copy.deepcopy(self.game.board)\n                piece_type_before_promotion = self.selected_piece&#091;1]\n                \n                target_piece = board_before_move&#091;new_row]&#091;new_col]\n                if target_piece != EMPTY:\n                    captured_piece = get_demoted_piece(target_piece&#091;1])\n                    capture_list = self.game.black_captures \n                    capture_list.append((player, captured_piece))\n                \n                promote_flag = False\n                can_promote_check = should_promote(piece_type_before_promotion, player, self.original_pos&#091;0], new_row)\n                is_forced_promotion = (\n                    (piece_type_before_promotion in &#091;'FU', '\u9999'] and ((player == BLACK and new_row == 0) or (player == WHITE and new_row == 8))) or\n                    (piece_type_before_promotion == 'KE' and ((player == BLACK and new_row &lt;= 1) or (player == WHITE and new_row &gt;= 7)))\n                )\n\n                if is_forced_promotion:\n                    self.selected_piece = (player, get_promoted_piece(piece_type_before_promotion))\n                    promote_flag = True\n                elif can_promote_check:\n                    result = messagebox.askyesno(\"\u6210\u308a\", \"\u6210\u308a\u307e\u3059\u304b\uff1f (\u300c\u3044\u3044\u3048\u300d\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u6210\u308a\u307e\u305b\u3093\u3002)\")\n                    if result:\n                        self.selected_piece = (player, get_promoted_piece(piece_type_before_promotion))\n                        promote_flag = True\n\n                self.game.board&#091;new_row]&#091;new_col] = self.selected_piece\n                \n                move_details = ('move', self.original_pos&#091;0], self.original_pos&#091;1], new_row, new_col, promote_flag)\n                turn_count = (len(self.game.history) \/\/ 2) + 1 \n                kifu_str = format_move_to_kifu_static(move_details, player, board_before_move)\n                \n                if player == BLACK:\n                    self.append_kifu(f\"{turn_count}. \u2617{kifu_str}\")\n                else: \n                    self.append_kifu(f\"&nbsp; &nbsp;\u2616{kifu_str}\") \n\n                self.handle_end_turn(WHITE)\n        \n            else:\n                if self.original_pos:\n                    self.game.board&#091;self.original_pos&#091;0]]&#091;self.original_pos&#091;1]] = self.selected_piece\n\n            self.selected_piece = None\n            self.original_pos = None\n            self.highlight_moves = &#091;]\n            self.is_placing_piece = False\n\n            self.canvas.delete(\"drag_piece\")\n            self.draw_pieces()\n            self.draw_captured_pieces()\n    \n    def handle_drop_move(self, r, c):\n        if not self.is_placing_piece or not self.selected_piece: return\n\n        piece_type = self.selected_piece&#091;1]\n        player = self.selected_piece&#091;0]\n        \n        temp_list = &#091;]\n        removed = False\n        for p, t in self.game.black_captures: \n            if t == piece_type and not removed:\n                removed = True \n            else:\n                temp_list.append((p, t))\n        self.game.black_captures = temp_list \n        \n        self.game.board&#091;r]&#091;c] = self.selected_piece \n        \n        move_details = ('drop', piece_type, r, c)\n        turn_count = (len(self.game.history) \/\/ 2) + 1 \n        kifu_str = format_move_to_kifu_static(move_details, player, self.game.board) + \"\u6253\"\n        self.append_kifu(f\"{turn_count}. \u2617{kifu_str}\") \n        \n        self.selected_piece = None\n        self.is_placing_piece = False\n        self.highlight_moves = &#091;]\n        \n        self.handle_end_turn(WHITE)\n\n\n    def handle_end_turn(self, next_player):\n        self.game.current_player = next_player\n        \n        current_state = get_simple_state_string_static(self.game.board, self.game.black_captures, self.game.white_captures, self.game.current_player)\n        self.game.game_states.append(current_state)\n        self.game.save_state()\n        \n        repetition_count = self.game.game_states.count(current_state)\n        \n        if repetition_count &gt;= 4:\n            messagebox.showinfo(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", \"\u5343\u65e5\u624b\u306b\u3088\u308a\u5f15\u304d\u5206\u3051\u3067\u3059\u3002\")\n            self.game_running = False\n            self.stop_flashing()\n            return\n\n        self.stop_flashing()\n        self.update_turn_indicator()\n\n        if self.game_running:\n            self.draw_pieces()\n            self.draw_captured_pieces()\n            \n            if self.game.is_checkmate(self.game.current_player, self.game.board, self.game.black_captures, self.game.white_captures):\n                winner = BLACK if self.game.current_player == WHITE else WHITE\n                messagebox.showinfo(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", f\"\u8a70\u307f\u3067\u3059\uff01{winner}\u306e\u52dd\u5229\uff01\")\n                self.game_running = False\n            \n            elif self.game.is_in_check(self.game.current_player, self.game.board):\n                self.flash_king() \n\n            if self.game.current_player == AI_PLAYER and self.game_running:\n                self.canvas.after(500, self.make_ai_move)\n\n    def undo_move(self):\n        if self.game.current_player == AI_PLAYER:\n            messagebox.showinfo(\"\u8b66\u544a\", \"AI\u306e\u624b\u756a\u4e2d\u306fUndo\u3067\u304d\u307e\u305b\u3093\u3002AI\u306e\u624b\u304c\u7d42\u308f\u308b\u307e\u3067\u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002\")\n            return\n            \n        self.kifu_text.config(state=tk.NORMAL)\n        self.kifu_text.delete(1.0, tk.END)\n        \n        if self.game.undo_state():\n            self.stop_flashing()\n            self.selected_piece = None\n            self.original_pos = None\n            self.is_placing_piece = False\n            self.highlight_moves = &#091;]\n            self.game_running = True\n            \n            self.draw_pieces()\n            self.draw_captured_pieces()\n            self.update_turn_indicator()\n            \n            if self.game.is_in_check(self.game.current_player, self.game.board):\n                self.flash_king()\n\n            if self.game.current_player == AI_PLAYER and self.game_running:\n                self.canvas.after(500, self.make_ai_move)\n            \n            self.kifu_text.config(state=tk.DISABLED)\n            \n            return True\n        else:\n            messagebox.showinfo(\"\u60c5\u5831\", \"\u3053\u308c\u4ee5\u4e0a\u3001\u624b\u306f\u623b\u305b\u307e\u305b\u3093\u3002\")\n            self.kifu_text.config(state=tk.DISABLED)\n            return False\n                \n    def make_ai_move(self):\n        if not self.game_running or self.game.current_player != AI_PLAYER: return\n        \n        board_before_move = copy.deepcopy(self.game.board)\n        \n        chosen_move = self.game.find_best_move(self.game.board, self.game.black_captures, self.game.white_captures, AI_PLAYER, SEARCH_DEPTH)\n        \n        if chosen_move is None:\n            messagebox.showinfo(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", \"AI\u306b\u5408\u6cd5\u624b\u304c\u3042\u308a\u307e\u305b\u3093\u3002\")\n            self.game_running = False\n            return\n            \n        self.game.board, self.game.black_captures, self.game.white_captures = self.game.apply_move(\n            self.game.board, \n            self.game.black_captures, \n            self.game.white_captures, \n            chosen_move, \n            AI_PLAYER\n        )\n\n        move_details = chosen_move\n        player = AI_PLAYER\n        \n        kifu_str = format_move_to_kifu_static(move_details, player, board_before_move)\n        \n        if move_details&#091;0] == 'drop':\n             kifu_str += \"\u6253\"\n\n        self.append_kifu(f\"&nbsp; &nbsp;\u2616{kifu_str}\") \n\n        self.handle_end_turn(BLACK)\n\n    def append_kifu(self, kifu_string):\n        self.kifu_text.config(state=tk.NORMAL)\n        self.kifu_text.insert(tk.END, kifu_string + \"\\n\")\n        self.kifu_text.see(tk.END)\n        self.kifu_text.config(state=tk.DISABLED)\n\n# ==============================================================================\n# 5. \u30e1\u30a4\u30f3\u5b9f\u884c\u90e8 (\u5909\u66f4\u306a\u3057)\n# ==============================================================================\nif __name__ == \"__main__\":\n    root = tk.Tk()\n    app = ShogiApp(root)\n    root.mainloop()<\/code><\/pre>\n<\/details>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-6fa6bfbd80a239f639fe034511d73f77\" style=\"background-color:#004b76\">III. Redkabagon\u306e\u30b2\u30fc\u30e0\u9032\u5c55\u3068\u6b21\u56de\u4e88\u544a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-1c889166fe9cab49c34bc145ebc2426f\" style=\"font-size:20px\">1. Redkabagon\u306eG5\u30b2\u30fc\u30e0\u9032\u5c55<\/h3>\n\n\n\n<p><strong>\u4e00\u65b9\u3067\u3001<strong>Redkabagon\u306f\u3001\u3053\u308c\u307e\u3067\u901a\u308aG5 Entertainment\u63d0\u4f9b\u306e<\/strong>\u30a2\u30a4\u30c6\u30e0\u63a2\u3057\uff063\u30de\u30c3\u30c1\u30b2\u30fc\u30e0<\/strong>\u3092\u30af\u30ea\u30a2\u3059\u308b\u52d5\u753b\u3092\u6295\u7a3f\u3057\u3001\u30d6\u30ed\u30b0\u306b\u30ea\u30f3\u30af\u3057\u3066\u3044\u307e\u3059\u3002\u5f7c\u5973\u306e\u7740\u5b9f\u306a\u30b2\u30fc\u30e0\u30af\u30ea\u30a2\u3082\u3001\u672c\u30b7\u30ea\u30fc\u30ba\u306e\u96a0\u308c\u305f\u898b\u3069\u3053\u308d\u3067\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"\u3010R60\u592b\u5a66\u306e\u8133\u5185\u6d3b\u6027\u30ed\u30b0  - Sherlock:\u30a2\u30a4\u30c6\u30e0\u63a2\u3057\uff06\u30de\u30c3\u30c13Vol.5\u3011\" width=\"525\" height=\"295\" src=\"https:\/\/www.youtube.com\/embed\/FGKd5aOyKjo?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><figcaption class=\"wp-element-caption\">\u30a2\u30a4\u30c6\u30e0\u63a2\u3057\uff063\u30de\u30c3\u30c1<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-cyan-blue-background-color has-text-color has-background has-link-color wp-elements-0753c4a78c0c35fea54c19513986ab6a\" style=\"font-size:20px\">2. \u30b7\u30ea\u30fc\u30ba\u306e\u7d99\u7d9a\u3068\u6b21\u56de\u306e\u6311\u6226<\/h3>\n\n\n\n<p>\u672c\u30b7\u30ea\u30fc\u30ba\u306f\u3001\u4eca\u5f8c\u3082\u7d99\u7d9a\u7684\u306b\u65b0\u3057\u3044\u30a2\u30d7\u30ea\u958b\u767a\u306b\u6311\u3093\u3067\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p>Redkabagon\u3055\u3093\u306e\u516c\u9053\u30c7\u30d3\u30e5\u30fc\u306f\u30cd\u30bf\u5316\u3057\u3066\u3044\u307e\u3059\u304c\u3001\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u521d\u5fc3\u8005\u306e\u7b46\u8005\u3082\u3001AI\u306e\u529b\u3092\u501f\u308a\u3066\u300eAI\u30b3\u30fc\u30c0\u30fc\u300f\u3068\u3057\u3066\u30c7\u30d3\u30e5\u30fc\u3067\u304d\u308b\u306e\u304b\u3001\u3069\u3046\u304b\uff01\uff1f\u3068\u3044\u3046\u6311\u6226\u306f\u7d9a\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u6b21\u56de\u306f<strong>\u5225\u306e\u30d1\u30ba\u30eb\u30b2\u30fc\u30e0\u30a2\u30d7\u30ea\u306e\u4f5c\u6210<\/strong>\u3001\u307e\u305f\u306f<strong>\u30d7\u30ed\u306e\u8133\u30c8\u30ec\u30a2\u30d7\u30ea\u306e\u6a5f\u80fd\u3068\u306e\u6bd4\u8f03\u691c\u8a3c<\/strong>\u3092\u4e88\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u3069\u3046\u305e\u3001Gemini\u306e\u30d7\u30ed\u30f3\u30d7\u30c8\u306e\u4e16\u754c\u306b\u98db\u3073\u8fbc\u3093\u3067\u307f\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-1cab9a404bb2aed3853792be230bccc7\" style=\"background-color:#004b76;font-size:20px\">\u3010The Gear\u3011\u64ae\u5f71\u6a5f\u6750\u306e\u3054\u7d39\u4ecb<\/h2>\n\n\n\n<p>\u672c\u52d5\u753b\u306e\u64ae\u5f71\u6a5f\u6750\u3084\u65b0\u3057\u3044\u52d5\u753b\u7de8\u96c6\u30bd\u30d5\u30c8\u300cPowerDirector 365\u300d\u306b\u95a2\u3059\u308b\u60c5\u5831\u3001\u30a2\u30d5\u30a3\u30ea\u30a8\u30a4\u30c8\u60c5\u5831\u306b\u3064\u3044\u3066\u306f\u3001<strong>\u300cThe Gear\u300d\u30ab\u30c6\u30b4\u30ea\u30fc<\/strong>\u3067\u8a73\u3057\u304f\u3054\u7d39\u4ecb\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-su-blogcard\">\n\t<article class=\"wp-blogcard\" cite=\"https:\/\/smilekabagon.com\/?cat=280\">\n\t\t<a\n\t\t\thref=\"https:\/\/smilekabagon.com\/?cat=280\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer nofollow sponsored ugc\"\n\t\t\t\t\t\tclass=\"wp-blogcard-item\"\n\t\t>\n\t\t\t\t\t\t\t<figure class=\"wp-blogcard-figure\">\n\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/smilekabagon.com\/wp-content\/uploads\/2020\/08\/BeautyPlus_20200705213331865_save-150x150.jpg\" alt=\"\" aria-hidden=\"true\" \/>\n\t\t\t\t<\/figure>\n\t\t\t\t\t\t<div class=\"wp-blogcard-content\">\n\t\t\t\t<div class=\"wp-blogcard-title\">\u524d\u56de\u307e\u3067\u306e\u8133\u5185\u6d3b\u6027\u306e\u30d6\u30ed\u30b0<\/div>\n\t\t\t\t<div class=\"wp-blogcard-description\">\u8a8d\u77e5\u75c7\u306e\u5224\u65ad\u30c6\u30b9\u30c8\u306b\u884c\u308f\u308c\u308b\u8a18\u61b6\u80fd\u529b\u3068\u3001\u7a7a\u9593\u8a8d\u77e5\u529b\u304c\u30c6\u30fc\u30de\u306b\u306a\u3063\u305f\u30aa\u30f3\u30e9\u30a4\u30f3\u30b2\u30fc\u30e0\u3092\u884c\u3063\u3066\u3044\u304d\u307e\u3059\u3002\u305d\u3057\u3066\u306a\u305credkabagon\u304c\u500b\u5225\u3067\u767b\u5834\u3059\u308b\u306e\u304b\u3068\u8a00\u3046\u3068\u3001\u3053\u308c\u3089\u306e\u30b2\u30fc\u30e0\u304c\u5f97\u610f\u51fa\u3042\u308b\u305f\u3081\u3001\u8ab2\u91d1\u3092\u305b\u305a\u306b\u3069\u3053\u307e\u3067\u30ec\u30d9\u30eb\u30a2\u30c3\u30d7\u304c\u3067\u304d\u308b\u306e\u304b\u3092\u767a\u4fe1\u3057\u305f\u3044\u304b\u3089\u3067\u3059<\/div>\n\t\t\t\t<div class=\"wp-blogcard-cite\">\n\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tclass=\"wp-blogcard-favicon\"\n\t\t\t\t\t\t\tsrc=\"https:\/\/smilekabagon.com\/favicon.ico\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\/>\n\t\t\t\t\t\t\t\t\t\t<div class=\"wp-blogcard-domain\">smilekabagon.com<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/a>\n\t<\/article>\n<\/div>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Dr.takodemous\uff08\u7b46\u8005\uff09<\/summary>\n<p><strong>\u300cAI\u30b3\u30fc\u30c0\u30fc\u300d<strong>\u3092\u76ee\u6307\u3059R60\u4e16\u4ee3\u306e\u592b\u3002\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u7121\u77e5\u306a\u304c\u3089\u3001Gemini\uff08AI\uff09\u3068<\/strong>\u683c\u95d8<\/strong>\u3057\u306a\u304c\u3089\u30a2\u30d7\u30ea\u958b\u767a\u306b\u6311\u3080\u30ed\u30b8\u30c3\u30af\u62c5\u5f53\u3002\u8da3\u5473\u306fAI\u3068\u306e\u5bfe\u8a71\u3068\u3001\u6614\u53d6\u3063\u305f\u6775\u67c4\u306e\u683c\u95d8\u6280\u3002\u6700\u8fd1\u306f\u59bb\u3068\u697d\u3057\u3080<strong>\u8fd1\u90ca\u3078\u306e\u592b\u5a66\u65c5<\/strong>\u306e\u4f01\u753b\u3068\u3001<strong>\u30a4\u30f3\u30c9\u30a2\u30fb\u30a2\u30a6\u30c8\u30c9\u30a2\u6d3b\u52d5\u306e\u7d4c\u8cbb\u5316<\/strong>\u3092\u76ee\u7684\u3068\u3057\u305f\u751f\u6d3b\u7814\u7a76\u306b\u71b1\u4e2d\u3057\u3066\u3044\u307e\u3059\u3002**R60\u304c\u9811\u5f35\u3063\u3066\u30c1\u30e3\u30ec\u30f3\u30b8\u3057\u3066\u307f\u305f\uff01**\u3068\u3044\u3046\u30c6\u30fc\u30de\u3067\u3001\u65b0\u3057\u3044\u767a\u898b\u3092\u5171\u6709\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Redkabagon\uff08\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306e\u59bb\uff09<\/summary>\n<p><\/p>\n<\/details>\n<\/details>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Redkabagon\uff08\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306e\u59bb\uff09<\/summary>\n<p>\u592b\u3068\u5171\u306b\u30d6\u30ed\u30b0\u3092\u904b\u55b6\u3059\u308bR60\u4e16\u4ee3\u306e\u59bb\u3002\u5f97\u610f\u5206\u91ce\u306f\u3001<strong>\u8133\u5185\u6d3b\u6027\uff08\u30ca\u30f3\u30d7\u30ec\u3001\u30b2\u30fc\u30e0\uff09<strong>\u3068\u3001\u592b\u5a66\u306e\u6d3b\u52d5\u3092\u652f\u3048\u308b<\/strong>\u751f\u6d3b\u306e\u77e5\u6075<\/strong>\u3002G5\u30b2\u30fc\u30e0\u3084\u8da3\u5473\u306e\u97f3\u697d\u52d5\u753b\uff08Remix\uff09\u306e\u5236\u4f5c\u306b\u3082\u6311\u6226\u4e2d\u3002\u7279\u306b\u3001**\u7279\u6280\u3092\u6d3b\u304b\u3057\u305f\u30ec\u30f3\u30bf\u30eb\u4f01\u753b\uff08\u89b3\u8449\u690d\u7269\u306a\u3069\uff09<strong>\u306e\u5b9f\u73fe\u306b\u5411\u3051\u3066\u596e\u95d8\u4e2d\u3067\u3059\u3002\u592b\u306e\u5947\u629c\u306a\u30a2\u30a4\u30c7\u30a2\u306b\u632f\u308a\u56de\u3055\u308c\u3064\u3064\u3001\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u304c\u4ef2\u826f\u304f\u8001\u3044\u3066\u3044\u304f\u305f\u3081\u306e<\/strong>\u300c\u7d46\u3068\u7652\u3084\u3057\u306e\u30ed\u30b8\u30c3\u30af\u300d**\u3092\u62c5\u5f53\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n<\/details>\n\n\n<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/smilekabagon.com\" title=\"\u30db\u30fc\u30e0\">\u30db\u30fc\u30e0<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/smilekabagon.com\/?cat=280\" title=\"game\">game<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log Vol.3\uff1a\u5c06\u68cb\u7de8\n\t\t<\/span><\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I. \u6311\u6226\uff1aAI\u3068\u683c\u95d8\uff01Python\u3067\u5c06\u68cb\u30b2\u30fc\u30e0\u3092\u4f5c\u6210 1. \u65b0\u3057\u3044\u6311\u6226\u3068\u30b7\u30ea\u30fc\u30ba\u306e\u30c6\u30fc\u30de \u300cGame Trial Log\u300d\u30b7\u30ea\u30fc\u30ba Vol.3\u3078\u3088\u3046\u3053\u305d\u3002 \u672c\u30b7\u30ea\u30fc\u30ba\u306e\u6838\u3068\u306a\u308b\u30c6\u30fc\u30de\u306f\u3001\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u7121\u77e5\u306a\u7b46\u8005Dr.t &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/smilekabagon.com\/?p=3943\" class=\"more-link\"><span class=\"screen-reader-text\">&#8220;\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log Vol.3\uff1a\u5c06\u68cb\u7de8&#8221; \u306e<\/span>\u7d9a\u304d\u3092\u8aad\u3080<\/a><\/p>\n","protected":false},"author":2,"featured_media":3969,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[280],"tags":[274],"class_list":["post-3943","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-game","tag-274"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/posts\/3943","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3943"}],"version-history":[{"count":17,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/posts\/3943\/revisions"}],"predecessor-version":[{"id":4042,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/posts\/3943\/revisions\/4042"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/media\/3969"}],"wp:attachment":[{"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}