{"id":3961,"date":"2025-10-15T19:36:44","date_gmt":"2025-10-15T10:36:44","guid":{"rendered":"https:\/\/smilekabagon.com\/?p=3961"},"modified":"2026-02-12T18:58:07","modified_gmt":"2026-02-12T09:58:07","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-4%ef%bc%9a%e4%b8%83%e4%b8%a6%e3%81%b9%ef%bc%88sevens%ef%bc%89","status":"publish","type":"post","link":"https:\/\/smilekabagon.com\/?p=3961","title":{"rendered":"&#x1f3af; \u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log Vol.4\uff1a\u4e03\u4e26\u3079\uff08Sevens\uff09"},"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-3fef7a389e666d4ece5f7229603b5994\" style=\"background-color:#004b76;font-size:20px\"><strong>&#x1f3ac; \u5c0e\u5165\uff1aR60\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u3001\u4e03\u4e26\u3079AI\u958b\u767a\u3067\u300c\u8133\u5185\u6d3b\u6027\u300d\u306b\u6311\u3080\uff01<\/strong><\/h1>\n\n\n\n<p>\u79c1\u305f\u3061R60\u306e\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306f\u3001\u4ef2\u826f\u304f\u8001\u3044\u3066\u3044\u304f\u4e2d\u3067\u3001\u8133\u5185\u6d3b\u6027\uff08\u30a2\u30f3\u30c1\u30a8\u30a4\u30b8\u30f3\u30b0\uff09\u306e\u305f\u3081\u306e\u6311\u6226\u3092\u7d9a\u3051\u308b\u300c\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log\u300d\u30b7\u30ea\u30fc\u30ba\u3092\u7d9a\u3051\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u4eca\u56de\u306fVol.3\u306e\u96e3\u984c\u3067\u3042\u3063\u305f\u5c06\u68cb\u7de8\u304b\u3089\u4e00\u8ee2\u3001Python\u3067\u30c8\u30e9\u30f3\u30d7\u306e\u300c\u4e03\u4e26\u3079\uff08Sevens\uff09\u30a2\u30d7\u30ea\u300d\u306eAI\u958b\u767a\u306b\u6311\u307f\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<p><strong>\u3010YouTube\u30bf\u30a4\u30c8\u30eb\u3011<\/strong> \u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u7121\u77e5\u306a\u7b46\u8005Dr.takodemous\u304c\u3001AI\uff08Gemini\uff09\u3068\u5171\u540c\u958b\u767a\u3057\u305f\u4e03\u4e26\u3079\u30a2\u30d7\u30ea\u3002\u5916\u90ed\u306f\u300c\u30d7\u30ed\u30f3\u30d7\u30c8\u4e00\u767a\u300d\u3067\u7206\u901f\u5b8c\u4e86\u3057\u305f\u3082\u306e\u306e\u3001\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u5b9a\u7fa9\u3084CM\uff08\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\uff09\u5074\u306e\u6226\u7565\u304c\u96e3\u95a2\u3059\u304e\u3001\u5168\u54e1\u7d9a\u884c\u4e0d\u80fd\u306e\u5371\u6a5f\u306b\uff01\u52d5\u753b\u3067\u306f\u3001\u3053\u306eAI\u306e\u6b20\u9665\u3092\u56de\u907f\u3059\u308b\u305f\u3081\u3001\u592b\u5a66\u4e8c\u4eba\u3067\u6226\u7565\u3092\u7acb\u3066\u3066CM\u306b\u6311\u3080\u69d8\u5b50\u3092\u304a\u5c4a\u3051\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-e4b9feb7fa36c4ebda30a4f11cb615e6\" style=\"background-color:#004b76;font-size:20px\"><strong><strong>I. Dr.takodemous\u306e\u6226\u3044\uff1aAI\u3068\u306e\u5171\u540c\u958b\u767a\u30ed\u30b0<\/strong><\/strong><\/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-68cf833fadea3b21230ef7e1796ca9be\" style=\"font-size:20px\"><strong><strong>1. \u7206\u901f\u958b\u767a\u3068\u521d\u671f\u306e\u58c1\uff1a\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u7f60<\/strong><\/strong><\/h3>\n\n\n\n<p>Vol.3\u307e\u3067\u306e\u7d4c\u9a13\u3092\u6d3b\u304b\u3057\u3001\u4e03\u4e26\u3079\u306e<strong>\u5916\u90ed\u3068\u30eb\u30fc\u30eb\u8a2d\u5b9a<\/strong>\u306f\u9a5a\u304f\u307b\u3069\u30b9\u30e0\u30fc\u30ba\u306b\u9032\u884c\u3057\u307e\u3057\u305f\u3002\u3057\u304b\u3057\u3001\u30c8\u30e9\u30f3\u30d7\u30b2\u30fc\u30e0\u306a\u3089\u3067\u306f\u306e<strong>\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u5b9a\u7fa9<\/strong>\u304c\u6700\u521d\u306e\u96e3\u95a2\u3067\u3057\u305f\u3002<\/p>\n\n\n\n<p><strong>\u3010&#x1f4bb;\u96e3\u95a2\uff01\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u7f60\u3011<\/strong> \u30ab\u30fc\u30c9\u306e\u30de\u30fc\u30af\u3084\u6570\u5b57\u3092Python\u304c\u6b63\u78ba\u306b\u8aad\u307f\u8fbc\u3081\u305a\u3001\u4efb\u610f\u306e\u5834\u6240\u306b\u7f6e\u3051\u308b\u3068\u3044\u3046<strong>\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u7279\u6b8a\u306a\u30eb\u30fc\u30eb<\/strong>\u3092\u8a2d\u5b9a\u3059\u308b\u306e\u306b\u5927\u5e45\u306b\u6642\u9593\u3092\u8cbb\u3084\u3057\u307e\u3057\u305f\u3002\u3053\u306e\u5b9a\u7fa9\u306e\u8907\u96d1\u3055\u304c\u3001\u5f8c\u306eCM\u6226\u7565\u306e\u6b20\u9665\u306b\u3082\u7e4b\u304c\u3063\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-5fea23d6fe686b91bb316f7bb59d8664\" style=\"background-color:#004b76;font-size:20px\"><strong>II. &#x1f4bb; \u96e3\u95a2\uff01CM\u6226\u7565\u3068\u30c7\u30d0\u30c3\u30b0\u306e\u82e6\u52b4\u8a71\uff08\u6280\u8853\u7684\u306a\u6838\uff09<\/strong><\/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-d04dbf7cfb1ba8b7f54eb0e816f9e20a\" style=\"font-size:19px\"><strong>1. CM\u306e\u58c1\u3068\u81f4\u547d\u7684\u306a\u6b20\u9665<\/strong><\/h3>\n\n\n\n<p>\u4e03\u4e26\u3079AI\u306e\u6700\u5927\u306e\u96e3\u95a2\u306f\u3001<strong>CM\u5074\u306b\u4eba\u9593\u306e\u3088\u3046\u306a\u6226\u7565\u7684\u306a\u5224\u65ad\u3092\u3055\u305b\u308b\u3053\u3068<\/strong>\u3067\u3057\u305f\u3002<\/p>\n\n\n\n<p><strong>\u3010&#x1f4bb;\u96e3\u95a2\uff01CM\u306e\u58c1\u3011<\/strong> CM\u5074\u306f\u3001\u9060\u3044\u5834\u6240\u304b\u3089\u9806\u306b\u7f6e\u304f\u3053\u3068\u3057\u304b\u8a2d\u5b9a\u3067\u304d\u305a\u3001<strong>\u30ad\u30f3\u30b0\u3084\u30a8\u30fc\u30b9\u3092\u6301\u3063\u3066\u3044\u308b\u5834\u5408\u3067\u3082\u3001\u3042\u3048\u3066\uff17\u306b\u8fd1\u3044\u5834\u6240\u3092\u7f6e\u3044\u3066\u5834\u306e\u6d41\u308c\u3092\u652f\u914d\u3059\u308b<\/strong>\u3068\u3044\u3063\u305f\u6226\u7565\u304c\u4e0d\u80fd\u3067\u3057\u305f\u3002\u3053\u306e\u878d\u901a\u306e\u5229\u304b\u306a\u3044\u30ed\u30b8\u30c3\u30af\u3053\u305d\u304c\u3001\u300c\u5168\u54e1\u7d9a\u884c\u4e0d\u80fd\u300d\u306e\u5371\u6a5f\u3092\u62db\u304f\u81f4\u547d\u7684\u306a\u6b20\u9665\u3068\u306a\u308a\u307e\u3059\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-415e14b4b59d1281168c405af35f05e0\" style=\"font-size:19px\">\u3010\u30b5\u30a4\u30c8\u7d39\u4ecb\u3011\u30d7\u30ed\u306e\u30b3\u30fc\u30c0\u30fc\u306e\u8133\u30c8\u30ec\u30a2\u30d7\u30ea\u3068\u306e\u5bfe\u6bd4<\/h3>\n\n\n\n<p>\u4eca\u56de\u3082\u524d\u56de\u540c\u69d8\u3001<strong>PR TIMES\u3055\u3093\u306e\u30b5\u30a4\u30c8\u3088\u308a\u30d7\u30ed\u306e\u30b3\u30fc\u30c0\u30fc\u304c\u4f5c\u6210\u3057\u305f\u8133\u30c8\u30ecWeb\u30b2\u30fc\u30e0\u3092\u7d39\u4ecb\u3057\u307e\u3059<\/strong>\u3002<\/p>\n\n\n\n<p><strong>\u7d20\u4eba\u306eAI\u30b3\u30fc\u30c0\u30fc\u3067\u3042\u308b\u7b46\u8005\u306e\u30b3\u30fc\u30c9<\/strong>\u306e\u96e3\u89e3\u3055\u3068\u3001<strong>\u30d7\u30ed\u306e\u30a2\u30d7\u30ea\u306e\u6a5f\u80fd<\/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\u3053\u308c\u306b\u3088\u308a\u3001\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u521d\u5fc3\u8005\u3067\u3082AI\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\u3092\u5f37\u8abf\u3057\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<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-d3ac8363dcf044b9245893173b1bce02\" style=\"background-color:#004b76;font-size:20px\"><strong>III. Redkabagon\u53c2\u6226\uff01\u592b\u5a66\u5171\u95d8\u3067AI\u306e\u6b20\u9665\u3092\u653b\u7565<\/strong><\/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-cbf8518dff9418a1a44d8ebc51a1b4dc\" style=\"font-size:20px\"><strong>1. Redkabagon\u53c2\u6226\u3068\u592b\u5a66\u5171\u95d8\u306e\u30c6\u30fc\u30de<\/strong><\/h3>\n\n\n\n<p>\u524d\u56de\u306e\u5c06\u68cb\u7de8\u3067\u306f\u30ae\u30d6\u30a2\u30c3\u30d7\u3057\u305fRedkabagon\u3067\u3059\u304c\u3001\u4eca\u56de\u306f\u3053\u306e\u300c\u878d\u901a\u306e\u5229\u304b\u306a\u3044AI\u306e\u5f31\u70b9\u300d\u3092\u653b\u7565\u3059\u308b\u30d1\u30ba\u30eb\u8981\u7d20\u306b\u8208\u5473\u3092\u793a\u3057\u3001\u592b\u5a66\u5171\u95d8\u304c\u5b9f\u73fe\u3057\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<p>\u52d5\u753b\u3067\u306f\u3001\u3053\u306eAI\u306e\u6b20\u9665\u3092\u56de\u907f\u3059\u308b\u305f\u3081\u3001<strong>R60\u592b\u5a66\u4e8c\u4eba\u3067\u6226\u7565\u3092\u7acb\u3066\u3066CM\u306b\u6311\u3080<\/strong>\u69d8\u5b50\u304c\u53ce\u9332\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u592b\u5a66\u306e\u4f1a\u8a71\u3092\u901a\u3058\u3066\u3001CM\u304c\u6b21\u306b\u4f55\u3092\u7f6e\u304f\u304b\u3092\u4e88\u6e2c\u3059\u308b\u4f5c\u696d\u306f\u3001\u307e\u3055\u306b\u8133\u5185\u6d3b\u6027\uff08\u30a2\u30f3\u30c1\u30a8\u30a4\u30b8\u30f3\u30b0\uff09\u305d\u306e\u3082\u306e\u3067\u3059\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-90b073aff49f654790ce0ceab0caec89\" style=\"font-size:20px\">2. Redkabagon\u306e\u30bd\u30ed\u6d3b\u52d5\u3068\u7740\u5b9f\u306a\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\u3092\u30af\u30ea\u30a2\u3059\u308b\u52d5\u753b\u3092\u6295\u7a3f<\/strong>\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<p><strong>\u3055\u3089\u306b\u3001<\/strong> Redkabagon\u306e\u30bd\u30ed\u6d3b\u52d5\u3068\u3057\u3066\u3001\u300c\u65e5\u5e38\u306b\u307b\u307c\u4e0d\u8981\u306a\u7279\u6b8a\u80fd\u529b\u300d\u3068\u3044\u3046\u8133\u5185\u6d3b\u6027\u30b2\u30fc\u30e0\u306e\u52d5\u753b\u30ea\u30f3\u30af\u3082\u5f15\u304d\u7d9a\u304d\u884c\u3044\u307e\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<div class=\"linkcard\"><div class=\"lkc-external-wrap\"><a class=\"lkc-link no_icon\" href=\"https:\/\/youtu.be\/-ZmAVp_H9rQ\" data-lkc-id=\"153\" 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=youtu.be\" alt=\"\" width=\"16\" height=\"16\" \/><\/div><div class=\"lkc-domain\">YouTube<\/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\/cbd12a76975cd33a8c0173190d07bf8664165612cae2e821c9c6fdc809cb1746.jpeg\" width=\"100px\" height=\"150px\" alt=\"\" \/><\/figure><div class=\"lkc-title\">\u3010R60 redkabagon\u306e\u7279\u6b8a\u80fd\u529b\u3011\u7121\u8ab2\u91d1\u3067\u4e8b\u4ef6\u3092\u89e3\u6c7a!? Sherlock:\u30a2\u30a4\u30c6\u30e0\u63a2\u3057\uff06\u30de\u30c3...<\/div><div class=\"lkc-excerpt\">\u3010R60\u592b\u5a66\u306e\u8133\u5185\u6d3b\u6027\u30ed\u30b0 Vol.6 - Sherlock:\u30a2\u30a4\u30c6\u30e0\u63a2\u3057\uff06\u30de\u30c3\u30c13\u3011R60\u306e\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u304c\u4ef2\u826f\u304f\u8001\u3044\u3066\u3044\u304f\u4e2d\u3001\u4eca\u56de\u306fredkabagon\u306e\u300c\u8133\u5185\u6d3b\u6027\uff08\u30a2\u30f3\u30c1\u30a8\u30a4\u30b8\u30f3\u30b0\uff09\u300d\u3092\u30c6\u30fc\u30de\u306b\u3057\u305f\u30bd\u30ed\u6d3b\u52d5\u306e\u6700\u65b0\u7248\u3092\u304a\u5c4a\u3051\u3057\u307e\u3059\u3002\u4eca\u56de\u306e\u6311\u6226\uff1aSherlock:\u30a2\u30a4\u30c6\u30e0\u63a2\u3057\uff06\u30de\u30c3\u30c13\u52d5\u753b\u306f\u3001redkabagon...<\/div><\/div><div class=\"clear\"><\/div><\/div><\/a><\/div><\/div>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-white-color has-text-color has-background has-link-color wp-elements-351777599343a501c02a392cf747e7d1\" style=\"background-color:#004b76\">IV. YouTube\u52d5\u753b\u516c\u958b\u3068\u30b3\u30fc\u30c9\u516c\u958b<\/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-73a1e455d96e23bd823861ba12cd16ad\" style=\"font-size:20px\">1. \u7b46\u8005\u30af\u30ea\u30a2\u52d5\u753b\u306e\u4e00\u822c\u516c\u958b\u3068\u8aad\u8005\u3078\u306e\u5354\u529b\u4f9d\u983c<\/h3>\n\n\n\n<p>\u3053\u306eAI\u3068\u306e\u5bfe\u6226\u306e\u6a21\u69d8\u306f\u3001\u7b46\u8005\u30af\u30ea\u30a2\u52d5\u753b\u3068\u3057\u3066<strong>\u4e00\u822c\u516c\u958b<\/strong>\u3055\u308c\u3066\u3044\u307e\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\u4e03\u4e26\u3079AI\u3092\u7206\u901f\u958b\u767a\u2192\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u7f60\u3068\u9b3c\u30c7\u30d0\u30c3\u30b0\uff01\" width=\"525\" height=\"295\" src=\"https:\/\/www.youtube.com\/embed\/gl4VV3mfSMc?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<p><strong>\u3010&#x1f4e3;\u7686\u3055\u3093\u306e\u77e5\u8b58\u304c\u5fc5\u8981\u3067\u3059\uff01\u3011<\/strong> \u3053\u306e\u4e03\u4e26\u3079AI\u306f\u3001\u7279\u306bCM\u5074\u306e\u6226\u7565\u8a2d\u5b9a\u306b\u8ab2\u984c\u304c\u6b8b\u3063\u3066\u3044\u307e\u3059\u3002<strong>CM\u306b\u4eba\u9593\u7684\u306a\u6226\u7565\u3092\u6301\u305f\u305b\u308b\u6539\u5584\u6848\u3084\u77e5\u8b58<\/strong>\u3092\u304a\u6301\u3061\u306e\u65b9\u304c\u3044\u3089\u3063\u3057\u3083\u3044\u307e\u3057\u305f\u3089\u3001\u592b\u5a66\u4e8c\u4eba\u3067\u306f\u9650\u754c\u306b\u9054\u3057\u307e\u3057\u305f\u306e\u3067\u3001\u305c\u3072\u30b3\u30e1\u30f3\u30c8\u6b04\u3067\u5171\u6709\u3092\u304a\u9858\u3044\u3044\u305f\u3057\u307e\u3059\uff01<\/p>\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><strong>\u30b8\u30e7\u30fc\u30ab\u30fc\u8a2d\u5b9a\u6642\u30d0\u30b0\u30b3\u30fc\u30c9<\/strong>\u3001<strong>GUI\u306e\u4e0d\u5b89\u5b9a\u8981\u7d20\u306e\u3042\u308b\u30b3\u30fc\u30c9<\/strong>\u3001<strong>\u4e0d\u5b89\u5b9a\u306a\u8981\u7d20\u306f\u7121\u3044\u304cGUI\u306e\u6539\u5584\u304c\u5fc5\u8981\u306a\u30b3\u30fc\u30c9<\/strong><\/strong>\u306e3\u3064\u306e\u6bb5\u968e\u306e\u30b3\u30fc\u30c9\u3092\u7d39\u4ecb\u3057\u307e\u3059\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-5e1d7c900b6eacb577a6e2acbc7cf434\" style=\"font-size:20px\">2. Python\u30b3\u30fc\u30c9\u306e\u516c\u958b\u3068\u30b7\u30ea\u30fc\u30ba\u306e\u7d99\u7d9a<\/h3>\n\n\n\n<p>\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u5b9a\u7fa9\u3084CM\u6226\u7565\u306b\u95a2\u3059\u308b\u8a73\u7d30\u306a\u82e6\u52b4\u3001\u305d\u3057\u3066\u73fe\u5728\u306e<strong>Python\u30b3\u30fc\u30c9<\/strong>\u3092\u3053\u3061\u3089\u306e\u30d6\u30ed\u30b0\u3067\u516c\u958b\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-078100636dda6d71db3b252fb09c258c is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no1(\u30b8\u30e7\u30fc\u30ab\u30fc\u8a2d\u5b9a\u6642\u30d0\u30b0\u30b3\u30fc\u30c9)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>import random\nimport tkinter as tk\nfrom tkinter import messagebox\nfrom tkinter import simpledialog \n\n# ======================================================================\n# A. \u30ab\u30fc\u30c9\u3001\u30c7\u30c3\u30ad\u3001\u30d7\u30ec\u30a4\u30e4\u30fc\u3001\u30d5\u30a3\u30fc\u30eb\u30c9\u3001\u30b2\u30fc\u30e0\u30ed\u30b8\u30c3\u30af (\u5909\u66f4\u306a\u3057)\n# ======================================================================\n\nclass Card:\n    SUITS = &#091;'Spade', 'Heart', 'Diamond', 'Club']\n    RANKS = &#091;'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']\n    RANK_VALUES = {rank: i + 1 for i, rank in enumerate(RANKS)}\n    JOKER_SUIT = 'Joker'\n    JOKER_RANK = 'JK'\n    SUIT_SYMBOLS = {'Spade': '&#x2660;', 'Heart': '&#x2665;', 'Diamond': '&#x2666;', 'Club': '&#x2663;'}\n    def __init__(self, suit_index, rank_index, is_joker=False):\n        self.is_joker = is_joker\n        if is_joker:\n            self.suit = self.JOKER_SUIT\n            self.rank = self.JOKER_RANK\n            self.value = 0\n            self.suit_index = 5 \n        else:\n            self.suit_index = suit_index\n            self.rank_index = rank_index\n            self.suit = self.SUITS&#091;suit_index]\n            self.rank = self.RANKS&#091;rank_index]\n            self.value = self.RANK_VALUES&#091;self.rank]\n            self.symbol = self.SUIT_SYMBOLS.get(self.suit, '')\n    def __str__(self):\n        if self.is_joker: return \"JOKER\"\n        return f\"{self.symbol}{self.rank}\" \n    def __repr__(self):\n        return f\"&lt;Card: {self.__str__()}&gt;\"\n    def __eq__(self, other):\n        if not isinstance(other, Card): return NotImplemented\n        if self.is_joker and other.is_joker: return True\n        if self.is_joker or other.is_joker: return False\n        return self.suit_index == other.suit_index and self.rank_index == other.rank_index\n\nclass Deck:\n    def __init__(self, num_jokers=1):\n        self.num_jokers = num_jokers\n        self.cards = &#091;]\n        self.reset()\n    def reset(self):\n        self.cards = &#091;]\n        for suit_index, suit in enumerate(Card.SUITS):\n            for rank_index, rank in enumerate(Card.RANKS):\n                self.cards.append(Card(suit_index, rank_index))\n        for _ in range(self.num_jokers):\n            self.cards.append(Card(0, 0, is_joker=True)) \n    def shuffle(self):\n        random.shuffle(self.cards)\n    def deal(self, num_cards):\n        if len(self.cards) &lt; num_cards:\n            num_cards = len(self.cards)\n        dealt_cards = self.cards&#091;:num_cards]\n        self.cards = self.cards&#091;num_cards:]\n        return dealt_cards\n        \nclass Player:\n    def __init__(self, name, is_human=False):\n        self.name = name\n        self.hand = &#091;]\n        self.passes_count = 0\n        self.is_human = is_human\n    def receive_cards(self, cards):\n        self.hand.extend(cards)\n        self.hand.sort(key=lambda card: (card.suit_index if not card.is_joker else 5, \n                                        card.value if not card.is_joker else 0)) \n    def remove_card(self, card_to_remove):\n        for i, card in enumerate(self.hand):\n            if card == card_to_remove: \n                del self.hand&#091;i]\n                return True\n        return False\n    def can_play(self, field):\n        for card in self.hand:\n            if card.is_joker or field.is_playable(card):\n                return True\n        return False\n    def get_playable_cards(self, field):\n        playable = &#091;]\n        for card in self.hand:\n            if card.is_joker or field.is_playable(card):\n                playable.append(card)\n        return playable\n\nclass Field:\n    def __init__(self):\n        self.table = {suit: &#091;None] * len(Card.RANKS) for suit in Card.SUITS}\n        self.center_index = Card.RANK_VALUES&#091;'7'] - 1\n    def initialize_sevens(self):\n        for suit in Card.SUITS:\n            self.table&#091;suit]&#091;self.center_index] = True \n    def is_playable(self, card):\n        if card.is_joker: return True\n        suit = card.suit\n        rank_index = card.rank_index\n        if isinstance(self.table&#091;suit]&#091;rank_index], Card): \n            return False \n        if card.value &lt; 7:\n            next_index = rank_index + 1\n            if next_index &lt;= self.center_index: \n                return isinstance(self.table&#091;suit]&#091;next_index], Card)\n        if card.value &gt; 7:\n            prev_index = rank_index - 1\n            if prev_index &gt;= self.center_index:\n                return isinstance(self.table&#091;suit]&#091;prev_index], Card)\n        if card.value == 7:\n             return self.table&#091;suit]&#091;rank_index] is True\n        return False\n    def place_card(self, card):\n        self.table&#091;card.suit]&#091;card.rank_index] = card\n        return True\n\nclass Game:\n    def __init__(self, player_names, max_passes=3, num_jokers=1):\n        self.players = &#091;Player(name, is_human=(name == 'YOU')) for name in player_names]\n        self.num_players = len(self.players)\n        self.deck = Deck(num_jokers=num_jokers)\n        self.field = Field()\n        self.max_passes = max_passes\n        self.current_player_index = -1\n        self.is_running = False\n        self.h7_card = Card(suit_index=1, rank_index=6)\n    def start_game(self):\n        for player in self.players:\n            player.hand = &#091;]\n            player.passes_count = 0\n        self.deck.reset()\n        self.deck.shuffle() \n        total_cards = len(self.deck.cards)\n        cards_per_player = total_cards \/\/ self.num_players\n        remainder = total_cards % self.num_players\n        for i, player in enumerate(self.players):\n            num_to_deal = cards_per_player + (1 if i &lt; remainder else 0)\n            player.receive_cards(self.deck.deal(num_to_deal))\n        self.field = Field()\n        self.field.initialize_sevens()\n        starter_index = -1\n        h7_card_in_hand = None\n        for i, player in enumerate(self.players):\n            for card in player.hand:\n                if card == self.h7_card:\n                    starter_index = i\n                    h7_card_in_hand = card\n                    break\n            if starter_index != -1: break\n        if starter_index == -1: return False\n        self.current_player_index = starter_index\n        self.is_running = True\n        starter = self.players&#091;starter_index]\n        if h7_card_in_hand and starter.remove_card(h7_card_in_hand):\n            self.field.place_card(h7_card_in_hand)\n            starter.hand.sort(key=lambda card: (card.suit_index if not card.is_joker else 5, \n                                                card.value if not card.is_joker else 0))\n        self.current_player_index = (starter_index + 1) % self.num_players\n        return True\n    def get_current_player(self):\n        return self.players&#091;self.current_player_index]\n    def enforce_seven_play(self, seven_card):\n        enforced_plays = &#091;]\n        for p in self.players:\n            if p.name == self.get_current_player().name:\n                 continue \n            for card in p.hand:\n                if card == seven_card:\n                    p.remove_card(card)\n                    self.field.place_card(card) \n                    enforced_plays.append(f\"{p.name} \u304c {seven_card.__str__()} \u3092\u5f37\u5236\u63d0\u793a\")\n                    break \n        return enforced_plays\n    def play_card(self, player, card_to_play, target_card_info=None):\n        if card_to_play not in player.hand: return False, \"\u624b\u672d\u306b\u3042\u308a\u307e\u305b\u3093\"\n        \n        if card_to_play.is_joker:\n            if target_card_info is None: return False, \"\u30b8\u30e7\u30fc\u30ab\u30fc\u306f\u4ee3\u7528\u3059\u308b\u30ab\u30fc\u30c9\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\"\n            target_suit, target_rank_str = target_card_info\n            try:\n                target_rank_index = Card.RANKS.index(target_rank_str)\n                target_suit_index = Card.SUITS.index(target_suit)\n                temp_card = Card(target_suit_index, target_rank_index)\n            except (ValueError, IndexError):\n                return False, \"\u7121\u52b9\u306a\u30b9\u30fc\u30c8\u307e\u305f\u306f\u30e9\u30f3\u30af\u304c\u6307\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002\"\n            \n            suit = temp_card.suit\n            rank_index = temp_card.rank_index\n            field = self.field\n            if isinstance(field.table&#091;suit]&#091;rank_index], Card):\n                return False, f\"\u305d\u306e\u30ab\u30fc\u30c9\uff08{temp_card.__str__()}\uff09\u306f\u65e2\u306b\u51fa\u3066\u3044\u307e\u3059\u3002\"\n            if temp_card.value == 7:\n                if field.table&#091;suit]&#091;rank_index] is not True:\n                    return False, \"7\u306e\u4ee3\u7528\u306f\u3067\u304d\u307e\u305b\u3093\u3002\uff08H7\u4ee5\u5916\u306f\u521d\u671f\u30d5\u30e9\u30b0True\u3067\u3042\u308b\u5fc5\u8981\uff09\"\n            elif not field.is_playable(temp_card):\n                return False, f\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092 {temp_card.__str__()} \u306e\u4ee3\u308f\u308a\u306b\u51fa\u305b\u307e\u305b\u3093\u3002\u96a3\u63a5\u30ab\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002\"\n            \n            player.remove_card(card_to_play) \n            self.field.table&#091;suit]&#091;rank_index] = temp_card \n            \n            forced_msg_list = &#091;]\n            if temp_card.value == 7:\n                forced_msg_list = self.enforce_seven_play(temp_card)\n            base_msg = f\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092 {temp_card.__str__()} \u306e\u4ee3\u308f\u308a\u306b\u51fa\u3057\u307e\u3057\u305f\u3002\"\n            if forced_msg_list:\n                base_msg += \" (\" + \", \".join(forced_msg_list) + \")\"\n            return True, base_msg\n        \n        if not self.field.is_playable(card_to_play):\n            return False, \"\u305d\u306e\u30ab\u30fc\u30c9\u306f\u5834\u306b\u51fa\u305b\u307e\u305b\u3093\u3002\"\n        \n        player.remove_card(card_to_play)\n        self.field.place_card(card_to_play)\n        return True, f\"{card_to_play} \u3092\u51fa\u3057\u307e\u3057\u305f\u3002\"\n        \n    def pass_turn(self, player):\n        if player.can_play(self.field):\n            return False, \"\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308b\u305f\u3081\u3001\u30d1\u30b9\u306f\u3067\u304d\u307e\u305b\u3093\u3002\"\n        player.passes_count += 1\n        if player.passes_count &gt; self.max_passes:\n            return True, f\"{player.name} \u306f\u30d1\u30b9\u5236\u9650\u56de\u6570\u3092\u8d85\u3048\u3001\u8131\u843d\u3057\u307e\u3057\u305f\u3002\"\n        return True, f\"{player.name} \u306f\u30d1\u30b9\u3057\u307e\u3057\u305f\u3002\"\n        \n    def check_winner(self):\n        for player in self.players:\n            if not player.hand:\n                self.is_running = False\n                return player.name\n        active_players = &#091;p for p in self.players if p.passes_count &lt;= self.max_passes and p.hand]\n        if not active_players and self.is_running:\n            self.is_running = False\n            return \"\u5168\u54e1\u304c\u30d1\u30b9\u5236\u9650\u3092\u8d85\u3048\u3001\u30b2\u30fc\u30e0\u7d42\u4e86\u3067\u3059\u3002\"\n        return None\n        \n    def next_turn(self):\n        for _ in range(self.num_players):\n            self.current_player_index = (self.current_player_index + 1) % self.num_players\n            next_player = self.get_current_player()\n            if next_player.passes_count &lt;= self.max_passes and next_player.hand:\n                return True\n            if self.check_winner():\n                return False\n        return False\n\n# ======================================================================\n# B. Tkinter GUI \u30af\u30e9\u30b9\n# ======================================================================\n\nclass SevensGUI:\n    \n    def __init__(self, master):\n        self.master = master\n        master.title(\"\u4e03\u4e26\u3079 (Sevens)\")\n        \n        self.player_names = &#091;\"YOU\", \"COM-A\", \"COM-B\", \"COM-C\"]\n        self.game = Game(self.player_names, max_passes=3, num_jokers=1)\n        \n        # \u30d5\u30a3\u30fc\u30eb\u30c9\u30d5\u30ec\u30fc\u30e0 (\u6700\u4e0a\u90e8)\n        self.field_frame = tk.Frame(master, padx=10, pady=10, bg='#333333') \n        self.field_frame.pack()\n        \n        # \u30b9\u30c6\u30fc\u30bf\u30b9\u30e9\u30d9\u30eb (2\u756a\u76ee)\n        self.status_label = tk.Label(master, text=\"\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\", font=('Arial', 14))\n        self.status_label.pack(pady=5)\n        \n        self.highlight_color = '#FFFFCC' \n        self.default_bg = master.cget('bg') \n        \n        # 3. \u624b\u672d\u3068\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u3092\u683c\u7d0d\u3059\u308b\u30b3\u30f3\u30c6\u30ca (\u4e2d\u592e\u5bc4\u305b)\n        self.hand_control_container = tk.Frame(master, padx=10, pady=10)\n        # \u4e2d\u592e\u5bc4\u305b: fill='none'\u3068anchor='center'\n        self.hand_control_container.pack(fill='none', expand=False, anchor='center') \n        \n        # 3.1 \u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u30d5\u30ec\u30fc\u30e0 (\u30dc\u30bf\u30f3\u3092\u5de6\u306b)\n        self.control_frame = tk.Frame(self.hand_control_container, padx=10, pady=0)\n        self.control_frame.pack(side=tk.LEFT, anchor='n') # LEFT\u306b\u914d\u7f6e\n\n        self.start_button = tk.Button(self.control_frame, text=\"\u30b2\u30fc\u30e0\u30b9\u30bf\u30fc\u30c8\", command=self.start_game, font=('Arial', 12), bg='lightgreen', width=12)\n        self.start_button.pack(pady=5)\n        \n        self.pass_button = tk.Button(self.control_frame, text=\"\u30d1\u30b9\", command=self.handle_pass, font=('Arial', 12), bg='salmon', state=tk.DISABLED, width=12)\n        self.pass_button.pack(pady=5)\n        \n        # 3.2 \u624b\u672d\u30d5\u30ec\u30fc\u30e0 (\u624b\u672d\u3092\u53f3\u306b)\n        self.hand_frame = tk.Frame(self.hand_control_container, padx=0, pady=0, bg=self.default_bg) \n        self.hand_frame.pack(side=tk.RIGHT, fill='none', expand=False, anchor='n') # RIGHT\u306b\u914d\u7f6e\n\n        self.draw_field() \n        self.draw_hand(self.game.players&#091;0]) \n\n    def start_game(self):\n        if self.game.start_game():\n            self.start_button.config(state=tk.DISABLED)\n            self.update_gui()\n            current_player = self.game.get_current_player()\n            if self.game.is_running and not current_player.is_human:\n                self.run_turn()\n            elif self.game.is_running and current_player.is_human:\n                self.pass_button.config(state=tk.NORMAL)\n        else:\n            messagebox.showerror(\"\u30a8\u30e9\u30fc\", \"\u30b2\u30fc\u30e0\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002Heart 7 \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002\")\n\n    def reset_and_start_game(self):\n        self.start_button.config(state=tk.NORMAL, text=\"\u30b2\u30fc\u30e0\u30b9\u30bf\u30fc\u30c8\")\n        self.pass_button.config(state=tk.DISABLED)\n        self.status_label.config(text=\"\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\", fg='black')\n        self.game = Game(self.player_names, max_passes=3, num_jokers=1) \n        self.draw_field()\n        self.draw_hand(self.game.players&#091;0])\n\n    def get_card_color(self, card_str):\n        if '&#x2665;' in card_str or '&#x2666;' in card_str:\n            return 'red', 'mistyrose' \n        elif card_str == 'JOKER':\n            return 'purple', 'yellow'\n        return 'black', 'white'\n\n    def get_card_highlight_color(self, card):\n        if card.is_joker:\n            return 'purple', 'gold' \n        if card.suit == 'Spade':\n            return 'white', '#333399'  \n        elif card.suit == 'Heart':\n            return 'white', '#993333'  \n        elif card.suit == 'Diamond':\n            return 'black', '#FFD700'  \n        elif card.suit == 'Club':\n            return 'white', '#339933'  \n        return 'black', 'lightgray'\n    \n    def draw_field(self):\n        for widget in self.field_frame.winfo_children(): widget.destroy()\n        ranks = Card.RANKS\n        suits = Card.SUITS\n\n        for c, rank in enumerate(ranks):\n            tk.Label(self.field_frame, text=rank, width=6, font=('Arial', 10, 'bold'), bg='#555555', fg='white').grid(row=0, column=c+1)\n\n        for r, suit in enumerate(suits):\n            symbol_fg = 'red' if suit in ('Heart', 'Diamond') else 'white'\n            tk.Label(self.field_frame, text=Card.SUIT_SYMBOLS.get(suit, suit&#091;0]), width=2, \n                     font=('Arial', 18, 'bold'), bg='#555555', fg=symbol_fg).grid(row=r+1, column=0)\n            \n            for c in range(len(ranks)):\n                card_obj = self.game.field.table&#091;suit]&#091;c] if suit in self.game.field.table else None\n                \n                if isinstance(card_obj, Card): \n                    card_str = card_obj.__str__()\n                    fg, bg = self.get_card_color(card_str)\n                else:\n                    if Card.RANKS&#091;c] == '7':\n                        card_str = Card.RANKS&#091;c] \n                        fg, bg = ('black', 'yellow') \n                    else:\n                        card_str = ' ' \n                        fg, bg = ('black', 'white')\n\n                card_label = tk.Label(self.field_frame, text=card_str, width=6, height=3, \n                                      bg=bg, fg=fg, font=('Arial', 12, 'bold'), relief=tk.SUNKEN)\n                card_label.grid(row=r+1, column=c+1, padx=1, pady=1)\n\n    def draw_hand(self, player):\n        for widget in self.hand_frame.winfo_children(): widget.destroy()\n        self.hand_frame.config(bg=self.default_bg) \n        tk.Label(self.hand_frame, text=f\"\u3042\u306a\u305f\u306e\u624b\u672d ({len(player.hand)}\u679a):\", font=('Arial', 10, 'bold')).pack(anchor='w', pady=(0, 5))\n        cards_by_suit = {suit: &#091;] for suit in Card.SUITS}\n        jokers = &#091;]\n        for card in player.hand:\n            if card.is_joker:\n                jokers.append(card)\n            else:\n                cards_by_suit&#091;card.suit].append(card)\n        display_order = &#091;'Spade', 'Heart', 'Diamond', 'Club']\n        CARDS_PER_ROW = 5 \n        for suit in display_order:\n            cards = cards_by_suit&#091;suit]\n            if not cards:\n                continue\n            suit_frame = tk.Frame(self.hand_frame, bg=self.hand_frame.cget('bg'), relief=tk.RIDGE, borderwidth=2) \n            suit_frame.pack(anchor='w', pady=5, padx=0) \n            symbol_frame = tk.Frame(suit_frame, bg=suit_frame.cget('bg'))\n            symbol_frame.pack(side=tk.LEFT, fill='y', padx=(5, 2))\n            symbol = Card.SUIT_SYMBOLS&#091;suit]\n            symbol_fg = 'red' if suit in ('Heart', 'Diamond') else 'black'\n            tk.Label(symbol_frame, text=f\"{symbol}:\", fg=symbol_fg, bg=symbol_frame.cget('bg'), font=('Arial', 14, 'bold'), width=2).pack(pady=(0, 0)) \n            cards_container = tk.Frame(suit_frame, bg=suit_frame.cget('bg'))\n            cards_container.pack(side=tk.LEFT)\n            cards_row_frame = tk.Frame(cards_container, bg=cards_container.cget('bg'))\n            cards_row_frame.pack(anchor='w', pady=1)\n            for i, card in enumerate(cards):\n                if i &gt; 0 and i % CARDS_PER_ROW == 0:\n                    cards_row_frame = tk.Frame(cards_container, bg=cards_container.cget('bg'))\n                    cards_row_frame.pack(anchor='w', pady=1)\n                is_playable = self.game.field.is_playable(card)\n                if is_playable:\n                    fg, bg = self.get_card_highlight_color(card)\n                else:\n                    fg, bg = self.get_card_color(card.__str__())\n                card_button = tk.Button(cards_row_frame, text=card.__str__(), width=4, height=2, \n                                        bg=bg, fg=fg, font=('Arial', 9, 'bold'),\n                                        command=lambda c=card: self.handle_card_click(c))\n                if not is_playable:\n                     card_button.config(state=tk.DISABLED, bg='lightgray', fg='darkgray')\n                if player.is_human and is_playable:\n                     card_button.config(relief=tk.RAISED) \n                card_button.pack(side=tk.LEFT, padx=1) \n        if jokers:\n            joker_frame = tk.Frame(self.hand_frame, bg=self.hand_frame.cget('bg'), relief=tk.RIDGE, borderwidth=2)\n            joker_frame.pack(anchor='w', pady=5, padx=0)\n            symbol_frame = tk.Frame(joker_frame, bg=joker_frame.cget('bg'))\n            symbol_frame.pack(side=tk.LEFT, fill='y', padx=(5, 2))\n            tk.Label(symbol_frame, text=\"JK:\", fg='purple', bg=symbol_frame.cget('bg'), font=('Arial', 14, 'bold'), width=2).pack(pady=(0, 0))\n            cards_container = tk.Frame(joker_frame, bg=joker_frame.cget('bg'))\n            cards_container.pack(side=tk.LEFT)\n            joker_row_frame = tk.Frame(cards_container, bg=cards_container.cget('bg'))\n            joker_row_frame.pack(anchor='w', pady=1)\n            for i, card in enumerate(jokers):\n                if i &gt; 0 and i % CARDS_PER_ROW == 0:\n                     joker_row_frame = tk.Frame(cards_container, bg=cards_container.cget('bg'))\n                     joker_row_frame.pack(anchor='w', pady=1)\n                fg, bg = self.get_card_highlight_color(card)\n                card_button = tk.Button(joker_row_frame, text=card.__str__(), width=4, height=2, \n                                        bg=bg, fg=fg, font=('Arial', 9, 'bold'),\n                                        command=lambda c=card: self.handle_card_click(c))\n                card_button.pack(side=tk.LEFT, padx=1)\n                \n    def update_hand_frame_highlight(self):\n        self.hand_frame.config(bg=self.highlight_color)\n        for widget in self.hand_frame.winfo_children():\n            if isinstance(widget, tk.Label):\n                widget.config(bg=self.highlight_color)\n            elif isinstance(widget, tk.Frame): \n                widget.config(bg=self.highlight_color)\n                for sub_frame in widget.winfo_children():\n                    if isinstance(sub_frame, tk.Frame):\n                        sub_frame.config(bg=self.highlight_color)\n                        for row_frame in sub_frame.winfo_children():\n                             if isinstance(row_frame, tk.Frame):\n                                row_frame.config(bg=self.highlight_color)\n                             if isinstance(row_frame, tk.Label):\n                                row_frame.config(bg=self.highlight_color)\n                    elif isinstance(sub_frame, tk.Label):\n                         sub_frame.config(bg=self.highlight_color)\n\n    def update_gui(self):\n        if not self.game.is_running: \n            self.draw_field()\n            return\n        current_player = self.game.get_current_player()\n        self.draw_field()\n        status_text = f\"\u30bf\u30fc\u30f3: {current_player.name} | \u30d1\u30b9: {current_player.passes_count}\/{self.game.max_passes} | \u624b\u672d: {len(current_player.hand)}\u679a\"\n        self.status_label.config(text=status_text)\n        if current_player.is_human:\n            self.draw_hand(current_player)\n            self.pass_button.config(state=tk.NORMAL)\n            self.update_hand_frame_highlight()\n        else:\n            for widget in self.hand_frame.winfo_children(): widget.destroy()\n            self.pass_button.config(state=tk.DISABLED)\n            self.hand_frame.config(bg=self.default_bg) \n        self.master.update()\n\n    def show_joker_options(self, joker_card):\n        playable_targets = &#091;]\n        field = self.game.field\n        for suit in Card.SUITS:\n            for rank_index in range(len(Card.RANKS)):\n                if not isinstance(field.table&#091;suit]&#091;rank_index], Card):\n                    temp_card = Card(Card.SUITS.index(suit), rank_index)\n                    if field.is_playable(temp_card):\n                        playable_targets.append((suit, Card.RANKS&#091;rank_index], temp_card.__str__()))\n\n        if not playable_targets:\n            messagebox.showinfo(\"\u30b8\u30e7\u30fc\u30ab\u30fc\", \"\u73fe\u5728\u3001\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u4ee3\u7528\u3057\u3066\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002\")\n            return\n\n        joker_window = tk.Toplevel(self.master)\n        joker_window.title(\"\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u4ee3\u7528\u30ab\u30fc\u30c9\u3092\u9078\u629e\")\n        joker_window.transient(self.master)\n        joker_window.grab_set() \n\n        tk.Label(joker_window, text=\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u3069\u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u308f\u308a\u306b\u51fa\u3057\u307e\u3059\u304b\uff1f\", font=('Arial', 10, 'bold')).pack(padx=10, pady=10)\n        button_frame = tk.Frame(joker_window)\n        button_frame.pack(padx=10, pady=5)\n        row = 0\n        col = 0\n        for suit, rank, card_str in playable_targets:\n            fg, bg = self.get_card_color(card_str)\n            btn = tk.Button(button_frame, text=card_str, width=6, height=2, \n                            bg=bg, fg=fg, font=('Arial', 12, 'bold'),\n                            command=lambda s=suit, r=rank, w=joker_window: self.process_joker_choice(joker_card, s, r, w))\n            btn.grid(row=row, column=col, padx=5, pady=5)\n            col += 1\n            if col &gt; 6:\n                col = 0\n                row += 1\n        joker_window.protocol(\"WM_DELETE_WINDOW\", lambda: self.process_joker_choice(joker_card, None, None, joker_window))\n        self.master.wait_window(joker_window)\n\n    def process_joker_choice(self, joker_card, target_suit, target_rank, joker_window):\n        try:\n            joker_window.destroy() \n        except tk.TclError:\n            pass \n        if target_suit is None:\n            self.status_label.config(text=\"YOU \u306e\u79fb\u52d5: \u30b8\u30e7\u30fc\u30ab\u30fc\u4f7f\u7528\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f\", fg='orange')\n            return\n            \n        player = self.game.get_current_player()\n        target_info = (target_suit, target_rank)\n        success, msg = self.game.play_card(player, joker_card, target_info)\n        \n        if success:\n            if \"\u5f37\u5236\u63d0\u793a\" in msg:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='red')\n            else:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='green')\n            self.end_turn()\n        else:\n            messagebox.showerror(\"\u5931\u6557\", msg)\n\n    def handle_card_click(self, card):\n        player = self.game.get_current_player()\n        if not player.is_human: return\n        if card.is_joker:\n            self.show_joker_options(card)\n        else:\n            success, msg = self.game.play_card(player, card)\n            if success:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='green')\n                self.end_turn()\n            else:\n                messagebox.showerror(\"\u5931\u6557\", msg)\n            \n    def handle_pass(self, event=None):\n        player = self.game.get_current_player()\n        if not player.is_human: return\n        success, msg = self.game.pass_turn(player)\n        if success:\n            self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='blue')\n            self.end_turn()\n        else:\n            messagebox.showerror(\"\u30d1\u30b9\u5931\u6557\", msg)\n\n    def end_turn(self):\n        winner = self.game.check_winner()\n        if winner:\n            self.status_label.config(text=f\"&#x1f389; \u52dd\u8005: {winner} &#x1f389;\", fg='red')\n            response = messagebox.askyesno(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", f\"\u52dd\u8005\u306f {winner} \u3067\u3059\uff01\\n\u3082\u3046\u4e00\u5ea6\u30d7\u30ec\u30a4\u3057\u307e\u3059\u304b\uff1f\")\n            if response:\n                self.reset_and_start_game()\n            else:\n                self.pass_button.config(state=tk.DISABLED)\n                self.master.quit()\n            return\n        if self.game.next_turn():\n            self.update_gui()\n            if not self.game.get_current_player().is_human:\n                self.run_turn() \n        else:\n            self.update_gui()\n\n    def run_turn(self):\n        current_player = self.game.get_current_player()\n        if current_player.is_human: return \n        self.master.after(500, lambda: self.ai_move(current_player)) \n\n    def ai_move(self, player):\n        playable_cards = player.get_playable_cards(self.game.field)\n        if playable_cards:\n            non_jokers = &#091;c for c in playable_cards if not c.is_joker]\n            if non_jokers:\n                card_to_play = max(non_jokers, key=lambda c: abs(c.value - 7)) \n                success, msg = self.game.play_card(player, card_to_play)\n            elif playable_cards&#091;0].is_joker:\n                joker = playable_cards&#091;0]\n                target_info = None\n                field = self.game.field\n                candidates = &#091;]\n                for suit in Card.SUITS:\n                    for rank_index in range(len(Card.RANKS)):\n                        if not isinstance(field.table&#091;suit]&#091;rank_index], Card):\n                            temp_card = Card(Card.SUITS.index(suit), rank_index)\n                            if field.is_playable(temp_card):\n                                candidates.append((suit, temp_card.rank))\n                if candidates:\n                    candidates.sort(key=lambda x: abs(Card.RANK_VALUES&#091;x&#091;1]] - 7))\n                    target_suit, target_rank = candidates&#091;0]\n                    target_info = (target_suit, target_rank)\n                if target_info:\n                    success, msg = self.game.play_card(player, joker, target_info)\n                else:\n                    success, msg = self.game.pass_turn(player)\n            else:\n                 success, msg = self.game.pass_turn(player)\n        else:\n            success, msg = self.game.pass_turn(player)\n            \n        if \"\u5f37\u5236\u63d0\u793a\" in msg:\n            self.status_label.config(text=f\"{player.name} \u306e\u79fb\u52d5: {msg}\", fg='red')\n        else:\n            self.status_label.config(text=f\"{player.name} \u306e\u79fb\u52d5: {msg}\", fg='blue')\n            \n        self.master.update()\n        self.master.after(500, self.end_turn)\n\n# ======================================================================\n# C. \u30e1\u30a4\u30f3\u5b9f\u884c\n# ======================================================================\nif __name__ == '__main__':\n    root = tk.Tk()\n    app = SevensGUI(root)\n    root.mainloop()<\/code><\/pre>\n<\/details>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-3923f614f63fc8ca579ff509be6db0d8 is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no2(GUI\u306e\u4e0d\u5b89\u5b9a\u8981\u7d20\u306e\u3042\u308b\u30b3\u30fc\u30c9)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>import random\nimport tkinter as tk\nfrom tkinter import messagebox\nfrom tkinter import simpledialog \n\n# ======================================================================\n# A. \u30ab\u30fc\u30c9\u3001\u30c7\u30c3\u30ad\u3001\u30d7\u30ec\u30a4\u30e4\u30fc\u3001\u30d5\u30a3\u30fc\u30eb\u30c9\u3001\u30b2\u30fc\u30e0\u30ed\u30b8\u30c3\u30af\n# ======================================================================\n\nclass Card:\n    SUITS = &#091;'Spade', 'Heart', 'Diamond', 'Club']\n    RANKS = &#091;'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']\n    RANK_VALUES = {rank: i + 1 for i, rank in enumerate(RANKS)}\n    JOKER_SUIT = 'Joker'\n    JOKER_RANK = 'JK'\n    SUIT_SYMBOLS = {'Spade': '&#x2660;', 'Heart': '&#x2665;', 'Diamond': '&#x2666;', 'Club': '&#x2663;'}\n    def __init__(self, suit_index, rank_index, is_joker=False):\n        self.is_joker = is_joker\n        if is_joker:\n            self.suit = self.JOKER_SUIT\n            self.rank = self.JOKER_RANK\n            self.value = 0\n            self.suit_index = 5 \n        else:\n            self.suit_index = suit_index\n            self.rank_index = rank_index\n            self.suit = self.SUITS&#091;suit_index]\n            self.rank = self.RANKS&#091;rank_index]\n            self.value = self.RANK_VALUES&#091;self.rank]\n            self.symbol = self.SUIT_SYMBOLS.get(self.suit, '')\n    def __str__(self):\n        if self.is_joker: return \"JOKER\"\n        return f\"{self.symbol}{self.rank}\" \n    def __repr__(self):\n        return f\"&lt;Card: {self.__str__}&gt;\"\n    def __eq__(self, other):\n        if not isinstance(other, Card): return NotImplemented\n        if self.is_joker and other.is_joker: return True\n        if self.is_joker or other.is_joker: return False\n        return self.suit_index == other.suit_index and self.rank_index == other.rank_index\n\nclass Deck:\n    def __init__(self, num_jokers=1):\n        self.num_jokers = num_jokers\n        self.cards = &#091;]\n        self.reset()\n    def reset(self):\n        self.cards = &#091;]\n        for suit_index, suit in enumerate(Card.SUITS):\n            for rank_index, rank in enumerate(Card.RANKS):\n                self.cards.append(Card(suit_index, rank_index))\n        for _ in range(self.num_jokers):\n            self.cards.append(Card(0, 0, is_joker=True)) \n    def shuffle(self):\n        random.shuffle(self.cards)\n    def deal(self, num_cards):\n        if len(self.cards) &lt; num_cards:\n            num_cards = len(self.cards)\n        dealt_cards = self.cards&#091;:num_cards]\n        self.cards = self.cards&#091;num_cards:]\n        return dealt_cards\n        \nclass Player:\n    def __init__(self, name, is_human=False):\n        self.name = name\n        self.hand = &#091;]\n        self.passes_count = 0\n        self.is_human = is_human\n    def receive_cards(self, cards):\n        self.hand.extend(cards)\n        self.hand.sort(key=lambda card: (card.suit_index if not card.is_joker else 5, \n                                        card.value if not card.is_joker else 0)) \n    \n    def remove_card(self, card_to_remove):\n        # \u30ab\u30fc\u30c9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u524a\u9664\u3092\u53b3\u5bc6\u306b\u884c\u3046\n        for i, card in enumerate(self.hand):\n            # 1. \u30aa\u30d6\u30b8\u30a7\u30af\u30c8ID\uff08\u30e1\u30e2\u30ea\u4e0a\u306e\u30a2\u30c9\u30ec\u30b9\uff09\u304c\u4e00\u81f4\u3059\u308b\u5834\u5408\u3092\u6700\u512a\u5148\u3067\u524a\u9664\n            if card is card_to_remove: \n                del self.hand&#091;i]\n                return True\n                \n            # 2. \u30ab\u30fc\u30c9\u60c5\u5831\u304c\u4e00\u81f4\u3059\u308b\u5834\u5408 (__eq__ \u306b\u4f9d\u5b58)\n            if card == card_to_remove:\n                del self.hand&#091;i]\n                return True\n                    \n        return False\n    \n    def can_play(self, field):\n        for card in self.hand:\n            if card.is_joker or field.is_playable(card):\n                return True\n        return False\n    def get_playable_cards(self, field):\n        playable = &#091;]\n        for card in self.hand:\n            if card.is_joker or field.is_playable(card):\n                playable.append(card)\n        return playable\n\nclass Field:\n    def __init__(self):\n        # self.table\u306b\u306f\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u5834\u5408\u3001True\u304c\u683c\u7d0d\u3055\u308c\u308b (None\u306f\u7a7a\u306e\u72b6\u614b)\n        self.table = {suit: &#091;None] * len(Card.RANKS) for suit in Card.SUITS}\n        self.center_index = Card.RANK_VALUES&#091;'7'] - 1 # 6\n        \n    def place_card(self, card):\n        \"\"\"\u30ab\u30fc\u30c9\u3092\u5834\u306b\u51fa\u3059\u3002\"\"\"\n        if card.is_joker:\n            return False \n        \n        suit = card.suit\n        rank_index = card.rank_index\n        \n        if self.table&#091;suit]&#091;rank_index] is not None:\n            return False\n            \n        # True\u3092\u683c\u7d0d\u3057\u3001\u305d\u306e\u5834\u6240\u304c\u4f7f\u7528\u6e08\u307f\u3067\u3042\u308b\u3053\u3068\u3092\u793a\u3059\n        self.table&#091;suit]&#091;rank_index] = True\n        return True\n        \n\n    def is_playable(self, card):\n        if card.is_joker: return True\n        suit = card.suit\n        rank_index = card.rank_index\n        \n        # 1. \u3059\u3067\u306b\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u304b\uff1f (True\/None \u3092\u5224\u5b9a)\n        if self.table&#091;suit]&#091;rank_index] is not None: \n            return False \n            \n        # 2. 7 \u306e\u30ab\u30fc\u30c9\u306e\u5834\u5408 \n        if card.value == 7:\n             # self.table&#091;suit]&#091;rank_index] is None \u304c\u65e2\u306b\u78ba\u8a8d\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u5e38\u306b True\n             return True\n             \n        # 3. 7 \u3088\u308a\u5c0f\u3055\u3044\u30ab\u30fc\u30c9 (A, 2, ..., 6)\n        if card.value &lt; 7:\n            next_index = rank_index + 1\n            if next_index &lt;= self.center_index: \n                # \u96a3\u63a5\u30ab\u30fc\u30c9\uff08next_index\uff09\u304c\u300c\u51fa\u3066\u3044\u308b\u300d\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\n                return self.table&#091;suit]&#091;next_index] is not None \n            # 7\u307e\u3067\u306e\u9053\u7b4b\u306b\u96a3\u63a5\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f False\n            return False \n                \n        # 4. 7 \u3088\u308a\u5927\u304d\u3044\u30ab\u30fc\u30c9 (8, 9, ..., K)\n        if card.value &gt; 7:\n            prev_index = rank_index - 1\n            if prev_index &gt;= self.center_index:\n                # \u96a3\u63a5\u30ab\u30fc\u30c9\uff08prev_index\uff09\u304c\u300c\u51fa\u3066\u3044\u308b\u300d\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\n                return self.table&#091;suit]&#091;prev_index] is not None\n            # 7\u307e\u3067\u306e\u9053\u7b4b\u306b\u96a3\u63a5\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f False\n            return False\n                \n        return False\n\nclass Game:\n    def __init__(self, player_names, max_passes=3, num_jokers=1):\n        self.players = &#091;Player(name, is_human=(name == 'YOU')) for name in player_names]\n        self.num_players = len(self.players)\n        self.deck = Deck(num_jokers=num_jokers)\n        self.field = Field()\n        self.max_passes = max_passes\n        self.current_player_index = -1\n        self.is_running = False\n        # Heart 7 \u306e\u30ab\u30fc\u30c9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\n        self.h7_card = Card(suit_index=1, rank_index=6) \n        \n    def start_game(self):\n        for player in self.players:\n            player.hand = &#091;]\n            player.passes_count = 0\n            \n        self.deck.reset()\n        self.deck.shuffle() \n        \n        random.shuffle(self.players) \n        \n        total_cards = len(self.deck.cards)\n        cards_per_player = total_cards \/\/ self.num_players\n        remainder = total_cards % self.num_players\n        \n        for i, player in enumerate(self.players):\n            num_to_deal = cards_per_player + (1 if i &lt; remainder else 0)\n            player.receive_cards(self.deck.deal(num_to_deal))\n            \n        self.field = Field()\n        \n        starter_index = -1\n        h7_card_in_hand = None\n        \n        for i, player in enumerate(self.players):\n            for card in player.hand:\n                if card == self.h7_card:\n                    starter_index = i\n                    h7_card_in_hand = card\n                    break\n            if starter_index != -1: break\n            \n        if starter_index == -1: return False\n        \n        starter = self.players&#091;starter_index]\n        if h7_card_in_hand and starter.remove_card(h7_card_in_hand):\n            # Heart 7 \u3092\u5834\u306b\u51fa\u3059\n            self.field.place_card(h7_card_in_hand)\n            starter.hand.sort(key=lambda card: (card.suit_index if not card.is_joker else 5, \n                                                card.value if not card.is_joker else 0))\n        \n        self.current_player_index = (starter_index + 1) % self.num_players \n        self.is_running = True\n        return True\n\n    def get_current_player(self):\n        return self.players&#091;self.current_player_index]\n        \n    def enforce_seven_play(self, seven_card):\n        enforced_plays = &#091;]\n        for p in self.players:\n            if p.name == self.get_current_player().name:\n                 continue \n            for card in p.hand:\n                if card == seven_card:\n                    p.remove_card(card)\n                    self.field.place_card(card) \n                    enforced_plays.append(f\"{p.name} \u304c {seven_card.__str__()} \u3092\u5f37\u5236\u63d0\u793a\")\n                    break \n        return enforced_plays\n        \n    def play_card(self, player, card_to_play, target_card_info=None):\n        if card_to_play not in player.hand: return False, \"\u624b\u672d\u306b\u3042\u308a\u307e\u305b\u3093\"\n        \n        if card_to_play.is_joker:\n            if target_card_info is None: return False, \"\u30b8\u30e7\u30fc\u30ab\u30fc\u306f\u4ee3\u7528\u3059\u308b\u30ab\u30fc\u30c9\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\"\n            target_suit, target_rank_str = target_card_info\n            try:\n                target_rank_index = Card.RANKS.index(target_rank_str)\n                target_suit_index = Card.SUITS.index(target_suit)\n                temp_card = Card(target_suit_index, target_rank_index)\n            except (ValueError, IndexError):\n                return False, \"\u7121\u52b9\u306a\u30b9\u30fc\u30c8\u307e\u305f\u306f\u30e9\u30f3\u30af\u304c\u6307\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002\"\n            \n            suit = temp_card.suit\n            rank_index = temp_card.rank_index\n            field = self.field\n            \n            # 1. \u65e2\u306b\u51fa\u3066\u3044\u308b\u304b\u306e\u30c1\u30a7\u30c3\u30af\n            if field.table&#091;suit]&#091;rank_index] is not None:\n                return False, f\"\u305d\u306e\u30ab\u30fc\u30c9\uff08{temp_card.__str__()}\uff09\u306f\u65e2\u306b\u51fa\u3066\u3044\u307e\u3059\u3002\"\n            \n            # 2. 7 \u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u7528\u30c1\u30a7\u30c3\u30af\n            if temp_card.value == 7:\n                if temp_card == self.h7_card:\n                     return False, \"Heart 7 \u306e\u4ee3\u7528\u306f\u7981\u6b62\u3055\u308c\u3066\u3044\u307e\u3059\u3002\"\n                # 7\u306e\u30ab\u30fc\u30c9\u306f\u3001\u307e\u3060\u51fa\u3066\u3044\u306a\u3051\u308c\u3070\uff08None\u3067\u3042\u308c\u3070\uff09\u4ee3\u7528\u53ef\u80fd\n                if field.table&#091;suit]&#091;rank_index] is not None:\n                     return False, \"\u305d\u306e7\u306e\u4ee3\u7528\u306f\u3067\u304d\u307e\u305b\u3093\u3002\" \n            \n            # 3. 7 \u4ee5\u5916\u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u7528\u30c1\u30a7\u30c3\u30af\n            elif not field.is_playable(temp_card):\n                return False, f\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092 {temp_card.__str__()} \u306e\u4ee3\u308f\u308a\u306b\u51fa\u305b\u307e\u305b\u3093\u3002\u96a3\u63a5\u30ab\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002\"\n            \n            player.remove_card(card_to_play) \n            \n            # \u30b8\u30e7\u30fc\u30ab\u30fc\u4ee3\u7528\u6642\u3082 True \u3092\u683c\u7d0d\u3059\u308b\n            self.field.table&#091;suit]&#091;rank_index] = True \n            \n            forced_msg_list = &#091;]\n            if temp_card.value == 7:\n                # 7\u306e\u30ab\u30fc\u30c9\u3092\u4ee3\u7528\u3067\u51fa\u3057\u305f\u5834\u5408\u3082\u5f37\u5236\u63d0\u793a\u3092\u30c1\u30a7\u30c3\u30af\n                forced_msg_list = self.enforce_seven_play(temp_card)\n                \n            base_msg = f\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092 {temp_card.__str__()} \u306e\u4ee3\u308f\u308a\u306b\u51fa\u3057\u307e\u3057\u305f\u3002\"\n            if forced_msg_list:\n                base_msg += \" (\" + \", \".join(forced_msg_list) + \")\"\n            return True, base_msg\n        \n        # \u30b8\u30e7\u30fc\u30ab\u30fc\u4ee5\u5916\u306e\u30ab\u30fc\u30c9\u3067\u3001\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308b\u304b\u30c1\u30a7\u30c3\u30af\n        if not self.field.is_playable(card_to_play):\n            return False, \"\u305d\u306e\u30ab\u30fc\u30c9\u306f\u5834\u306b\u51fa\u305b\u307e\u305b\u3093\u3002\"\n        \n        player.remove_card(card_to_play)\n        self.field.place_card(card_to_play)\n        \n        # 7\u306e\u30ab\u30fc\u30c9\u3092\u901a\u5e38\u3067\u51fa\u3057\u305f\u5834\u5408\u3082\u5f37\u5236\u63d0\u793a\u3092\u30c1\u30a7\u30c3\u30af\n        forced_msg_list = &#091;]\n        if card_to_play.value == 7:\n            forced_msg_list = self.enforce_seven_play(card_to_play)\n            \n        base_msg = f\"{card_to_play} \u3092\u51fa\u3057\u307e\u3057\u305f\u3002\"\n        if forced_msg_list:\n            base_msg += \" (\" + \", \".join(forced_msg_list) + \")\"\n        return True, base_msg\n        \n    def pass_turn(self, player):\n        # \u2605\u4fee\u6b63\u7b87\u6240: \u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u3063\u3066\u3082\u30d1\u30b9\u3092\u53ef\u80fd\u306b\u3059\u308b (\u6226\u7565\u7684\u30d1\u30b9\u3092\u8a31\u53ef)\u2605\n        # if player.can_play(self.field):\n        #     return False, \"\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308b\u305f\u3081\u3001\u30d1\u30b9\u306f\u3067\u304d\u307e\u305b\u3093\u3002\"\n\n        player.passes_count += 1\n        if player.passes_count &gt; self.max_passes:\n            return True, f\"{player.name} \u306f\u30d1\u30b9\u5236\u9650\u56de\u6570\u3092\u8d85\u3048\u3001\u8131\u843d\u3057\u307e\u3057\u305f\u3002\"\n        return True, f\"{player.name} \u306f\u30d1\u30b9\u3057\u307e\u3057\u305f\u3002\"\n        \n    def check_winner(self):\n        for player in self.players:\n            if not player.hand:\n                self.is_running = False\n                return player.name\n        active_players = &#091;p for p in self.players if p.passes_count &lt;= self.max_passes and p.hand]\n        if not active_players and self.is_running:\n            self.is_running = False\n            return \"\u5168\u54e1\u304c\u30d1\u30b9\u5236\u9650\u3092\u8d85\u3048\u3001\u30b2\u30fc\u30e0\u7d42\u4e86\u3067\u3059\u3002\"\n        return None\n        \n    def next_turn(self):\n        for _ in range(self.num_players):\n            self.current_player_index = (self.current_player_index + 1) % self.num_players\n            next_player = self.get_current_player()\n            if next_player.passes_count &lt;= self.max_passes and next_player.hand:\n                return True\n            if self.check_winner():\n                return False\n        return False\n\n# ======================================================================\n# B. Tkinter GUI \u30af\u30e9\u30b9\n# ======================================================================\n\nclass SevensGUI:\n    \n    def __init__(self, master):\n        self.master = master\n        master.title(\"\u4e03\u4e26\u3079 (Sevens)\")\n        \n        self.player_names = &#091;\"YOU\", \"COM-A\", \"COM-B\", \"COM-C\"]\n        self.game = Game(self.player_names, max_passes=3, num_jokers=1)\n        \n        self.highlight_color = '#FFFFCC' \n        self.default_bg = master.cget('bg') \n\n        # 1. Top Container: Field + Player Status\n        self.top_container = tk.Frame(master, padx=10, pady=10)\n        self.top_container.pack(side=tk.TOP, fill='x')\n        \n        # 1.1 Field Frame: \u5834\n        self.field_frame = tk.Frame(self.top_container, padx=10, pady=10, bg='#333333') \n        self.field_frame.pack(side=tk.TOP, fill='x', expand=False, pady=(0, 5))\n        \n        # self.status_label \u3092 field_frame \u306e\u4e2d\u3067\u4f7f\u7528\u3059\u308b\u305f\u3081\u3001\u3053\u3053\u3067\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\n        self.status_label = tk.Label(self.field_frame, text=\"\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\", \n                                     font=('Arial', 12), justify=tk.LEFT, anchor='w', \n                                     bg=self.field_frame.cget('bg'), fg='white')\n\n        # 1.2 Player Status Frame: \u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u72b6\u614b\n        self.player_status_frame = tk.Frame(self.top_container, padx=0, pady=0)\n        self.player_status_frame.pack(side=tk.TOP, fill='x', expand=False, pady=(0, 5))\n        \n        # 3. Bottom Frame: Hand + Control Buttons\n        self.bottom_container = tk.Frame(master, padx=10, pady=10)\n        self.bottom_container.pack(side=tk.BOTTOM, fill='both', expand=True) \n        \n        # 3.2 Control Buttons (\u53f3\u5074: \u56fa\u5b9a\u5e45)\n        self.control_frame = tk.Frame(self.bottom_container, padx=10, pady=0, width=150)\n        self.control_frame.grid_propagate(False) \n        self.control_frame.pack(side=tk.RIGHT, fill='y') \n        \n        self.start_button = tk.Button(self.control_frame, text=\"\u30b2\u30fc\u30e0\u30b9\u30bf\u30fc\u30c8\", command=self.start_game, font=('Arial', 12), bg='lightgreen', width=12)\n        self.start_button.pack(pady=5, anchor=tk.N)\n        \n        self.pass_button = tk.Button(self.control_frame, text=\"\u30d1\u30b9\", command=self.handle_pass, font=('Arial', 12), bg='salmon', state=tk.DISABLED, width=12)\n        self.pass_button.pack(pady=5, anchor=tk.N)\n\n        # 3.1 Hand Frame (\u5de6\u5074: \u62e1\u5f35\u53ef\u80fd) - \u30b9\u30af\u30ed\u30fc\u30eb\u53ef\u80fd\u306a\u9818\u57df\u306b\u5909\u66f4\n        self.hand_outer_frame = tk.Frame(self.bottom_container, padx=0, pady=0, bg=self.default_bg)\n        self.hand_outer_frame.pack(side=tk.LEFT, fill='both', expand=True)\n        \n        self.hand_scrollbar = tk.Scrollbar(self.hand_outer_frame, orient=tk.VERTICAL)\n        self.hand_scrollbar.pack(side=tk.RIGHT, fill='y')\n        \n        self.hand_canvas = tk.Canvas(self.hand_outer_frame, yscrollcommand=self.hand_scrollbar.set, bg=self.default_bg, highlightthickness=0)\n        self.hand_canvas.pack(side=tk.LEFT, fill='both', expand=True)\n        \n        self.hand_scrollbar.config(command=self.hand_canvas.yview)\n\n        self.hand_frame = tk.Frame(self.hand_canvas, bg=self.default_bg)\n        self.hand_frame_id = self.hand_canvas.create_window((0, 0), window=self.hand_frame, anchor='nw') \n        \n        self.hand_frame.bind('&lt;Configure&gt;', lambda e: self.hand_canvas.config(scrollregion=self.hand_canvas.bbox(\"all\")))\n        self.hand_canvas.bind('&lt;Configure&gt;', self._on_canvas_configure)\n\n        # \u521d\u671f\u63cf\u753b\n        self.draw_field() \n        self.draw_hand(self.game.players&#091;0]) \n        self.update_status_display() \n        \n    def _on_canvas_configure(self, event):\n        canvas_width = event.width\n        self.hand_canvas.itemconfig(self.hand_frame_id, width=canvas_width)\n\n    def start_game(self):\n        if self.game.start_game():\n            self.start_button.config(state=tk.DISABLED)\n            self.status_label.config(text=\"Heart 7 \u304c\u5834\u306b\u51fa\u3055\u308c\u307e\u3057\u305f\u3002\u30b2\u30fc\u30e0\u958b\u59cb\uff01\", fg='white')\n            self.update_gui()\n            current_player = self.game.get_current_player()\n            if self.game.is_running and not current_player.is_human:\n                self.run_turn()\n            elif self.game.is_running and current_player.is_human:\n                self.pass_button.config(state=tk.NORMAL)\n        else:\n            messagebox.showerror(\"\u30a8\u30e9\u30fc\", \"\u30b2\u30fc\u30e0\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002Heart 7 \u306e\u521d\u671f\u914d\u7f6e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\")\n\n    def reset_and_start_game(self):\n        player_names = &#091;p.name for p in self.game.players]\n        \n        self.start_button.config(state=tk.NORMAL, text=\"\u30b2\u30fc\u30e0\u30b9\u30bf\u30fc\u30c8\")\n        self.pass_button.config(state=tk.DISABLED)\n        self.status_label.config(text=\"\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\", fg='white')\n        self.game = Game(player_names, max_passes=3, num_jokers=1) \n        self.draw_field()\n        self.draw_hand(self.game.players&#091;0])\n        self.update_status_display() \n\n    def update_status_display(self):\n        for widget in self.player_status_frame.winfo_children():\n            widget.destroy()\n\n        if not self.game.players:\n            return\n\n        player_map = {p.name: p for p in self.game.players}\n        display_players = &#091;player_map&#091;name] for name in self.player_names if name in player_map]\n\n        for col, player in enumerate(display_players):\n            player_frame = tk.Frame(self.player_status_frame, padx=10, pady=5, relief=tk.RIDGE, borderwidth=2)\n            player_frame.pack(side=tk.LEFT, padx=5, fill=tk.Y)\n            \n            is_current_player = (player == self.game.get_current_player()) and self.game.is_running\n            name_bg = 'lightblue' if is_current_player else 'lightgray'\n            name_fg = 'black' if is_current_player else 'darkslategray'\n            \n            name_label = tk.Label(player_frame, text=player.name, \n                                  font=('Arial', 12, 'bold'), \n                                  bg=name_bg, fg=name_fg, width=8)\n            name_label.pack(pady=(0, 5))\n\n            hand_text = f\"\u624b\u672d: {len(player.hand)}\u679a\"\n            tk.Label(player_frame, text=hand_text, font=('Arial', 10)).pack()\n            \n            pass_color = 'red' if player.passes_count &gt; self.game.max_passes else 'orange' if player.passes_count &gt;= 2 else 'black'\n            pass_text = f\"\u30d1\u30b9: {player.passes_count}\/{self.game.max_passes}\"\n            tk.Label(player_frame, text=pass_text, font=('Arial', 10, 'bold'), fg=pass_color).pack()\n            \n            if player.passes_count &gt; self.game.max_passes:\n                status_text = \"\u8131\u843d\"\n                tk.Label(player_frame, text=status_text, font=('Arial', 10, 'bold'), fg='red', bg='white').pack(pady=(5,0))\n            elif self.game.is_running and not player.hand:\n                 status_text = \"\u4e0a\u304c\u308a\"\n                 tk.Label(player_frame, text=status_text, font=('Arial', 10, 'bold'), fg='green', bg='white').pack(pady=(5,0))\n\n    def get_card_color(self, card_str):\n        if '&#x2665;' in card_str or '&#x2666;' in card_str:\n            return 'red', 'mistyrose' \n        elif card_str == 'JOKER':\n            return 'purple', 'yellow'\n        return 'black', 'white'\n\n    def get_card_highlight_color(self, card):\n        if card.is_joker:\n            return 'purple', 'gold' \n        \n        if card.value == 7:\n            return 'black', '#FFD700' \n        \n        if card.suit == 'Spade':\n            return 'white', '#1E90FF'  \n        elif card.suit == 'Heart':\n            return 'white', '#DC143C'  \n        elif card.suit == 'Diamond':\n            return 'black', '#FFA500'  \n        elif card.suit == 'Club':\n            return 'white', '#3CB371'  \n        \n        return 'black', 'lightgray'\n    \n    def draw_field(self):\n        for widget in self.field_frame.winfo_children(): \n            if widget is not self.status_label:\n                widget.destroy()\n        \n        ranks = Card.RANKS\n        suits = Card.SUITS\n        NUM_RANKS = len(ranks) \n        NUM_SUITS = len(suits)\n\n        # \u30e9\u30f3\u30af\u8868\u793a (0\u884c\u76ee)\n        for c, rank in enumerate(ranks):\n            # Column 1 \u304b\u3089 Column 13: \u30ab\u30fc\u30c9\u30e9\u30f3\u30af\n            tk.Label(self.field_frame, text=rank, width=6, font=('Arial', 10, 'bold'), bg='#555555', fg='white').grid(row=0, column=c+1)\n\n        # \u30b9\u30fc\u30c8\u30b7\u30f3\u30dc\u30eb\u3068\u30ab\u30fc\u30c9\u672c\u4f53 (1\u884c\u76ee\u304b\u30894\u884c\u76ee)\n        for r, suit in enumerate(suits):\n            # Column 0: \u30b9\u30fc\u30c8\u30b7\u30f3\u30dc\u30eb\n            symbol_fg = 'red' if suit in ('Heart', 'Diamond') else 'white'\n            tk.Label(self.field_frame, text=Card.SUIT_SYMBOLS.get(suit, suit&#091;0]), width=2, \n                     font=('Arial', 18, 'bold'), bg='#555555', fg=symbol_fg).grid(row=r+1, column=0)\n            \n            # Column 1 \u304b\u3089 Column 13: \u30ab\u30fc\u30c9\u672c\u4f53\n            for c in range(NUM_RANKS):\n                card_obj_or_bool = self.game.field.table&#091;suit]&#091;c] if suit in self.game.field.table else None\n                \n                # True\u306e\u5834\u5408\u3082\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u3068\u898b\u306a\u3057\u3066\u63cf\u753b\u3059\u308b\n                if card_obj_or_bool is not None: \n                    # \u5834\u306b\u51fa\u3066\u3044\u308b\u30ab\u30fc\u30c9\u306e\u60c5\u5831\u3092\u53d6\u5f97\n                    card_obj = Card(Card.SUITS.index(suit), c)\n                    card_str = card_obj.__str__()\n                    fg, bg = self.get_card_color(card_str)\n                else:\n                    card_str = ' ' \n                    fg, bg = ('black', 'white')\n\n                card_label = tk.Label(self.field_frame, text=card_str, width=6, height=3, \n                                      bg=bg, fg=fg, font=('Arial', 12, 'bold'), relief=tk.SUNKEN)\n                card_label.grid(row=r+1, column=c+1, padx=1, pady=1)\n        \n        # \u30e1\u30c3\u30bb\u30fc\u30b8\u30e9\u30d9\u30eb\u3092\u30ad\u30f3\u30b0(K)\u306e\u53f3\u306b\u914d\u7f6e (\u5217\u30a4\u30f3\u30c7\u30c3\u30af\u30b9: 1 + NUM_RANKS = 14)\n        self.status_label.grid(row=1, column=NUM_RANKS + 1, padx=10, sticky='nsew', \n                              rowspan=NUM_SUITS) \n        \n        \n        # --- Weight \u306e\u8abf\u6574 ---\n        \n        for c in range(1, NUM_RANKS + 1): \n            self.field_frame.grid_columnconfigure(c, weight=0)\n            \n        self.field_frame.grid_columnconfigure(NUM_RANKS + 1, weight=1) \n        \n        for r in range(NUM_SUITS + 1): \n             self.field_frame.grid_rowconfigure(r, weight=0)\n        # -------------------------------------------\n\n    # \u2605GUI\u6539\u5584\u5f8c\u306e draw_hand \u30e1\u30bd\u30c3\u30c9\u2605\n    def draw_hand(self, player):\n        for widget in self.hand_frame.winfo_children(): widget.destroy()\n        self.hand_frame.config(bg=self.default_bg) \n        \n        # \u30bf\u30a4\u30c8\u30eb\u30e9\u30d9\u30eb\n        tk.Label(self.hand_frame, text=f\"\u3042\u306a\u305f\u306e\u624b\u672d ({len(player.hand)}\u679a):\", \n                 font=('Arial', 10, 'bold')).pack(anchor='w', pady=(0, 5))\n                 \n        cards_by_suit = {suit: &#091;] for suit in Card.SUITS}\n        jokers = &#091;]\n        for card in player.hand:\n            if card.is_joker:\n                jokers.append(card)\n            else:\n                cards_by_suit&#091;card.suit].append(card)\n        display_order = &#091;'Spade', 'Heart', 'Diamond', 'Club']\n        \n        \n        # \u30b9\u30fc\u30c8\u30ab\u30fc\u30c9\u306e\u8868\u793a\n        for suit in display_order:\n            cards = cards_by_suit&#091;suit]\n            if not cards:\n                continue\n            \n            # \u5404\u30b9\u30fc\u30c8\u306e\u30b3\u30f3\u30c6\u30ca\u30d5\u30ec\u30fc\u30e0\n            suit_container_frame = tk.Frame(self.hand_frame, bg=self.hand_frame.cget('bg'), relief=tk.RIDGE, borderwidth=2) \n            suit_container_frame.pack(anchor='w', pady=3, padx=0, fill='x') \n            \n            # \u30b9\u30fc\u30c8\u30b7\u30f3\u30dc\u30eb\u306e\u30e9\u30d9\u30eb (\u5de6\u7aef)\n            symbol_frame = tk.Frame(suit_container_frame, bg=suit_container_frame.cget('bg'))\n            symbol_frame.pack(side=tk.LEFT, fill='y', padx=(5, 5))\n            symbol = Card.SUIT_SYMBOLS&#091;suit]\n            symbol_fg = 'red' if suit in ('Heart', 'Diamond') else 'black'\n            tk.Label(symbol_frame, text=f\"{symbol}:\", fg=symbol_fg, bg=symbol_frame.cget('bg'), \n                     font=('Arial', 14, 'bold'), width=2).pack(pady=0) \n            \n            # \u30ab\u30fc\u30c9\u30dc\u30bf\u30f3\u3092\u914d\u7f6e\u3059\u308b\u305f\u3081\u306e\u5185\u90e8\u30d5\u30ec\u30fc\u30e0\n            cards_frame = tk.Frame(suit_container_frame, bg=suit_container_frame.cget('bg'))\n            cards_frame.pack(side=tk.LEFT, fill='x', expand=True) \n\n            # \u30ab\u30fc\u30c9\u306e\u6298\u308a\u8fd4\u3057\u8868\u793a\n            cards_row_frame = tk.Frame(cards_frame, bg=cards_frame.cget('bg'))\n            cards_row_frame.pack(anchor='w', pady=1, fill='x')\n            \n            CARDS_PER_ROW_FIXED = 13 \n            \n            for i, card in enumerate(cards):\n                if i &gt; 0 and i % CARDS_PER_ROW_FIXED == 0:\n                    # 13\u679a\u3092\u8d85\u3048\u305f\u3089\u65b0\u3057\u3044\u884c\u306b\n                    cards_row_frame = tk.Frame(cards_frame, bg=cards_frame.cget('bg'))\n                    cards_row_frame.pack(anchor='w', pady=1, fill='x')\n\n                is_playable = self.game.field.is_playable(card)\n                \n                if is_playable:\n                    fg, bg = self.get_card_highlight_color(card)\n                else:\n                    fg = 'darkgray'\n                    bg = 'lightgray'\n\n                card_button = tk.Button(cards_row_frame, text=card.__str__(), width=4, height=2, \n                                        bg=bg, fg=fg, font=('Arial', 9, 'bold'),\n                                        command=lambda c=card: self.handle_card_click(c))\n                \n                # \u30b8\u30e7\u30fc\u30ab\u30fc\u4ee5\u5916\u306e\u51fa\u305b\u306a\u3044\u30ab\u30fc\u30c9\u306f\u7121\u52b9\n                if not is_playable and not card.is_joker:\n                     card_button.config(state=tk.DISABLED)\n                     \n                # \u30b8\u30e7\u30fc\u30ab\u30fc\u307e\u305f\u306f\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u306f\u6709\u52b9\n                if player.is_human and (is_playable or card.is_joker):\n                     card_button.config(relief=tk.RAISED) \n                \n                card_button.pack(side=tk.LEFT, padx=1, pady=1) \n        \n        # \u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u8868\u793a\n        if jokers:\n            joker_container_frame = tk.Frame(self.hand_frame, bg=self.hand_frame.cget('bg'), relief=tk.RIDGE, borderwidth=2)\n            joker_container_frame.pack(anchor='w', pady=3, padx=0, fill='x')\n            \n            symbol_frame = tk.Frame(joker_container_frame, bg=joker_container_frame.cget('bg'))\n            symbol_frame.pack(side=tk.LEFT, fill='y', padx=(5, 5))\n            tk.Label(symbol_frame, text=\"JK:\", fg='purple', bg=symbol_frame.cget('bg'), \n                     font=('Arial', 14, 'bold'), width=2).pack(pady=0)\n            \n            cards_frame = tk.Frame(joker_container_frame, bg=joker_container_frame.cget('bg'))\n            cards_frame.pack(side=tk.LEFT, fill='x', expand=True)\n\n            joker_row_frame = tk.Frame(cards_frame, bg=cards_frame.cget('bg'))\n            joker_row_frame.pack(anchor='w', pady=1, fill='x')\n            \n            CARDS_PER_ROW_FIXED = 13 \n            \n            for i, card in enumerate(jokers):\n                if i &gt; 0 and i % CARDS_PER_ROW_FIXED == 0:\n                     joker_row_frame = tk.Frame(cards_frame, bg=cards_frame.cget('bg'))\n                     joker_row_frame.pack(anchor='w', pady=1, fill='x')\n                     \n                fg, bg = self.get_card_highlight_color(card) \n                card_button = tk.Button(joker_row_frame, text=card.__str__(), width=4, height=2, \n                                        bg=bg, fg=fg, font=('Arial', 9, 'bold'),\n                                        command=lambda c=card: self.handle_card_click(c))\n                card_button.pack(side=tk.LEFT, padx=1, pady=1)\n        \n        self.hand_frame.update_idletasks() \n        self.hand_canvas.config(scrollregion=self.hand_canvas.bbox(\"all\"))\n\n    def update_hand_frame_highlight(self):\n        # ... (\u4e2d\u7565 - \u5909\u66f4\u306a\u3057)\n        # \u753b\u9762\u30cf\u30a4\u30e9\u30a4\u30c8\u306e\u30ed\u30b8\u30c3\u30af\u306f sevens-008.py \u3068\u540c\u4e00\n\n        for widget in self.hand_frame.winfo_children():\n            if isinstance(widget, tk.Label):\n                widget.config(bg=self.highlight_color)\n            elif isinstance(widget, tk.Frame): \n                widget.config(bg=self.highlight_color)\n                for sub_frame in widget.winfo_children():\n                    if isinstance(sub_frame, tk.Frame):\n                        sub_frame.config(bg=self.highlight_color)\n                        for row_frame in sub_frame.winfo_children():\n                             if isinstance(row_frame, tk.Frame):\n                                row_frame.config(bg=self.highlight_color)\n                             if isinstance(row_frame, tk.Label):\n                                row_frame.config(bg=self.highlight_color)\n                    elif isinstance(sub_frame, tk.Label):\n                         sub_frame.config(bg=self.highlight_color)\n    \n    def update_gui(self):\n        if not self.game.is_running: \n            self.draw_field()\n            return\n        \n        current_player = self.game.get_current_player()\n        self.draw_field()\n        self.update_status_display() \n\n        if current_player.is_human:\n            self.draw_hand(current_player)\n            # \u2605\u4fee\u6b63: \u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308b\u5834\u5408\u3067\u3082\u30d1\u30b9\u30dc\u30bf\u30f3\u3092\u6709\u52b9\u306e\u307e\u307e\u306b\u3059\u308b (Game.pass_turn \u304c\u4fee\u6b63\u3055\u308c\u3066\u3044\u308b\u305f\u3081)\n            self.pass_button.config(state=tk.NORMAL) \n            self.update_hand_frame_highlight()\n        else:\n            for widget in self.hand_frame.winfo_children(): widget.destroy()\n            self.hand_canvas.config(scrollregion=(0, 0, 0, 0))\n            self.pass_button.config(state=tk.DISABLED)\n            self.hand_outer_frame.config(bg=self.default_bg) \n            self.hand_canvas.config(bg=self.default_bg)\n            self.status_label.config(text=f\"{current_player.name} \u306e\u30bf\u30fc\u30f3\u3067\u3059...\", fg='white')\n            \n        self.master.update()\n        \n    def show_joker_options(self, joker_card):\n        \n        # sevens-008.py \u3068\u540c\u4e00\u306e\u30d0\u30b0\u5bfe\u7b56\u30ed\u30b8\u30c3\u30af (\u8ab0\u306e\u624b\u672d\u306b\u3082\u6b8b\u3063\u3066\u3044\u306a\u3044\u30ab\u30fc\u30c9\u306e\u307f\u5019\u88dc\u306b\u3059\u308b)\n        all_hands_cards = set()\n        for p in self.game.players:\n            for card in p.hand:\n                if not card.is_joker:\n                    all_hands_cards.add((card.suit, card.rank))\n        \n        playable_targets = &#091;]\n        field = self.game.field\n        for suit in Card.SUITS:\n            for rank_index in range(len(Card.RANKS)):\n                temp_card = Card(Card.SUITS.index(suit), rank_index)\n                \n                # 1. \u65e2\u306b\u51fa\u3066\u3044\u308b\u30ab\u30fc\u30c9\u306f\u30b9\u30ad\u30c3\u30d7 \n                if field.table&#091;suit]&#091;rank_index] is not None:\n                    continue\n\n                # 2. Heart 7 \u306f\u4ee3\u7528\u4e0d\u53ef\n                if temp_card == self.game.h7_card:\n                    continue\n                    \n                # 3. \u8ab0\u304b\u306e\u624b\u672d\u306b\u6b8b\u3063\u3066\u3044\u308b\u30ab\u30fc\u30c9\u306f\u4ee3\u7528\u4e0d\u53ef\n                if (temp_card.suit, temp_card.rank) in all_hands_cards:\n                    continue\n\n\n                if temp_card.value == 7:\n                    # \u4ed6\u306e 7 \u306f\u5834\u306b\u51fa\u3066\u3044\u306a\u3051\u308c\u3070\u5e38\u306b\u4ee3\u7528\u53ef\u80fd\n                    playable_targets.append((suit, Card.RANKS&#091;rank_index], temp_card.__str__()))\n                elif field.is_playable(temp_card):\n                    # 7 \u4ee5\u5916\u306e\u30ab\u30fc\u30c9\u306f\u96a3\u63a5\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308c\u3070\u4ee3\u7528\u53ef\u80fd\n                    playable_targets.append((suit, Card.RANKS&#091;rank_index], temp_card.__str__()))\n\n        if not playable_targets:\n            messagebox.showinfo(\"\u30b8\u30e7\u30fc\u30ab\u30fc\", \"\u73fe\u5728\u3001\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u4ee3\u7528\u3057\u3066\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002\")\n            return\n\n        joker_window = tk.Toplevel(self.master)\n        joker_window.title(\"\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u4ee3\u7528\u30ab\u30fc\u30c9\u3092\u9078\u629e\")\n        joker_window.transient(self.master)\n        joker_window.grab_set() \n\n        tk.Label(joker_window, text=\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u3069\u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u308f\u308a\u306b\u51fa\u3057\u307e\u3059\u304b\uff1f\", font=('Arial', 10, 'bold')).pack(padx=10, pady=10)\n        button_frame = tk.Frame(joker_window)\n        button_frame.pack(padx=10, pady=5)\n        row = 0\n        col = 0\n        for suit, rank, card_str in playable_targets:\n            fg, bg = self.get_card_color(card_str)\n            btn = tk.Button(button_frame, text=card_str, width=6, height=2, \n                            bg=bg, fg=fg, font=('Arial', 12, 'bold'),\n                            command=lambda s=suit, r=rank, w=joker_window: self.process_joker_choice(joker_card, s, r, w))\n            btn.grid(row=row, column=col, padx=5, pady=5)\n            col += 1\n            if col &gt; 6:\n                col = 0\n                row += 1\n        joker_window.protocol(\"WM_DELETE_WINDOW\", lambda: self.process_joker_choice(joker_card, None, None, joker_window))\n        self.master.wait_window(joker_window)\n\n    def process_joker_choice(self, joker_card, target_suit, target_rank, joker_window):\n        # ... (\u4e2d\u7565 - \u5909\u66f4\u306a\u3057)\n        try:\n            joker_window.destroy() \n        except tk.TclError:\n            pass \n        if target_suit is None:\n            self.status_label.config(text=\"YOU \u306e\u79fb\u52d5: \u30b8\u30e7\u30fc\u30ab\u30fc\u4f7f\u7528\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f\", fg='orange')\n            return\n            \n        player = self.game.get_current_player()\n        target_info = (target_suit, target_rank)\n        success, msg = self.game.play_card(player, joker_card, target_info)\n        \n        if success:\n            if \"\u5f37\u5236\u63d0\u793a\" in msg:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='red')\n            else:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='green')\n            self.end_turn()\n        else:\n            messagebox.showerror(\"\u5931\u6557\", msg)\n\n    def handle_card_click(self, card):\n        player = self.game.get_current_player()\n        if not player.is_human: return\n        \n        # \u2605\u4fee\u6b63\u7b87\u62401: \u30b8\u30e7\u30fc\u30ab\u30fc\u306f\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u306e\u6709\u7121\u306b\u95a2\u308f\u3089\u305a\u5e38\u306b\u5b9f\u884c\u53ef\u80fd\u3068\u3059\u308b\u2605\n        if card.is_joker:\n            self.show_joker_options(card)\n        else:\n            success, msg = self.game.play_card(player, card)\n            if success:\n                if \"\u5f37\u5236\u63d0\u793a\" in msg:\n                    self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='red')\n                else:\n                    self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='green')\n                self.end_turn()\n            else:\n                 messagebox.showerror(\"\u5931\u6557\", msg)\n\n\n    def handle_pass(self, event=None):\n        player = self.game.get_current_player()\n        if not player.is_human: return\n        \n        # \u2605\u4fee\u6b63\u7b87\u62402: can_play() \u306e\u30c1\u30a7\u30c3\u30af\u3092\u524a\u9664\u3057\u305f\u305f\u3081\u3001\u5e38\u306b\u30d1\u30b9\u3092\u8a66\u307f\u308b\u2605\n        # \u305f\u3060\u3057\u3001GUI\u3067\u306fcan_play\u304c\u306a\u3044\u3068\u30d1\u30b9\u30dc\u30bf\u30f3\u3092\u7121\u52b9\u306b\u3067\u304d\u306a\u3044\u305f\u3081\u3001\n        # can_play()\u304cTrue\u3092\u8fd4\u3059\u5834\u5408\u306fGUI\u5074\u3067\u30dc\u30bf\u30f3\u3092\u7121\u52b9\u5316\u305b\u305a\u3001Game\u5074\u3067\u5e38\u306b\u30d1\u30b9\u3092\u8a31\u53ef\u3059\u308b\u3002\n\n        success, msg = self.game.pass_turn(player)\n        if success:\n            self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='blue')\n            self.end_turn()\n        else:\n            # Game.pass_turn \u304b\u3089 can_play \u306e\u30c1\u30a7\u30c3\u30af\u3092\u524a\u9664\u3057\u305f\u305f\u3081\u3001\u901a\u5e38\u3053\u306e\u30a8\u30e9\u30fc\u306f\u51fa\u307e\u305b\u3093\u3002\n            messagebox.showerror(\"\u30d1\u30b9\u5931\u6557\", msg)\n\n    def end_turn(self):\n        # ... (\u4e2d\u7565 - \u5909\u66f4\u306a\u3057)\n        winner = self.game.check_winner()\n        if winner:\n            self.status_label.config(text=f\"&#x1f389; \u52dd\u8005: {winner} &#x1f389;\", fg='red')\n            self.update_status_display() \n            response = messagebox.askyesno(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", f\"\u52dd\u8005\u306f {winner} \u3067\u3059\uff01\\n\u3082\u3046\u4e00\u5ea6\u30d7\u30ec\u30a4\u3057\u307e\u3059\u304b\uff1f\")\n            if response:\n                self.reset_and_start_game()\n            else:\n                self.pass_button.config(state=tk.DISABLED)\n                self.master.quit()\n            return\n        if self.game.next_turn():\n            self.update_gui()\n            if not self.game.get_current_player().is_human:\n                self.run_turn() \n        else:\n            self.update_gui()\n\n    def run_turn(self):\n        # ... (\u4e2d\u7565 - \u5909\u66f4\u306a\u3057)\n        current_player = self.game.get_current_player()\n        if current_player.is_human: return \n        self.master.after(500, lambda: self.ai_move(current_player)) \n\n    def ai_move(self, player):\n        # ... (\u5f8c\u7565 - AI\u306e\u30ed\u30b8\u30c3\u30af\u306f sevens-008.py \u3068\u540c\u4e00)\n        playable_cards = player.get_playable_cards(self.game.field)\n        \n        target_info = None\n        card_to_play = None\n        \n        if not playable_cards:\n            # \u30d1\u30b9\n            success, msg = self.game.pass_turn(player)\n        else:\n            joker = next((c for c in playable_cards if c.is_joker), None)\n            non_jokers = &#091;c for c in playable_cards if not c.is_joker]\n            \n            if non_jokers:\n                # 7\u304b\u3089\u9060\u3044\u30ab\u30fc\u30c9\u3092\u512a\u5148\u3057\u3066\u51fa\u3059 (\u624b\u672d\u3092\u6e1b\u3089\u3059\u6226\u7565)\n                card_to_play = max(non_jokers, key=lambda c: abs(c.value - 7)) \n                success, msg = self.game.play_card(player, card_to_play)\n            elif joker:\n                # \u30b8\u30e7\u30fc\u30ab\u30fc\u3057\u304b\u51fa\u305b\u306a\u3044\u5834\u5408\n                field = self.game.field\n                \n                # \u5168\u3066\u306e\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u624b\u672d\u306b\u3042\u308b\u30ab\u30fc\u30c9\u306e\u30bb\u30c3\u30c8\u3092\u4f5c\u6210\n                all_hands_cards = set()\n                for p in self.game.players:\n                    for card in p.hand:\n                        if not card.is_joker:\n                             all_hands_cards.add((card.suit, card.rank))\n                \n                candidates = &#091;]\n                for suit in Card.SUITS:\n                    for rank_index in range(len(Card.RANKS)):\n                        temp_card = Card(Card.SUITS.index(suit), rank_index)\n                        \n                        # 1. \u65e2\u306b\u51fa\u3066\u3044\u308b\u304b\uff1f\n                        if field.table&#091;suit]&#091;rank_index] is not None: continue\n                        # 2. Heart 7 \u306e\u4ee3\u7528\u7981\u6b62\n                        if temp_card == self.game.h7_card: continue\n                        \n                        # 3. \u8ab0\u304b\u306e\u624b\u672d\u306b\u6b8b\u3063\u3066\u3044\u308b\u304b\uff1f\n                        if (temp_card.suit, temp_card.rank) in all_hands_cards: continue \n                        \n                        # 4. 7\u307e\u305f\u306f\u96a3\u63a5\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u304b\uff1f\n                        if temp_card.value == 7 or field.is_playable(temp_card):\n                             candidates.append((suit, temp_card.rank))\n                             \n                if candidates:\n                    # 7\u306b\u8fd1\u3044\u30ab\u30fc\u30c9\u3092\u512a\u5148\u3057\u3066\u4ee3\u7528\u3059\u308b (\u5834\u3092\u7e4b\u3052\u308b\u6226\u7565)\n                    candidates.sort(key=lambda x: abs(Card.RANK_VALUES&#091;x&#091;1]] - 7))\n                    target_suit, target_rank = candidates&#091;0]\n                    target_info = (target_suit, target_rank)\n                    \n                    card_to_play = joker\n                    success, msg = self.game.play_card(player, card_to_play, target_info)\n                else:\n                    # \u4ee3\u7528\u3067\u304d\u308b\u30ab\u30fc\u30c9\u304c\u306a\u3044\u5834\u5408\u306f\u30d1\u30b9\n                    success, msg = self.game.pass_turn(player)\n            else:\n                 success, msg = self.game.pass_turn(player) \n\n        \n        if \"\u5f37\u5236\u63d0\u793a\" in msg:\n            self.status_label.config(text=f\"{player.name} \u306e\u79fb\u52d5: {msg}\", fg='red')\n        else:\n            self.status_label.config(text=f\"{player.name} \u306e\u79fb\u52d5: {msg}\", fg='white')\n            \n        self.master.update()\n        self.master.after(500, self.end_turn)\n\n# ======================================================================\n# C. \u30e1\u30a4\u30f3\u5b9f\u884c\n# ======================================================================\nif __name__ == '__main__':\n    root = tk.Tk()\n    app = SevensGUI(root)\n    root.mainloop()<\/code><\/pre>\n<\/details>\n\n\n\n<details class=\"wp-block-details has-black-color has-text-color has-link-color wp-elements-840a1aa417f7c63941da1d586bf44406 is-layout-flow wp-block-details-is-layout-flow\"><summary><strong>\u30d7\u30ed\u30f3\u30d7\u30c8no3(\u4e0d\u5b89\u5b9a\u306a\u8981\u7d20\u306f\u7121\u3044\u304cGUI\u306e\u6539\u5584\u304c\u5fc5\u8981\u306a\u30b3\u30fc\u30c9)<\/strong><\/summary>\n<pre class=\"wp-block-code\"><code>import random\nimport tkinter as tk\nfrom tkinter import messagebox\nfrom tkinter import simpledialog \n\n# ======================================================================\n# A. \u30ab\u30fc\u30c9\u3001\u30c7\u30c3\u30ad\u3001\u30d7\u30ec\u30a4\u30e4\u30fc\u3001\u30d5\u30a3\u30fc\u30eb\u30c9\u3001\u30b2\u30fc\u30e0\u30ed\u30b8\u30c3\u30af\n# ======================================================================\n\nclass Card:\n    SUITS = &#091;'Spade', 'Heart', 'Diamond', 'Club']\n    RANKS = &#091;'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']\n    RANK_VALUES = {rank: i + 1 for i, rank in enumerate(RANKS)}\n    JOKER_SUIT = 'Joker'\n    JOKER_RANK = 'JK'\n    SUIT_SYMBOLS = {'Spade': '&#x2660;', 'Heart': '&#x2665;', 'Diamond': '&#x2666;', 'Club': '&#x2663;'}\n    def __init__(self, suit_index, rank_index, is_joker=False):\n        self.is_joker = is_joker\n        if is_joker:\n            self.suit = self.JOKER_SUIT\n            self.rank = self.JOKER_RANK\n            self.value = 0\n            self.suit_index = 5 \n        else:\n            self.suit_index = suit_index\n            self.rank_index = rank_index\n            self.suit = self.SUITS&#091;suit_index]\n            self.rank = self.RANKS&#091;rank_index]\n            self.value = self.RANK_VALUES&#091;self.rank]\n            self.symbol = self.SUIT_SYMBOLS.get(self.suit, '')\n    def __str__(self):\n        if self.is_joker: return \"JOKER\"\n        return f\"{self.symbol}{self.rank}\" \n    def __repr__(self):\n        return f\"&lt;Card: {self.__str__}&gt;\"\n    def __eq__(self, other):\n        if not isinstance(other, Card): return NotImplemented\n        if self.is_joker and other.is_joker: return True\n        if self.is_joker or other.is_joker: return False\n        return self.suit_index == other.suit_index and self.rank_index == other.rank_index\n\nclass Deck:\n    def __init__(self, num_jokers=1):\n        self.num_jokers = num_jokers\n        self.cards = &#091;]\n        self.reset()\n    def reset(self):\n        self.cards = &#091;]\n        for suit_index, suit in enumerate(Card.SUITS):\n            for rank_index, rank in enumerate(Card.RANKS):\n                self.cards.append(Card(suit_index, rank_index))\n        for _ in range(self.num_jokers):\n            self.cards.append(Card(0, 0, is_joker=True)) \n    def shuffle(self):\n        random.shuffle(self.cards)\n    def deal(self, num_cards):\n        if len(self.cards) &lt; num_cards:\n            num_cards = len(self.cards)\n        dealt_cards = self.cards&#091;:num_cards]\n        self.cards = self.cards&#091;num_cards:]\n        return dealt_cards\n        \nclass Player:\n    def __init__(self, name, is_human=False):\n        self.name = name\n        self.hand = &#091;]\n        self.passes_count = 0\n        self.is_human = is_human\n    def receive_cards(self, cards):\n        self.hand.extend(cards)\n        self.hand.sort(key=lambda card: (card.suit_index if not card.is_joker else 5, \n                                        card.value if not card.is_joker else 0)) \n    \n    def remove_card(self, card_to_remove):\n        # \u30ab\u30fc\u30c9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u524a\u9664\u3092\u53b3\u5bc6\u306b\u884c\u3046\n        for i, card in enumerate(self.hand):\n            # 1. \u30aa\u30d6\u30b8\u30a7\u30af\u30c8ID\uff08\u30e1\u30e2\u30ea\u4e0a\u306e\u30a2\u30c9\u30ec\u30b9\uff09\u304c\u4e00\u81f4\u3059\u308b\u5834\u5408\u3092\u6700\u512a\u5148\u3067\u524a\u9664\n            if card is card_to_remove: \n                del self.hand&#091;i]\n                return True\n                \n            # 2. \u30ab\u30fc\u30c9\u60c5\u5831\u304c\u4e00\u81f4\u3059\u308b\u5834\u5408 (__eq__ \u306b\u4f9d\u5b58)\n            if card == card_to_remove:\n                del self.hand&#091;i]\n                return True\n                    \n        return False\n    \n    def can_play(self, field):\n        for card in self.hand:\n            if card.is_joker or field.is_playable(card):\n                return True\n        return False\n    def get_playable_cards(self, field):\n        playable = &#091;]\n        for card in self.hand:\n            if card.is_joker or field.is_playable(card):\n                playable.append(card)\n        return playable\n\nclass Field:\n    def __init__(self):\n        # self.table\u306b\u306f\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u5834\u5408\u3001True\u304c\u683c\u7d0d\u3055\u308c\u308b (None\u306f\u7a7a\u306e\u72b6\u614b)\n        self.table = {suit: &#091;None] * len(Card.RANKS) for suit in Card.SUITS}\n        self.center_index = Card.RANK_VALUES&#091;'7'] - 1 # 6\n        \n    def place_card(self, card):\n        \"\"\"\u30ab\u30fc\u30c9\u3092\u5834\u306b\u51fa\u3059\u3002\"\"\"\n        if card.is_joker:\n            return False \n        \n        suit = card.suit\n        rank_index = card.rank_index\n        \n        if self.table&#091;suit]&#091;rank_index] is not None:\n            return False\n            \n        # True\u3092\u683c\u7d0d\u3057\u3001\u305d\u306e\u5834\u6240\u304c\u4f7f\u7528\u6e08\u307f\u3067\u3042\u308b\u3053\u3068\u3092\u793a\u3059\n        self.table&#091;suit]&#091;rank_index] = True\n        return True\n        \n\n    def is_playable(self, card):\n        if card.is_joker: return True\n        suit = card.suit\n        rank_index = card.rank_index\n        \n        # 1. \u3059\u3067\u306b\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u304b\uff1f (True\/None \u3092\u5224\u5b9a)\n        if self.table&#091;suit]&#091;rank_index] is not None: \n            return False \n            \n        # 2. 7 \u306e\u30ab\u30fc\u30c9\u306e\u5834\u5408 \n        if card.value == 7:\n             # self.table&#091;suit]&#091;rank_index] is None \u304c\u65e2\u306b\u78ba\u8a8d\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u5e38\u306b True\n             return True\n             \n        # 3. 7 \u3088\u308a\u5c0f\u3055\u3044\u30ab\u30fc\u30c9 (A, 2, ..., 6)\n        if card.value &lt; 7:\n            next_index = rank_index + 1\n            if next_index &lt;= self.center_index: \n                # \u96a3\u63a5\u30ab\u30fc\u30c9\uff08next_index\uff09\u304c\u300c\u51fa\u3066\u3044\u308b\u300d\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\n                return self.table&#091;suit]&#091;next_index] is not None \n            # 7\u307e\u3067\u306e\u9053\u7b4b\u306b\u96a3\u63a5\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f False\n            return False \n                \n        # 4. 7 \u3088\u308a\u5927\u304d\u3044\u30ab\u30fc\u30c9 (8, 9, ..., K)\n        if card.value &gt; 7:\n            prev_index = rank_index - 1\n            if prev_index &gt;= self.center_index:\n                # \u96a3\u63a5\u30ab\u30fc\u30c9\uff08prev_index\uff09\u304c\u300c\u51fa\u3066\u3044\u308b\u300d\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\n                return self.table&#091;suit]&#091;prev_index] is not None\n            # 7\u307e\u3067\u306e\u9053\u7b4b\u306b\u96a3\u63a5\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f False\n            return False\n                \n        return False\n\nclass Game:\n    def __init__(self, player_names, max_passes=3, num_jokers=1):\n        self.players = &#091;Player(name, is_human=(name == 'YOU')) for name in player_names]\n        self.num_players = len(self.players)\n        self.deck = Deck(num_jokers=num_jokers)\n        self.field = Field()\n        self.max_passes = max_passes\n        self.current_player_index = -1\n        self.is_running = False\n        # Heart 7 \u306e\u30ab\u30fc\u30c9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\n        self.h7_card = Card(suit_index=1, rank_index=6) \n        \n    def start_game(self):\n        for player in self.players:\n            player.hand = &#091;]\n            player.passes_count = 0\n            \n        self.deck.reset()\n        self.deck.shuffle() \n        \n        random.shuffle(self.players) \n        \n        total_cards = len(self.deck.cards)\n        cards_per_player = total_cards \/\/ self.num_players\n        remainder = total_cards % self.num_players\n        \n        for i, player in enumerate(self.players):\n            num_to_deal = cards_per_player + (1 if i &lt; remainder else 0)\n            player.receive_cards(self.deck.deal(num_to_deal))\n            \n        self.field = Field()\n        \n        starter_index = -1\n        h7_card_in_hand = None\n        \n        for i, player in enumerate(self.players):\n            for card in player.hand:\n                if card == self.h7_card:\n                    starter_index = i\n                    h7_card_in_hand = card\n                    break\n            if starter_index != -1: break\n            \n        if starter_index == -1: return False\n        \n        starter = self.players&#091;starter_index]\n        if h7_card_in_hand and starter.remove_card(h7_card_in_hand):\n            # Heart 7 \u3092\u5834\u306b\u51fa\u3059\n            self.field.place_card(h7_card_in_hand)\n            starter.hand.sort(key=lambda card: (card.suit_index if not card.is_joker else 5, \n                                                card.value if not card.is_joker else 0))\n        \n        self.current_player_index = (starter_index + 1) % self.num_players \n        self.is_running = True\n        return True\n\n    def get_current_player(self):\n        return self.players&#091;self.current_player_index]\n        \n    def enforce_seven_play(self, seven_card):\n        \"\"\"7\u306e\u30ab\u30fc\u30c9\u304c\u51fa\u305f\u969b\u306b\u3001\u305d\u306e\u30ab\u30fc\u30c9\u3092\u8ab0\u304b\u306e\u624b\u672d\u304b\u3089\u5f37\u5236\u7684\u306b\u5834\u306b\u51fa\u3055\u305b\u308b\uff08\u30d0\u30b0\u5bfe\u7b56\u542b\u3080\uff09\"\"\"\n        enforced_plays = &#091;]\n        \n        # 7\u306e\u30ab\u30fc\u30c9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\uff08\u30b8\u30e7\u30fc\u30ab\u30fc\u4ee3\u7528\u6642\u3082\u6b63\u3057\u3044\u30ab\u30fc\u30c9\u60c5\u5831\u304c\u5fc5\u8981\uff09\n        enforced_card = Card(Card.SUITS.index(seven_card.suit), seven_card.rank_index)\n        \n        for p in self.players:\n            if p.name == self.get_current_player().name:\n                 continue \n            \n            # \u624b\u672d\u306b\u5f37\u5236\u63d0\u793a\u5bfe\u8c61\u306e\u30ab\u30fc\u30c9\u304c\u3042\u308b\u304b\u3092\u78ba\u8a8d\u3057\u3001\u524a\u9664\u3059\u308b\n            for card in p.hand:\n                if card == enforced_card:\n                    p.remove_card(card)\n                    # \u65e2\u306b\u5834\u306b\u51fa\u3066\u3044\u308b\u305f\u3081 Field.place_card \u306f\u4e0d\u8981\u3060\u304c\u3001\n                    # \u30ed\u30b0\u3092\u6b8b\u3059\u305f\u3081 forced_plays \u306b\u8ffd\u52a0\n                    enforced_plays.append(f\"{p.name} \u304c {enforced_card.__str__()} \u3092\u5f37\u5236\u63d0\u793a\")\n                    break \n        return enforced_plays\n        \n    def play_card(self, player, card_to_play, target_card_info=None):\n        if card_to_play not in player.hand: return False, \"\u624b\u672d\u306b\u3042\u308a\u307e\u305b\u3093\"\n        \n        if card_to_play.is_joker:\n            if target_card_info is None: return False, \"\u30b8\u30e7\u30fc\u30ab\u30fc\u306f\u4ee3\u7528\u3059\u308b\u30ab\u30fc\u30c9\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\"\n            target_suit, target_rank_str = target_card_info\n            \n            try:\n                target_rank_index = Card.RANKS.index(target_rank_str)\n                target_suit_index = Card.SUITS.index(target_suit)\n                temp_card = Card(target_suit_index, target_rank_index)\n            except (ValueError, IndexError):\n                return False, \"\u7121\u52b9\u306a\u30b9\u30fc\u30c8\u307e\u305f\u306f\u30e9\u30f3\u30af\u304c\u6307\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002\"\n            \n            suit = temp_card.suit\n            rank_index = temp_card.rank_index\n            field = self.field\n            \n            # 1. \u65e2\u306b\u51fa\u3066\u3044\u308b\u304b\u306e\u30c1\u30a7\u30c3\u30af\n            if field.table&#091;suit]&#091;rank_index] is not None:\n                return False, f\"\u305d\u306e\u30ab\u30fc\u30c9\uff08{temp_card.__str__()}\uff09\u306f\u65e2\u306b\u51fa\u3066\u3044\u307e\u3059\u3002\"\n            \n            # 2. 7 \u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u7528\u30c1\u30a7\u30c3\u30af\n            if temp_card.value == 7:\n                if temp_card == self.h7_card:\n                     return False, \"Heart 7 \u306e\u4ee3\u7528\u306f\u7981\u6b62\u3055\u308c\u3066\u3044\u307e\u3059\u3002\"\n                # 7\u306e\u30ab\u30fc\u30c9\u306f\u3001\u307e\u3060\u51fa\u3066\u3044\u306a\u3051\u308c\u3070\uff08None\u3067\u3042\u308c\u3070\uff09\u4ee3\u7528\u53ef\u80fd\n            \n            # 3. 7 \u4ee5\u5916\u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u7528\u30c1\u30a7\u30c3\u30af\n            elif not field.is_playable(temp_card):\n                return False, f\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092 {temp_card.__str__()} \u306e\u4ee3\u308f\u308a\u306b\u51fa\u305b\u307e\u305b\u3093\u3002\u96a3\u63a5\u30ab\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002\"\n            \n            # \u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u6d88\u8cbb\n            player.remove_card(card_to_play) \n            \n            # \u30b8\u30e7\u30fc\u30ab\u30fc\u4ee3\u7528\u6642\u3082 True \u3092\u683c\u7d0d\u3059\u308b\n            self.field.table&#091;suit]&#091;rank_index] = True \n            \n            forced_msg_list = &#091;]\n            if temp_card.value == 7:\n                # 7\u306e\u30ab\u30fc\u30c9\u3092\u4ee3\u7528\u3067\u51fa\u3057\u305f\u5834\u5408\u3082\u5f37\u5236\u63d0\u793a\u3092\u30c1\u30a7\u30c3\u30af\n                # \u3053\u306e\u3068\u304d\u3001COM\u306e\u624b\u672d\u306b\u6b8b\u3063\u3066\u3044\u305f7\u306e\u30ab\u30fc\u30c9\u306f\u3053\u3053\u3067\u524a\u9664\u3055\u308c\u308b\u305f\u3081\u3001\u6574\u5408\u6027\u304c\u4fdd\u305f\u308c\u307e\u3059\u3002\n                forced_msg_list = self.enforce_seven_play(temp_card)\n                \n            base_msg = f\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092 {temp_card.__str__()} \u306e\u4ee3\u308f\u308a\u306b\u51fa\u3057\u307e\u3057\u305f\u3002\"\n            if forced_msg_list:\n                base_msg += \" (\" + \", \".join(forced_msg_list) + \")\"\n            return True, base_msg\n        \n        # \u30b8\u30e7\u30fc\u30ab\u30fc\u4ee5\u5916\u306e\u30ab\u30fc\u30c9\u3067\u3001\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u3042\u308b\u304b\u30c1\u30a7\u30c3\u30af\n        if not self.field.is_playable(card_to_play):\n            return False, \"\u305d\u306e\u30ab\u30fc\u30c9\u306f\u5834\u306b\u51fa\u305b\u307e\u305b\u3093\u3002\"\n        \n        player.remove_card(card_to_play)\n        self.field.place_card(card_to_play)\n        \n        # 7\u306e\u30ab\u30fc\u30c9\u3092\u901a\u5e38\u3067\u51fa\u3057\u305f\u5834\u5408\u3082\u5f37\u5236\u63d0\u793a\u3092\u30c1\u30a7\u30c3\u30af\n        forced_msg_list = &#091;]\n        if card_to_play.value == 7:\n            forced_msg_list = self.enforce_seven_play(card_to_play)\n            \n        base_msg = f\"{card_to_play} \u3092\u51fa\u3057\u307e\u3057\u305f\u3002\"\n        if forced_msg_list:\n            base_msg += \" (\" + \", \".join(forced_msg_list) + \")\"\n        return True, base_msg\n        \n    def pass_turn(self, player):\n        # \u6226\u7565\u7684\u30d1\u30b9\u3092\u8a31\u53ef\n        player.passes_count += 1\n        if player.passes_count &gt; self.max_passes:\n            return True, f\"{player.name} \u306f\u30d1\u30b9\u5236\u9650\u56de\u6570\u3092\u8d85\u3048\u3001\u8131\u843d\u3057\u307e\u3057\u305f\u3002\"\n        return True, f\"{player.name} \u306f\u30d1\u30b9\u3057\u307e\u3057\u305f\u3002\"\n        \n    def check_winner(self):\n        for player in self.players:\n            if not player.hand:\n                self.is_running = False\n                return player.name\n        active_players = &#091;p for p in self.players if p.passes_count &lt;= self.max_passes and p.hand]\n        if not active_players and self.is_running:\n            self.is_running = False\n            return \"\u5168\u54e1\u304c\u30d1\u30b9\u5236\u9650\u3092\u8d85\u3048\u3001\u30b2\u30fc\u30e0\u7d42\u4e86\u3067\u3059\u3002\"\n        return None\n        \n    def next_turn(self):\n        for _ in range(self.num_players):\n            self.current_player_index = (self.current_player_index + 1) % self.num_players\n            next_player = self.get_current_player()\n            if next_player.passes_count &lt;= self.max_passes and next_player.hand:\n                return True\n            if self.check_winner():\n                return False\n        return False\n\n# ======================================================================\n# B. Tkinter GUI \u30af\u30e9\u30b9\n# ======================================================================\n\nclass SevensGUI:\n    \n    def __init__(self, master):\n        self.master = master\n        master.title(\"\u4e03\u4e26\u3079 (Sevens)\")\n        \n        # GUI\u4fee\u6b631: \u30a6\u30a3\u30f3\u30c9\u30a6\u30b5\u30a4\u30ba\u306e\u6307\u5b9a (1920x1080 \u306b\u53ce\u307e\u308b\u3088\u3046\u8a2d\u5b9a)\n        master.geometry(\"1200x700\") \n        \n        self.player_names = &#091;\"YOU\", \"COM-A\", \"COM-B\", \"COM-C\"]\n        self.game = Game(self.player_names, max_passes=3, num_jokers=1)\n        \n        self.highlight_color = '#FFFFCC' \n        self.default_bg = master.cget('bg') \n\n        # 1. Top Container: Field + Player Status\n        self.top_container = tk.Frame(master, padx=10, pady=10)\n        self.top_container.pack(side=tk.TOP, fill='x')\n        \n        # 1.1 Field Frame: \u5834\n        self.field_frame = tk.Frame(self.top_container, padx=10, pady=10, bg='#333333') \n        self.field_frame.pack(side=tk.TOP, fill='x', expand=False, pady=(0, 5))\n        \n        # self.status_label \u3092 field_frame \u306e\u4e2d\u3067\u4f7f\u7528\u3059\u308b\u305f\u3081\u3001\u3053\u3053\u3067\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\n        self.status_label = tk.Label(self.field_frame, text=\"\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\", \n                                     font=('Arial', 12), justify=tk.LEFT, anchor='w', \n                                     bg=self.field_frame.cget('bg'), fg='white')\n\n        # 1.2 Player Status Frame: \u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u72b6\u614b\n        self.player_status_frame = tk.Frame(self.top_container, padx=0, pady=0)\n        self.player_status_frame.pack(side=tk.TOP, fill='x', expand=False, pady=(0, 5))\n        \n        # 3. Bottom Frame: Hand + Control Buttons (\u753b\u9762\u4e0b\u90e8\u306e\u64cd\u4f5c\u30a8\u30ea\u30a2\u5168\u4f53)\n        self.bottom_container = tk.Frame(master, padx=10, pady=10)\n        self.bottom_container.pack(side=tk.BOTTOM, fill='both', expand=True) \n        \n        # \u2605\u2605\u2605 GUI\u4fee\u6b634: Control Buttons \u3092\u624b\u672d\u30a8\u30ea\u30a2\u306e\u3059\u3050\u4e0a\u306b\u914d\u7f6e \u2605\u2605\u2605\n        self.control_frame = tk.Frame(self.bottom_container, padx=10, pady=0)\n        # \u624b\u672d\u306e\u4e0a\u306b\u6c34\u5e73\u65b9\u5411\u306b\u914d\u7f6e\n        self.control_frame.pack(side=tk.TOP, fill='x', anchor='w') \n        \n        self.start_button = tk.Button(self.control_frame, text=\"\u30b2\u30fc\u30e0\u30b9\u30bf\u30fc\u30c8\", command=self.start_game, font=('Arial', 12), bg='lightgreen', width=12)\n        self.start_button.pack(side=tk.LEFT, pady=5, padx=(0, 10)) # \u5de6\u7aef\u306b\u914d\u7f6e\n        \n        self.pass_button = tk.Button(self.control_frame, text=\"\u30d1\u30b9\", command=self.handle_pass, font=('Arial', 12), bg='salmon', state=tk.DISABLED, width=12)\n        self.pass_button.pack(side=tk.LEFT, pady=5) # \u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u306e\u96a3\u306b\u914d\u7f6e\n\n        # 3.1 Hand Frame (\u4e0b\u5074: \u62e1\u5f35\u53ef\u80fd) - \u6c34\u5e73\u30b9\u30af\u30ed\u30fc\u30eb\u53ef\u80fd\u306a\u9818\u57df\n        self.hand_outer_frame = tk.Frame(self.bottom_container, padx=0, pady=0, bg=self.default_bg)\n        # \u2605\u2605\u2605 GUI\u4fee\u6b634: control_frame \u306e\u4e0b\u306b\u914d\u7f6e \u2605\u2605\u2605\n        self.hand_outer_frame.pack(side=tk.TOP, fill='both', expand=True)\n        \n        # \u30b9\u30af\u30ed\u30fc\u30eb\u30d0\u30fc\u3068\u30ad\u30e3\u30f3\u30d0\u30b9\u306e\u8a2d\u5b9a\u306f\u305d\u306e\u307e\u307e\u7dad\u6301\n        self.hand_scrollbar = tk.Scrollbar(self.hand_outer_frame, orient=tk.HORIZONTAL)\n        self.hand_scrollbar.pack(side=tk.BOTTOM, fill='x')\n        \n        self.hand_canvas = tk.Canvas(self.hand_outer_frame, xscrollcommand=self.hand_scrollbar.set, bg=self.default_bg, highlightthickness=0)\n        self.hand_canvas.pack(side=tk.TOP, fill='both', expand=True)\n        \n        self.hand_scrollbar.config(command=self.hand_canvas.xview)\n\n        # Frame \u306e\u914d\u7f6e\u3092 'nw' \u306b\u8a2d\u5b9a (\u5de6\u4e0a\u57fa\u6e96)\n        self.hand_frame = tk.Frame(self.hand_canvas, bg=self.default_bg)\n        # hand_frame \u306f\u30b3\u30f3\u30c6\u30f3\u30c4\u30b5\u30a4\u30ba\u306b\u5408\u308f\u305b\u3066\u62e1\u5f35\u3057\u3001\u30ad\u30e3\u30f3\u30d0\u30b9\u306b\u57cb\u3081\u8fbc\u3080\n        self.hand_canvas.create_window((0, 0), window=self.hand_frame, anchor='nw') \n        \n        # \u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u30b5\u30a4\u30ba\u304c\u5909\u308f\u3063\u305f\u3089\u30b9\u30af\u30ed\u30fc\u30eb\u9818\u57df\u3092\u66f4\u65b0\n        self.hand_frame.bind('&lt;Configure&gt;', lambda e: self.hand_canvas.config(scrollregion=self.hand_canvas.bbox(\"all\")))\n\n        # \u521d\u671f\u63cf\u753b\n        self.draw_field() \n        self.draw_hand(self.game.players&#091;0]) \n        self.update_status_display() \n        \n    def _on_canvas_configure(self, event):\n        # \u6c34\u5e73\u30b9\u30af\u30ed\u30fc\u30eb\u306b\u5909\u66f4\u3057\u305f\u305f\u3081\u3001\u3053\u306e\u30e1\u30bd\u30c3\u30c9\u306f\u4e0d\u8981\n        pass\n\n    def start_game(self):\n        if self.game.start_game():\n            self.start_button.config(state=tk.DISABLED)\n            self.status_label.config(text=\"Heart 7 \u304c\u5834\u306b\u51fa\u3055\u308c\u307e\u3057\u305f\u3002\u30b2\u30fc\u30e0\u958b\u59cb\uff01\", fg='white')\n            self.update_gui()\n            current_player = self.game.get_current_player()\n            if self.game.is_running and not current_player.is_human:\n                self.run_turn()\n            elif self.game.is_running and current_player.is_human:\n                self.pass_button.config(state=tk.NORMAL)\n        else:\n            messagebox.showerror(\"\u30a8\u30e9\u30fc\", \"\u30b2\u30fc\u30e0\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002Heart 7 \u306e\u521d\u671f\u914d\u7f6e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\")\n\n    def reset_and_start_game(self):\n        player_names = &#091;p.name for p in self.game.players]\n        \n        self.start_button.config(state=tk.NORMAL, text=\"\u30b2\u30fc\u30e0\u30b9\u30bf\u30fc\u30c8\")\n        self.pass_button.config(state=tk.DISABLED)\n        self.status_label.config(text=\"\u30b9\u30bf\u30fc\u30c8\u30dc\u30bf\u30f3\u3092\u62bc\u3057\u3066\u304f\u3060\u3055\u3044\", fg='white')\n        self.game = Game(player_names, max_passes=3, num_jokers=1) \n        self.draw_field()\n        self.draw_hand(self.game.players&#091;0])\n        self.update_status_display() \n\n    def update_status_display(self):\n        for widget in self.player_status_frame.winfo_children():\n            widget.destroy()\n\n        if not self.game.players:\n            return\n\n        player_map = {p.name: p for p in self.game.players}\n        display_players = &#091;player_map&#091;name] for name in self.player_names if name in player_map]\n\n        for col, player in enumerate(display_players):\n            player_frame = tk.Frame(self.player_status_frame, padx=10, pady=5, relief=tk.RIDGE, borderwidth=2)\n            player_frame.pack(side=tk.LEFT, padx=5, fill=tk.Y)\n            \n            is_current_player = (player == self.game.get_current_player()) and self.game.is_running\n            name_bg = 'lightblue' if is_current_player else 'lightgray'\n            name_fg = 'black' if is_current_player else 'darkslategray'\n            \n            name_label = tk.Label(player_frame, text=player.name, \n                                  font=('Arial', 12, 'bold'), \n                                  bg=name_bg, fg=name_fg, width=8)\n            name_label.pack(pady=(0, 5))\n\n            hand_text = f\"\u624b\u672d: {len(player.hand)}\u679a\"\n            tk.Label(player_frame, text=hand_text, font=('Arial', 10)).pack()\n            \n            pass_color = 'red' if player.passes_count &gt; self.game.max_passes else 'orange' if player.passes_count &gt;= 2 else 'black'\n            pass_text = f\"\u30d1\u30b9: {player.passes_count}\/{self.game.max_passes}\"\n            tk.Label(player_frame, text=pass_text, font=('Arial', 10, 'bold'), fg=pass_color).pack()\n            \n            if player.passes_count &gt; self.game.max_passes:\n                status_text = \"\u8131\u843d\"\n                tk.Label(player_frame, text=status_text, font=('Arial', 10, 'bold'), fg='red', bg='white').pack(pady=(5,0))\n            elif self.game.is_running and not player.hand:\n                 status_text = \"\u4e0a\u304c\u308a\"\n                 tk.Label(player_frame, text=status_text, font=('Arial', 10, 'bold'), fg='green', bg='white').pack(pady=(5,0))\n\n    def get_card_color(self, card_str):\n        if '&#x2665;' in card_str or '&#x2666;' in card_str:\n            return 'red', 'mistyrose' \n        elif card_str == 'JOKER':\n            return 'purple', 'yellow'\n        return 'black', 'white'\n\n    def get_card_highlight_color(self, card):\n        if card.is_joker:\n            return 'purple', 'gold' \n        \n        if card.value == 7:\n            return 'black', '#FFD700' \n        \n        if card.suit == 'Spade':\n            return 'white', '#1E90FF'  \n        elif card.suit == 'Heart':\n            return 'white', '#DC143C'  \n        elif card.suit == 'Diamond':\n            return 'black', '#FFA500'  \n        elif card.suit == 'Club':\n            return 'white', '#3CB371'  \n        \n        return 'black', 'lightgray'\n    \n    def draw_field(self):\n        for widget in self.field_frame.winfo_children(): \n            if widget is not self.status_label:\n                widget.destroy()\n        \n        ranks = Card.RANKS\n        suits = Card.SUITS\n        NUM_RANKS = len(ranks) \n        NUM_SUITS = len(suits)\n\n        # \u30e9\u30f3\u30af\u8868\u793a (0\u884c\u76ee)\n        for c, rank in enumerate(ranks):\n            # Column 1 \u304b\u3089 Column 13: \u30ab\u30fc\u30c9\u30e9\u30f3\u30af\n            tk.Label(self.field_frame, text=rank, width=6, font=('Arial', 10, 'bold'), bg='#555555', fg='white').grid(row=0, column=c+1)\n\n        # \u30b9\u30fc\u30c8\u30b7\u30f3\u30dc\u30eb\u3068\u30ab\u30fc\u30c9\u672c\u4f53 (1\u884c\u76ee\u304b\u30894\u884c\u76ee)\n        for r, suit in enumerate(suits):\n            # Column 0: \u30b9\u30fc\u30c8\u30b7\u30f3\u30dc\u30eb\n            symbol_fg = 'red' if suit in ('Heart', 'Diamond') else 'white'\n            tk.Label(self.field_frame, text=Card.SUIT_SYMBOLS.get(suit, suit&#091;0]), width=2, \n                     font=('Arial', 18, 'bold'), bg='#555555', fg=symbol_fg).grid(row=r+1, column=0)\n            \n            # Column 1 \u304b\u3089 Column 13: \u30ab\u30fc\u30c9\u672c\u4f53\n            for c in range(NUM_RANKS):\n                card_obj_or_bool = self.game.field.table&#091;suit]&#091;c] if suit in self.game.field.table else None\n                \n                # True\u306e\u5834\u5408\u3082\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u3068\u898b\u306a\u3057\u3066\u63cf\u753b\u3059\u308b\n                if card_obj_or_bool is not None: \n                    # \u5834\u306b\u51fa\u3066\u3044\u308b\u30ab\u30fc\u30c9\u306e\u60c5\u5831\u3092\u53d6\u5f97\n                    card_obj = Card(Card.SUITS.index(suit), c)\n                    card_str = card_obj.__str__()\n                    fg, bg = self.get_card_color(card_str)\n                else:\n                    card_str = ' ' \n                    fg, bg = ('black', 'white')\n\n                # GUI\u4fee\u6b632: height=2 \u306b\u5909\u66f4\u3057\u3001\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u7e26\u5e45\u3092\u7e2e\u5c0f\n                card_label = tk.Label(self.field_frame, text=card_str, width=6, height=2, \n                                      bg=bg, fg=fg, font=('Arial', 12, 'bold'), relief=tk.SUNKEN)\n                card_label.grid(row=r+1, column=c+1, padx=1, pady=1)\n        \n        # \u30e1\u30c3\u30bb\u30fc\u30b8\u30e9\u30d9\u30eb\u3092\u30ad\u30f3\u30b0(K)\u306e\u53f3\u306b\u914d\u7f6e (\u5217\u30a4\u30f3\u30c7\u30c3\u30af\u30b9: 1 + NUM_RANKS = 14)\n        self.status_label.grid(row=1, column=NUM_RANKS + 1, padx=10, sticky='nsew', \n                              rowspan=NUM_SUITS) \n        \n        \n        # --- Weight \u306e\u8abf\u6574 ---\n        \n        for c in range(1, NUM_RANKS + 1): \n            self.field_frame.grid_columnconfigure(c, weight=0)\n            \n        self.field_frame.grid_columnconfigure(NUM_RANKS + 1, weight=1) \n        \n        for r in range(NUM_SUITS + 1): \n             self.field_frame.grid_rowconfigure(r, weight=0)\n        # -------------------------------------------\n\n    def draw_hand(self, player):\n        for widget in self.hand_frame.winfo_children(): widget.destroy()\n        self.hand_frame.config(bg=self.default_bg) \n        \n        # \u30bf\u30a4\u30c8\u30eb\u30e9\u30d9\u30eb\n        tk.Label(self.hand_frame, text=f\"\u3042\u306a\u305f\u306e\u624b\u672d ({len(player.hand)}\u679a):\", \n                 font=('Arial', 10, 'bold')).pack(anchor='w', pady=(0, 5), padx=5)\n                 \n        cards_by_suit = {suit: &#091;] for suit in Card.SUITS}\n        jokers = &#091;]\n        for card in player.hand:\n            if card.is_joker:\n                jokers.append(card)\n            else:\n                cards_by_suit&#091;card.suit].append(card)\n        display_order = &#091;'Spade', 'Heart', 'Diamond', 'Club']\n        \n        # GUI\u4fee\u6b633: \u5168\u30b9\u30fc\u30c8\u306e\u30ab\u30fc\u30c9\u3092\u683c\u7d0d\u3059\u308b\u5358\u4e00\u306e\u30d5\u30ec\u30fc\u30e0 (\u6c34\u5e73\u30b9\u30af\u30ed\u30fc\u30eb\u3055\u305b\u308b\u5bfe\u8c61)\n        self.all_cards_frame = tk.Frame(self.hand_frame, bg=self.hand_frame.cget('bg'))\n        self.all_cards_frame.pack(anchor='w', fill='x', pady=0)\n\n        # \u30b9\u30fc\u30c8\u30ab\u30fc\u30c9\u306e\u8868\u793a\n        for suit in display_order:\n            cards = cards_by_suit&#091;suit]\n            if not cards:\n                continue\n            \n            # \u5404\u30b9\u30fc\u30c8\u306e\u30b3\u30f3\u30c6\u30ca\u30d5\u30ec\u30fc\u30e0\n            # GUI\u4fee\u6b633: all_cards_frame \u306b\u6a2a\u4e26\u3073\u3067\u914d\u7f6e (side=tk.LEFT)\n            suit_container_frame = tk.Frame(self.all_cards_frame, bg=self.all_cards_frame.cget('bg'), relief=tk.RIDGE, borderwidth=2) \n            suit_container_frame.pack(side=tk.LEFT, pady=3, padx=5, fill=tk.Y) \n            \n            # \u30b9\u30fc\u30c8\u30b7\u30f3\u30dc\u30eb\u306e\u30e9\u30d9\u30eb (\u4e0a\u7aef)\n            symbol_frame = tk.Frame(suit_container_frame, bg=suit_container_frame.cget('bg'))\n            symbol_frame.pack(side=tk.TOP, fill='x', padx=5)\n            symbol = Card.SUIT_SYMBOLS&#091;suit]\n            symbol_fg = 'red' if suit in ('Heart', 'Diamond') else 'black'\n            tk.Label(symbol_frame, text=f\"{symbol}:\", fg=symbol_fg, bg=symbol_frame.cget('bg'), \n                     font=('Arial', 14, 'bold')).pack(side=tk.LEFT, pady=0) \n            \n            # \u30ab\u30fc\u30c9\u30dc\u30bf\u30f3\u3092\u914d\u7f6e\u3059\u308b\u305f\u3081\u306e\u5185\u90e8\u30d5\u30ec\u30fc\u30e0 (\u7e26\u65b9\u5411\u306b\u30b9\u30bf\u30c3\u30af)\n            cards_frame = tk.Frame(suit_container_frame, bg=suit_container_frame.cget('bg'))\n            cards_frame.pack(side=tk.TOP, fill='y', expand=True) \n\n            for i, card in enumerate(cards):\n\n                is_playable = self.game.field.is_playable(card)\n                \n                if is_playable:\n                    fg, bg = self.get_card_highlight_color(card)\n                else:\n                    fg = 'darkgray'\n                    bg = 'lightgray'\n\n                # GUI\u4fee\u6b633: width=3, height=1 \u306b\u7e2e\u5c0f\n                card_button = tk.Button(cards_frame, text=card.__str__(), width=3, height=1, \n                                        bg=bg, fg=fg, font=('Arial', 9, 'bold'),\n                                        command=lambda c=card: self.handle_card_click(c))\n                \n                if not is_playable and not card.is_joker:\n                     card_button.config(state=tk.DISABLED)\n                     \n                if player.is_human and (is_playable or card.is_joker):\n                     card_button.config(relief=tk.RAISED) \n                \n                card_button.pack(side=tk.TOP, padx=1, pady=1) # \u7e26\u65b9\u5411\u306b\u914d\u7f6e\n        \n        # \u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u8868\u793a\n        if jokers:\n            # GUI\u4fee\u6b633: all_cards_frame \u306b\u6a2a\u4e26\u3073\u3067\u914d\u7f6e (side=tk.LEFT)\n            joker_container_frame = tk.Frame(self.all_cards_frame, bg=self.all_cards_frame.cget('bg'), relief=tk.RIDGE, borderwidth=2)\n            joker_container_frame.pack(side=tk.LEFT, pady=3, padx=5, fill=tk.Y)\n            \n            symbol_frame = tk.Frame(joker_container_frame, bg=joker_container_frame.cget('bg'))\n            symbol_frame.pack(side=tk.TOP, fill='x', padx=5)\n            tk.Label(symbol_frame, text=\"JK:\", fg='purple', bg=symbol_frame.cget('bg'), \n                     font=('Arial', 14, 'bold')).pack(side=tk.LEFT, pady=0)\n            \n            cards_frame = tk.Frame(joker_container_frame, bg=joker_container_frame.cget('bg'))\n            cards_frame.pack(side=tk.TOP, fill='y', expand=True)\n\n            for i, card in enumerate(jokers):\n                     \n                fg, bg = self.get_card_highlight_color(card) \n                # GUI\u4fee\u6b633: width=3, height=1 \u306b\u7e2e\u5c0f\n                card_button = tk.Button(cards_frame, text=card.__str__(), width=3, height=1, \n                                        bg=bg, fg=fg, font=('Arial', 9, 'bold'),\n                                        command=lambda c=card: self.handle_card_click(c))\n                card_button.pack(side=tk.TOP, padx=1, pady=1) # \u7e26\u65b9\u5411\u306b\u914d\u7f6e\n        \n        self.hand_frame.update_idletasks() \n        # GUI\u4fee\u6b633: scrollregion \u3092\u66f4\u65b0\u3057\u3066\u6c34\u5e73\u30b9\u30af\u30ed\u30fc\u30eb\u3092\u53ef\u80fd\u306b\u3059\u308b\n        self.hand_canvas.config(scrollregion=self.hand_canvas.bbox(\"all\"))\n\n    def update_hand_frame_highlight(self):\n        # \u73fe\u5728\u306e\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u30bf\u30fc\u30f3\u3067\u3042\u308b\u3053\u3068\u3092\u793a\u3059\u305f\u3081\u3001\u624b\u672d\u30d5\u30ec\u30fc\u30e0\u3092\u30cf\u30a4\u30e9\u30a4\u30c8\n        current_player = self.game.get_current_player()\n        if not current_player.is_human: return\n        \n        # self.hand_frame \u306e\u76f4\u4e0b\u306b\u3042\u308b\u30a6\u30a3\u30b8\u30a7\u30c3\u30c8\uff08\u30bf\u30a4\u30c8\u30eb\u30e9\u30d9\u30eb\u3068 self.all_cards_frame\uff09\u3092\u30cf\u30a4\u30e9\u30a4\u30c8\n        for widget in self.hand_frame.winfo_children():\n            # Frame\u306e\u5834\u5408\u3001\u518d\u5e30\u7684\u306b\u30cf\u30a4\u30e9\u30a4\u30c8\u3092\u9069\u7528\n            if isinstance(widget, tk.Frame):\n                self._highlight_frame_recursively(widget)\n            elif isinstance(widget, tk.Label): # \u30bf\u30a4\u30c8\u30eb\u30e9\u30d9\u30eb\n                widget.config(bg=self.highlight_color)\n            \n    def _highlight_frame_recursively(self, frame):\n        frame.config(bg=self.highlight_color)\n        for child in frame.winfo_children():\n            if isinstance(child, tk.Frame):\n                self._highlight_frame_recursively(child)\n            elif isinstance(child, tk.Label):\n                child.config(bg=self.highlight_color)\n\n    def update_gui(self):\n        if not self.game.is_running: \n            self.draw_field()\n            return\n        \n        current_player = self.game.get_current_player()\n        self.draw_field()\n        self.update_status_display() \n\n        if current_player.is_human:\n            self.draw_hand(current_player)\n            self.pass_button.config(state=tk.NORMAL) \n            self.update_hand_frame_highlight()\n        else:\n            # COM\u306e\u30bf\u30fc\u30f3\u4e2d\u306f\u624b\u672d\u8868\u793a\u3092\u975e\u8868\u793a\u306b\n            for widget in self.hand_frame.winfo_children(): widget.destroy()\n            self.hand_canvas.config(scrollregion=(0, 0, 0, 0))\n            self.pass_button.config(state=tk.DISABLED)\n            self.hand_outer_frame.config(bg=self.default_bg) \n            self.hand_canvas.config(bg=self.default_bg)\n            self.status_label.config(text=f\"{current_player.name} \u306e\u30bf\u30fc\u30f3\u3067\u3059...\", fg='white')\n            \n        self.master.update()\n        \n    def show_joker_options(self, joker_card):\n        # \u30d7\u30ec\u30a4\u30e4\u30fc\u304c\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u30af\u30ea\u30c3\u30af\u3057\u305f\u5834\u5408\u306b\u547c\u3070\u308c\u307e\u3059\u3002\n        \n        playable_targets = &#091;]\n        field = self.game.field\n        \n        for suit in Card.SUITS:\n            for rank_index in range(len(Card.RANKS)):\n                temp_card = Card(Card.SUITS.index(suit), rank_index)\n                \n                # 1. \u65e2\u306b\u51fa\u3066\u3044\u308b\u30ab\u30fc\u30c9\u306f\u30b9\u30ad\u30c3\u30d7 \n                if field.table&#091;suit]&#091;rank_index] is not None:\n                    continue\n\n                # 2. Heart 7 \u306f\u4ee3\u7528\u4e0d\u53ef\n                if temp_card == self.game.h7_card:\n                    continue\n                    \n                # 3. \u4ee3\u7528\u53ef\u80fd\u304b\u3069\u3046\u304b\u306e\u30c1\u30a7\u30c3\u30af (7\u306e\u30ab\u30fc\u30c9\u3001\u307e\u305f\u306f\u96a3\u63a5\u30ab\u30fc\u30c9)\n                if temp_card.value == 7 or field.is_playable(temp_card):\n                    # \u30d0\u30b0\u4fee\u6b63: \u8ab0\u306e\u624b\u672d\u306b\u3042\u3063\u3066\u3082\u4ee3\u7528\u5019\u88dc\u306b\u542b\u3081\u308b\n                    playable_targets.append((suit, Card.RANKS&#091;rank_index], temp_card.__str__()))\n\n        if not playable_targets:\n            messagebox.showinfo(\"\u30b8\u30e7\u30fc\u30ab\u30fc\", \"\u73fe\u5728\u3001\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u4ee3\u7528\u3057\u3066\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u304c\u5834\u306b\u3042\u308a\u307e\u305b\u3093\u3002\uff08\u65e2\u306b\u51fa\u3066\u3044\u308b\u30ab\u30fc\u30c9\u3001\u307e\u305f\u306f Heart 7 \u3092\u9664\u304f\uff09\")\n            return\n\n        joker_window = tk.Toplevel(self.master)\n        joker_window.title(\"\u30b8\u30e7\u30fc\u30ab\u30fc\u306e\u4ee3\u7528\u30ab\u30fc\u30c9\u3092\u9078\u629e\")\n        joker_window.transient(self.master)\n        joker_window.grab_set() \n\n        tk.Label(joker_window, text=\"\u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u3069\u306e\u30ab\u30fc\u30c9\u306e\u4ee3\u308f\u308a\u306b\u51fa\u3057\u307e\u3059\u304b\uff1f\", font=('Arial', 10, 'bold')).pack(padx=10, pady=10)\n        button_frame = tk.Frame(joker_window)\n        button_frame.pack(padx=10, pady=5)\n        row = 0\n        col = 0\n        \n        for suit, rank, card_str in playable_targets:\n            fg, bg = self.get_card_color(card_str)\n            btn = tk.Button(button_frame, text=card_str, width=6, height=2, \n                            bg=bg, fg=fg, font=('Arial', 12, 'bold'),\n                            command=lambda s=suit, r=rank, w=joker_window: self.process_joker_choice(joker_card, s, r, w))\n            btn.grid(row=row, column=col, padx=5, pady=5)\n            col += 1\n            if col &gt; 6:\n                col = 0\n                row += 1\n        joker_window.protocol(\"WM_DELETE_WINDOW\", lambda: self.process_joker_choice(joker_card, None, None, joker_window))\n        self.master.wait_window(joker_window)\n\n    def process_joker_choice(self, joker_card, target_suit, target_rank, joker_window):\n        try:\n            joker_window.destroy() \n        except tk.TclError:\n            pass \n        if target_suit is None:\n            self.status_label.config(text=\"YOU \u306e\u79fb\u52d5: \u30b8\u30e7\u30fc\u30ab\u30fc\u4f7f\u7528\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f\", fg='orange')\n            return\n            \n        player = self.game.get_current_player()\n        target_info = (target_suit, target_rank)\n        \n        # \u30b8\u30e7\u30fc\u30ab\u30fc\u3092\u4f7f\u3063\u3066\u5834\u306b\u51fa\u3059\n        success, msg = self.game.play_card(player, joker_card, target_info)\n        \n        if success:\n            if \"\u5f37\u5236\u63d0\u793a\" in msg:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='red')\n            else:\n                self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='green')\n            self.end_turn()\n        else:\n            messagebox.showerror(\"\u5931\u6557\", msg)\n\n    def handle_card_click(self, card):\n        player = self.game.get_current_player()\n        if not player.is_human: return\n        \n        # \u30d0\u30b0\u4fee\u6b63: \u30b8\u30e7\u30fc\u30ab\u30fc\u306f\u51fa\u305b\u308b\u30ab\u30fc\u30c9\u306e\u6709\u7121\u306b\u95a2\u308f\u3089\u305a\u5e38\u306b\u5b9f\u884c\u53ef\u80fd\u3068\u3059\u308b\n        if card.is_joker:\n            self.show_joker_options(card)\n        else:\n            success, msg = self.game.play_card(player, card)\n            if success:\n                if \"\u5f37\u5236\u63d0\u793a\" in msg:\n                    self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='red')\n                else:\n                    self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='green')\n                self.end_turn()\n            else:\n                 messagebox.showerror(\"\u5931\u6557\", msg)\n\n\n    def handle_pass(self, event=None):\n        player = self.game.get_current_player()\n        if not player.is_human: return\n        \n        # Game.pass_turn \u304c\u4fee\u6b63\u3055\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u6226\u7565\u7684\u30d1\u30b9\u3092\u8a31\u53ef\n\n        success, msg = self.game.pass_turn(player)\n        if success:\n            self.status_label.config(text=f\"YOU \u306e\u79fb\u52d5: {msg}\", fg='blue')\n            self.end_turn()\n        else:\n            messagebox.showerror(\"\u30d1\u30b9\u5931\u6557\", msg)\n\n    def end_turn(self):\n        winner = self.game.check_winner()\n        if winner:\n            self.status_label.config(text=f\"&#x1f389; \u52dd\u8005: {winner} &#x1f389;\", fg='red')\n            self.update_status_display() \n            response = messagebox.askyesno(\"\u30b2\u30fc\u30e0\u7d42\u4e86\", f\"\u52dd\u8005\u306f {winner} \u3067\u3059\uff01\\n\u3082\u3046\u4e00\u5ea6\u30d7\u30ec\u30a4\u3057\u307e\u3059\u304b\uff1f\")\n            if response:\n                self.reset_and_start_game()\n            else:\n                self.pass_button.config(state=tk.DISABLED)\n                self.master.quit()\n            return\n        if self.game.next_turn():\n            self.update_gui()\n            if not self.game.get_current_player().is_human:\n                self.run_turn() \n        else:\n            self.update_gui()\n\n    def run_turn(self):\n        current_player = self.game.get_current_player()\n        if current_player.is_human: return \n        self.master.after(500, lambda: self.ai_move(current_player)) \n\n    def ai_move(self, player):\n        playable_cards = player.get_playable_cards(self.game.field)\n        \n        target_info = None\n        card_to_play = None\n        \n        if not playable_cards:\n            # \u30d1\u30b9\n            success, msg = self.game.pass_turn(player)\n        else:\n            joker = next((c for c in playable_cards if c.is_joker), None)\n            non_jokers = &#091;c for c in playable_cards if not c.is_joker]\n            \n            if non_jokers:\n                # 7\u304b\u3089\u9060\u3044\u30ab\u30fc\u30c9\u3092\u512a\u5148\u3057\u3066\u51fa\u3059 (\u624b\u672d\u3092\u6e1b\u3089\u3059\u6226\u7565)\n                card_to_play = max(non_jokers, key=lambda c: abs(c.value - 7)) \n                success, msg = self.game.play_card(player, card_to_play)\n            elif joker:\n                # \u30b8\u30e7\u30fc\u30ab\u30fc\u3057\u304b\u51fa\u305b\u306a\u3044\u5834\u5408\u3001\u4ee3\u7528\u5019\u88dc\u3092\u63a2\u3059\n                field = self.game.field\n                \n                # \u5168\u3066\u306e\u30d7\u30ec\u30a4\u30e4\u30fc\u306e\u624b\u672d\u306b\u3042\u308b\u30ab\u30fc\u30c9\u306e\u30bb\u30c3\u30c8\u3092\u4f5c\u6210 (COM\u306e\u30b8\u30e7\u30fc\u30ab\u30fc\u4ee3\u7528\u6226\u7565\u306f\u4fdd\u5b88\u7684\u306b\u5236\u9650\u3092\u6b8b\u3059)\n                all_hands_cards = set()\n                for p in self.game.players:\n                    for card in p.hand:\n                        if not card.is_joker:\n                             all_hands_cards.add((card.suit, card.rank))\n                \n                candidates = &#091;]\n                for suit in Card.SUITS:\n                    for rank_index in range(len(Card.RANKS)):\n                        temp_card = Card(Card.SUITS.index(suit), rank_index)\n                        \n                        # 1. \u65e2\u306b\u51fa\u3066\u3044\u308b\u304b\uff1f\n                        if field.table&#091;suit]&#091;rank_index] is not None: continue\n                        # 2. Heart 7 \u306e\u4ee3\u7528\u7981\u6b62\n                        if temp_card == self.game.h7_card: continue\n                        \n                        # 3. \u8ab0\u304b\u306e\u624b\u672d\u306b\u6b8b\u3063\u3066\u3044\u308b\u304b\uff1f (COM\u306f\u30d0\u30b0\u5bfe\u7b56\u306e\u305f\u3081\u5236\u9650\u3092\u6b8b\u3059)\n                        if (temp_card.suit, temp_card.rank) in all_hands_cards: continue \n                        \n                        # 4. 7\u307e\u305f\u306f\u96a3\u63a5\u30ab\u30fc\u30c9\u304c\u51fa\u3066\u3044\u308b\u304b\uff1f\n                        if temp_card.value == 7 or field.is_playable(temp_card):\n                             candidates.append((suit, temp_card.rank))\n                             \n                if candidates:\n                    # 7\u306b\u8fd1\u3044\u30ab\u30fc\u30c9\u3092\u512a\u5148\u3057\u3066\u4ee3\u7528\u3059\u308b (\u5834\u3092\u7e4b\u3052\u308b\u6226\u7565)\n                    candidates.sort(key=lambda x: abs(Card.RANK_VALUES&#091;x&#091;1]] - 7))\n                    target_suit, target_rank = candidates&#091;0]\n                    target_info = (target_suit, target_rank)\n                    \n                    card_to_play = joker\n                    success, msg = self.game.play_card(player, card_to_play, target_info)\n                else:\n                    # \u4ee3\u7528\u3067\u304d\u308b\u30ab\u30fc\u30c9\u304c\u306a\u3044\u5834\u5408\u306f\u30d1\u30b9\n                    success, msg = self.game.pass_turn(player)\n            else:\n                 # \u3053\u3053\u306f\u30ed\u30b8\u30c3\u30af\u7684\u306b\u306f\u901a\u3089\u306a\u3044\u306f\u305a\u3060\u304c\u3001\u5ff5\u306e\u305f\u3081\u30d1\u30b9\n                 success, msg = self.game.pass_turn(player) \n\n        \n        if \"\u5f37\u5236\u63d0\u793a\" in msg:\n            self.status_label.config(text=f\"{player.name} \u306e\u79fb\u52d5: {msg}\", fg='red')\n        else:\n            self.status_label.config(text=f\"{player.name} \u306e\u79fb\u52d5: {msg}\", fg='white')\n            \n        self.master.update()\n        self.master.after(500, self.end_turn)\n\n# ======================================================================\n# C. \u30e1\u30a4\u30f3\u5b9f\u884c\n# ======================================================================\nif __name__ == '__main__':\n    root = tk.Tk()\n    app = SevensGUI(root)\n    root.mainloop()<\/code><\/pre>\n<\/details>\n\n\n\n<p>\u300c\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log\u300d\u30b7\u30ea\u30fc\u30ba\u306f\u4eca\u5f8c\u3082\u7d99\u7d9a\u3057\u307e\u3059\u3002AI\u306e\u529b\u3092\u501f\u308a\u3066\u300eAI\u30b3\u30fc\u30c0\u30fc\u300f\u3068\u3057\u3066\u3069\u3053\u307e\u3067\u3044\u3051\u308b\u304b\u3001R60\u306e\u6311\u6226\u306f\u7d9a\u304d\u307e\u3059\u3002\u3069\u3046\u305e\u3054\u671f\u5f85\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-6fa6bfbd80a239f639fe034511d73f77\" style=\"background-color:#004b76\">III. Redkabagon\u306e\u30b2\u30fc\u30e0\u9032\u5c55\u3068\u6b21\u56de\u4e88\u544a<\/h2>\n\n\n\n<p>\u3053\u306eAI\u3068\u306e\u5bfe\u6226\u306e\u6a21\u69d8\u306f\u3001\u7b46\u8005\u30af\u30ea\u30a2\u52d5\u753b\u3068\u3057\u3066<strong>\u4e00\u822c\u516c\u958b<\/strong>\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\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<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<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<\/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\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=\"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\ud83c\udfaf \u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log Vol.4\uff1a\u4e03\u4e26\u3079\uff08Sevens\uff09\n\t\t<\/span><\/div>","protected":false},"excerpt":{"rendered":"<p>&#x1f3ac; \u5c0e\u5165\uff1aR60\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u3001\u4e03\u4e26\u3079AI\u958b\u767a\u3067\u300c\u8133\u5185\u6d3b\u6027\u300d\u306b\u6311\u3080\uff01 \u79c1\u305f\u3061R60\u306e\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306f\u3001\u4ef2\u826f\u304f\u8001\u3044\u3066\u3044\u304f\u4e2d\u3067\u3001\u8133\u5185\u6d3b\u6027\uff08\u30a2\u30f3\u30c1\u30a8\u30a4\u30b8\u30f3\u30b0\uff09\u306e\u305f\u3081\u306e\u6311\u6226\u3092\u7d9a\u3051\u308b\u300c\u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/smilekabagon.com\/?p=3961\" class=\"more-link\"><span class=\"screen-reader-text\">&#8220;&#x1f3af; \u30dd\u30f3\u30b3\u30c4\u592b\u5a66\u306eGame Trial Log Vol.4\uff1a\u4e03\u4e26\u3079\uff08Sevens\uff09&#8221; \u306e<\/span>\u7d9a\u304d\u3092\u8aad\u3080<\/a><\/p>\n","protected":false},"author":2,"featured_media":4040,"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-3961","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\/3961","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=3961"}],"version-history":[{"count":8,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/posts\/3961\/revisions"}],"predecessor-version":[{"id":4091,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/posts\/3961\/revisions\/4091"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=\/wp\/v2\/media\/4040"}],"wp:attachment":[{"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smilekabagon.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}