{"id":336967,"date":"2022-08-12T15:01:08","date_gmt":"2022-08-12T15:01:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=336967"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=336967","title":{"rendered":"<span>\u0412\u044b\u0445\u043e\u0434\u0438\u043c \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b JVM. \u041e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u043c \u043d\u0430 \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0430\u0445-\u043d\u043e\u043b\u0438\u043a\u0430\u0445 \u0447\u0435\u043c \u0445\u043e\u0440\u043e\u0448 Kotlin Multiplatform<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/8ff\/3a1\/83f\/8ff3a183ff37c4260b21ff531faa56b4.jpg\" width=\"780\" height=\"440\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8ff\/3a1\/83f\/8ff3a183ff37c4260b21ff531faa56b4.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u043a\u043e\u0439 \u0435\u0441\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a \u0443 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439, front-end \u0438 back-end \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u0440\u0430\u0441\u043f\u0438\u043b\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432? \u0414\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438. \u041e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u044f \u0432\u0438\u0434\u0435\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0438\u043b\u0438 \u043d\u043e\u0432\u043e\u0441\u0442\u0438, \u0433\u0434\u0435 \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0436\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043a\u0430\u0442\u0438\u0442\u044c \u0440\u0435\u043b\u0438\u0437. \u0418 \u0435\u0441\u043b\u0438 \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u0432\u0441\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438 \u0435\u0441\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0442\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c? \u041e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438 \u0442\u0430\u043c.<\/p>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u0438\u043c\u0435\u0442\u044c \u0434\u0443\u0431\u043b\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0447\u0442\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 Kotlin Multiplatform \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432\u0441\u0435\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0439 \u0438\u0433\u0440\u044b \u00ab\u041a\u0440\u0435\u0441\u0442\u0438\u043a\u0438-\u043d\u043e\u043b\u0438\u043a\u0438\u00bb \u043d\u0430 \u0442\u0440\u0435\u0445 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 Browser (JS), iOS (Swift) \u0438 Android (Java) \u0441 \u043e\u0431\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043d\u0430 Kotlin.<\/p>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<ul>\n<li>\n<p><a href=\"#about\">\u041e\u0431 \u0430\u0432\u0442\u043e\u0440\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#why-kotlin\">\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e Kotlin Multiplatform<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#practice\">\u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0430<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#create-project\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#environment\">\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#create-project-more\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#build-settings\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"#write-code\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#design\">\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sdk\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f SDK<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sdk-implements\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f SDK \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#js-implement\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 JS<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#swift-implement\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Swift<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#java-implement\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Java<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"#result\">\u0418\u0442\u043e\u0433<\/a><\/p>\n<\/li>\n<\/ul>\n<p><a class=\"anchor\" name=\"about\" id=\"about\"><\/a><\/p>\n<h3>\u041e\u0431 \u0430\u0432\u0442\u043e\u0440\u0435<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044e\u0441\u044c \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0439 \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0438\u0448\u0443. \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0423\u0441\u0442\u0438\u043d\u043e\u0432 \u0422\u0438\u0445\u043e\u043d \u0438 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432\u00a0<a href=\"https:\/\/rtkit.ru\/\">\u0420\u043e\u0441\u0442\u0435\u043b\u0435\u043a\u043e\u043c \u0418\u0422<\/a>, \u0430 \u0435\u0441\u043b\u0438 \u0431\u044b\u0442\u044c \u0442\u043e\u0447\u043d\u0435\u0435 \u2014 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u00ab\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f\u00a0<a href=\"https:\/\/rtkit.ru\/products\/edinii-produktovii-katalog\">\u0415\u041f\u041a<\/a>\u00a0(\u0415\u0434\u0438\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430)\u00bb.<\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u043e\u0439 core-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0433\u043e\u0434\u0443 \u0420\u043e\u0441\u0442\u0435\u043b\u0435\u043a\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u0433\u0438\u0431\u043a\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u0443\u0441\u043b\u0443\u0433. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 SDK, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u0441\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443: \u043e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e \u043f\u0440\u043e\u0441\u0447\u0435\u0442\u0430 \u0446\u0435\u043d\u044b.<\/p>\n<p>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043d\u0438\u0436\u0435 \u2014 \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043e\u0434\u043d\u0430 \u0438\u0437 \u0432\u0438\u0442\u0440\u0438\u043d \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u044d\u0442\u043e\u0433\u043e SDK.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/bf6\/5f8\/b84\/bf65f8b84db61464bbe3a96e334f8299.jpeg\" width=\"1240\" height=\"1272\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bf6\/5f8\/b84\/bf65f8b84db61464bbe3a96e334f8299.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 SDK \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043b\u0438\u0447\u043d\u043e\u043c \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435, \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043b\u0438 \u0432 \u043e\u0444\u0438\u0441\u0435 \u043f\u0440\u043e\u0434\u0430\u0436, \u0433\u0434\u0435 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0430\u043c \u0447\u0442\u043e-\u043b\u0438\u0431\u043e, \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 SDK.<\/p>\n<p><a class=\"anchor\" name=\"why-kotlin\" id=\"why-kotlin\"><\/a><\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e Kotlin Multiplatform<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0432\u044b\u0431\u0440\u0430\u0442\u044c Kotlin Multiplatform, \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0438 \u043d\u0430 \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0430\u0445. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u043c \u043f\u0440\u0438\u044f\u0442\u043d\u044b\u043c \u0431\u043e\u043d\u0443\u0441\u043e\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u044f\u0441\u044c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, \u0442\u043e \u043f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u2014 \u044d\u0442\u043e React Native \u0438 Progressive Web Applications (PWA). \u041e\u0434\u043d\u0430\u043a\u043e, \u043c\u044b \u0443\u0436\u0435 \u0438\u043c\u0435\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0430\u0437\u0443 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f, \u0438 webview \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u043e\u0436\u0435 \u043d\u0435 \u043b\u0443\u0447\u0448\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c. \u041f\u043e \u044d\u0442\u043e\u0439 \u0436\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043c\u044b \u043e\u0442\u043c\u0435\u043b\u0438 \u0438\u0434\u0435\u044e \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 flutter, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u0438\u043c\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043d\u0430 ios \u0438 android \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0432 js. \u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e \u043d\u0430\u0448 \u0432\u044b\u0431\u043e\u0440 \u0434\u043e \u0434\u0432\u0443\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:<\/p>\n<p>a) C\/C++ \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043a \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0438 \u043a js \u043a\u0430\u043a WebAssembly<\/p>\n<p>b) \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u043e\u0433\u0434\u0430 Kotlin Multiplatform.<\/p>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u043f\u043e C\/C++ \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e \u043d\u0430\u0448\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0434\u043e \u043e\u0434\u043d\u043e\u0433\u043e, \u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043c\u044b \u043d\u0438 \u0440\u0430\u0437\u0443 \u043d\u0435 \u043f\u043e\u0436\u0430\u043b\u0435\u043b\u0438 \u043e \u0441\u0432\u043e\u0435\u043c \u0432\u044b\u0431\u043e\u0440\u0435. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043c\u044b \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u0435\u0451 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0439. \u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 API \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043a\u043e\u0434, \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435 \u0441\u0430\u0439\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u0432\u0432\u043e\u0434\u0430 \u043d\u043e\u043c\u0435\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 API \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a API \u0432 \u043e\u0431\u0445\u043e\u0434 \u0444\u0440\u043e\u043d\u0442\u0430, \u0438 \u0442\u043e\u0433\u0434\u0430 API \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/60a\/20c\/7f3\/60a20c7f3edfcb0ba038f1c5a7b0d883.jpeg\" width=\"1857\" height=\"831\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/60a\/20c\/7f3\/60a20c7f3edfcb0ba038f1c5a7b0d883.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0441 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 Kotlin Multiplatform \u0432\u0441\u0451 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e. \u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u043f\u043b\u044e\u0441\u044b \u043c\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u044d\u0442\u043e\u0439 \u043d\u0435\u0439.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0442\u043e\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform.html\">Kotlin Multiplatform<\/a>\u00a0\u2014 \u044d\u0442\u043e \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 JetBrains, \u043e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 Kotlin \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043d\u0430\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-dsl-reference.html#targets\">10 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c<\/a>. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u043c\u0435\u0442\u044c \u0434\u043b\u044f JVM *.jar \u0444\u0430\u0439\u043b, \u0434\u043b\u044f JS \u2014 *.js \u043c\u043e\u0434\u0443\u043b\u044c \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f *.d.ts, \u0438, \u043f\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u0437\u0430 \u0442\u0430\u0432\u0442\u043e\u043b\u043e\u0433\u0438\u044e, \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0442\u0438\u043f\u0430 *.framework \u0434\u043b\u044f Swift. \u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b.<\/p>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0438 \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440, \u0445\u043e\u0447\u0443 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043e\u0442\u0442\u0443\u0434\u0430 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u044e \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u0434\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/6c7\/943\/05a\/6c794305a82c90c17b2f92639fbd4055.jpeg\" width=\"6055\" height=\"2642\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6c7\/943\/05a\/6c794305a82c90c17b2f92639fbd4055.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0435 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0430\u043b\u044c\u0444\u0430-\u0432\u0435\u0440\u0441\u0438\u0438. \u041d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u0436\u0435 \u0433\u043e\u0434 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0442\u044b\u0441\u044f\u0447\u0430\u0445 (\u0435\u0441\u043b\u0438 \u043d\u0435 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430\u0445) \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043c\u043e\u0433\u0443 \u0437\u0430\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0436\u0438\u0437\u043d\u0435\u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d, \u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0440\u0435\u0448\u0430\u0435\u043c\u044b.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/3d2\/760\/b08\/3d2760b080a4ca1c8987e60d44e34ad1.jpeg\" width=\"801\" height=\"119\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3d2\/760\/b08\/3d2760b080a4ca1c8987e60d44e34ad1.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u044b \u0432\u044b\u044f\u0432\u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0442\u0430\u043a\u0438\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u044e\u0441\u044b:<\/p>\n<ul>\n<li>\n<p><strong>\u041e\u0434\u0438\u043d \u043a\u043e\u0434, \u043e\u0434\u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c.<\/strong>\u00a0\u041c\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0438\u043c\u0435\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0436\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u2014 \u044d\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0442\u0440\u0430\u0442 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0434\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0445\u043e\u0442\u0435\u043b\u043e\u043a \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u0434\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f;<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430.<\/strong>\u00a0\u0412\u044b\u043d\u0435\u0441\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0435\u0434\u0438\u043d\u044b\u0439 SDK \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0435\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u043c. \u0418\u043c\u0435\u044f \u043e\u0434\u043d\u0443 \u043e\u0431\u0449\u0443\u044e \u0434\u043e\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438, \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u044b\u0435 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430. \u041d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0443\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0437 \u0432\u0438\u0434\u0443 \u043d\u0435\u043c\u0430\u043b\u043e\u0432\u0430\u0436\u043d\u044b\u0439 bus factor, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0436\u0435 \u0443 \u0442\u0440\u0451\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u0447\u0435\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0443 3 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0430 3 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430 3 \u044f\u0437\u044b\u043a\u0430\u0445;<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f.<\/strong>\u00a0\u041e\u0447\u0435\u043d\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f JS. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0435\u0441\u0442\u044c TypeScript, \u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u043e \u0432 \u043f\u043b\u044e\u0441;<\/p>\n<\/li>\n<li>\n<p><strong>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/strong>\u00a0\u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u0442\u0435 \u043a\u043e\u0434 \u0431\u0435\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0435\u0437 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438, \u0432\u044b \u0440\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043d\u0430\u0447\u043d\u0435\u0442\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u0435\u0441\u0442\u0430 \u0432\u044b, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430, \u043f\u043b\u044e\u0441 \u0442\u0435\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0438 \u043f\u043e\u0432\u044b\u0448\u0430\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430. \u041d\u0430\u043f\u0438\u0441\u0430\u0432 \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442, \u0432\u044b \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u0432\u0441\u0435 \u0432\u0430\u0448\u0438 \u0446\u0435\u043b\u0435\u0432\u044b\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b, \u0447\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u0440\u0435\u0441\u0443\u0440\u0441 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p><strong>\u042f\u0437\u044b\u043a.<\/strong>\u00a0\u041a\u0442\u043e \u0431\u044b \u0447\u0442\u043e \u043d\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u043d\u043e \u043b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f Kotlin \u2014 \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u0433\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u044f\u0437\u044b\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u043b\u044e\u0434\u044c\u043c\u0438 \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0438\u043c\u0435\u0435\u0442\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u0435\u0451 [\u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443] \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0442\u044c, \u0430 \u043d\u0435 \u0432 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u043c (\u0431\u0435\u0437 \u043e\u0431\u0438\u0434) Go: \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u043c\u0435\u0442\u043e\u0434, \u0432\u0438\u0434\u0438\u0448\u044c \u043a\u0443\u0447\u0443 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0448\u044c \u0431\u0435\u0437 \u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f33\/aab\/25e\/f33aab25e266f0f520df3a45a3a08996.jpeg\" width=\"1195\" height=\"981\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f33\/aab\/25e\/f33aab25e266f0f520df3a45a3a08996.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0438 \u043c\u0438\u043d\u0443\u0441\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u043e\u0442\u0435\u0440\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/strong>\u00a0\u042d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f JS \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 overhead. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u043e\u0442\u0435\u0440\u0438 \u043d\u0435 \u0442\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u044d\u0442\u043e\u0433\u043e;<\/p>\n<\/li>\n<li>\n<p><strong>\u042d\u043a\u0441\u043f\u0435\u0440\u0442\u0438\u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/strong>\u00a0\u0425\u043e\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u043d\u043e \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u044b\u043a\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u043b\u044f \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u043d\u0430\u0442\u044c \u043f\u043e\u043c\u0438\u043c\u043e Kotlin \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0442;<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f.<\/strong>\u00a0\u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u043f\u0438\u0448\u0435\u0442\u0435 \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u0434, \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0435\u0437\u0434\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e. \u0422\u043e, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043e\u0434\u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u0440\u0443\u0433\u0430\u044f, \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 Kotlin \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 runBlocking, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u043a\u043e\u0434\u0435 Kotlin, Java \u0438 Swift, \u043d\u043e \u043e\u043d \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043a\u043e\u0434\u0435 JS, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e,\u00a0<a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\/195#issuecomment-354458878\">\u0446\u0438\u0442\u0438\u0440\u0443\u044e<\/a>: \u00ab\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u0443\u043c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 JS. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u0430\u044f \u043d\u0430 JS, \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439\u00bb. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-connect-to-apis.html\">\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f<\/a>\u00a0(expect\/actual \u043a\u043b\u0430\u0441\u0441\u044b) \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0443\u043c\u0430\u044e, \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u0431\u0449\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u0430\u043d\u043e. \u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u0441\u0442\u043e\u0438\u0442 \u043b\u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u0434\u0430\u043b\u044c\u0448\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043f\u043e\u0437\u0436\u0435, \u0438\u043b\u0438, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u043c \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u0438 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u044d\u0442\u043e \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p><a class=\"anchor\" name=\"practice\" id=\"practice\"><\/a><\/p>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0430<\/h3>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043a\u0430\u043a \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u044f\u0434\u0440\u043e \u0438\u0433\u0440\u044b \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0438-\u043d\u043e\u043b\u0438\u043a\u0438 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0442\u0440\u0435\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 JS (Browser), Swift (iOS), Java (Android). \u0412\u0435\u0441\u044c \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 GitHub \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e\u00a0<a href=\"https:\/\/github.com\/Tihon-Ustinov\/tictactoe\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<p><a class=\"anchor\" name=\"create-project\" id=\"create-project\"><\/a><\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p><a class=\"anchor\" name=\"environment\" id=\"environment\"><\/a><\/p>\n<p><strong>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/strong><\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Kotlin Multiplatform \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u044b\u00a0<a href=\"https:\/\/github.com\/Kotlin\/kdoctor\">KDoctor<\/a>. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b\u0438, \u0447\u0442\u043e \u0432\u0441\u0451 \u0435\u0441\u0442\u044c, \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043b\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442. \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u0438\u043c.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/5c6\/d90\/63e\/5c6d9063e586b192b1fb959b519af40d.jpeg\" width=\"2526\" height=\"1750\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5c6\/d90\/63e\/5c6d9063e586b192b1fb959b519af40d.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0434\u043b\u044f \u0432\u0430\u0441 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0434 iOS \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Kotlin Multiplatform \u043d\u0443\u0436\u0435\u043d Command Line Tools (\u043e\u0431\u044b\u0447\u043d\u043e \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 xcode), \u0430 \u043f\u043e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0435 Apple \u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043f\u0440\u043e\u0434\u0443\u043a\u0446\u0438\u044e Apple. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430 Hackintosh, \u0445\u043e\u0442\u044f, \u0447\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044f \u043d\u0435 \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b.<\/p>\n<p>\u0421\u043a\u0430\u0447\u0430\u0442\u044c Command Line Tools \u043c\u043e\u0436\u043d\u043e \u0441\u00a0<a href=\"https:\/\/developer.apple.com\/download\/all\/\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0430\u0439\u0442\u0430 Apple \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432<\/a>.<\/p>\n<p><a class=\"anchor\" name=\"create-project-more\" id=\"create-project-more\"><\/a><\/p>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/strong><\/p>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f\u00a0<a href=\"https:\/\/terrakok.github.io\/kmp-web-wizard\/\">Kotlin Multiplatform Wizard<\/a>. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Kotlin;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0446\u0435\u043b\u0435\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c\u00a0<strong>JVM<\/strong>,\u00a0<strong>JS<\/strong>,\u00a0<strong>iOS<\/strong>\u00a0(\u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435);<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u2014 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u041d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0442\u043e \u0442\u0435\u0441\u0442\u044b \u0432\u0430\u043c \u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/9e1\/bfb\/d7e\/9e1bfbd7e3286882606d007d8a21fcd7.jpeg\" width=\"1272\" height=\"779\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9e1\/bfb\/d7e\/9e1bfbd7e3286882606d007d8a21fcd7.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438 \u0440\u0430\u0437\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u0432 \u0432\u0430\u0448\u0443 \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432 \u0432\u0430\u0448\u0435\u0439 \u043b\u044e\u0431\u0438\u043c\u043e\u0439 IDE, \u043d\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c IntelliJ IDEA, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u043d\u0435\u0439 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Kotlin Multiplatform. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-connect-to-apis.html\">\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f<\/a>\u00a0\u043a\u043b\u0430\u0441\u0441\u043e\u0432 IntelliJ IDEA \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u043a\u043b\u0430\u0441\u0441\u044b.<\/p>\n<p>Kotlin Multiplatform Wizard \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0442\u0435\u0441\u0442\u043e\u0432: Platform.kt, CommonTest, PlatformTest. \u041d\u0430\u043c \u043e\u043d\u0438 \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0441\u0440\u0430\u0437\u0443 \u0443\u0434\u0430\u043b\u0438\u043c. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/876\/733\/718\/876733718002ef906b09be2199c2f778.jpeg\" width=\"640\" height=\"765\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/876\/733\/718\/876733718002ef906b09be2199c2f778.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p><a class=\"anchor\" name=\"build-settings\" id=\"build-settings\"><\/a><\/p>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438<\/strong><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0431\u043e\u0440\u043a\u0438 gradle \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043f\u043e\u0434 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u043c\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0442\u0440\u0438 \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0444\u0430\u0439\u043b\u0435 <strong><em>.\/settings.gradle.kts<\/em><\/strong>\u00a0\u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0436\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e kotlin multiplatform.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 .\/settings.gradle.kts<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">pluginManagement {     repositories {         google()         gradlePluginPortal()         mavenCentral()     }     \/\/ \u0423\u043a\u0430\u0436\u0435\u043c \u044f\u0432\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0431\u043e\u043b\u0435 \u0440\u0430\u043d\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u0435\u0441\u0442\u044c \u0431\u044b\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 *d.ts \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c IR     plugins {         kotlin(\"multiplatform\") version \"1.7.10\"     } }  rootProject.name = \"tictactoe\" include(\":core\")<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u2014 \u0443\u043a\u0430\u0436\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e \u0438 \u0433\u0440\u0443\u043f\u043f\u0443 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 .\/gradle.properties<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\"># \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u0443 \u0438 \u0432\u0435\u0440\u0441\u0438\u044e \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 group=ru.tikhon.tictactoe version=1.0.0 # \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0441\u0442\u044c #Gradle org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\\=\"-Xmx2048M\" #Kotlin kotlin.code.style=official #MPP kotlin.mpp.enableCInteropCommonization=true<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>B \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u0444\u0430\u0439\u043b\u0435 <strong><em>.\/core\/build.gradle.kts<\/em><\/strong>\u00a0\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c.<\/p>\n<p>\u0414\u043b\u044f jvm \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e java, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 *.jar-\u0444\u0430\u0439\u043b. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438 \u0432\u044b\u0448\u0435, \u044d\u0442\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e \u0433\u0434\u0435 \u0432\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u044d\u0442\u043e\u0442 *.jar-\u0444\u0430\u0439\u043b.<\/p>\n<p>\u0414\u043b\u044f js \u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0438\u043f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 IR. IR \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 *.d.ts, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 TypeScript. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b ide \u043f\u0440\u043e\u0438\u043d\u0434\u0435\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0435\u0433\u043e, \u0438 \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043a\u043e\u0434\u0430 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 ide.<\/p>\n<p>\u0423\u043a\u0430\u0436\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0434\u043b\u044f iOS \u0441\u0431\u043e\u0440\u043e\u043a, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 .\/core\/build.gradle.kts<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">plugins {     kotlin(\"multiplatform\") }  kotlin {     \/* JVM Target Configuration *\/     jvm {         compilations.all {             kotlinOptions.jvmTarget = \"1.8\"         }         withJava()     }     \/* JS Target Configuration *\/     js(IR) {         binaries.executable()         browser()     }     \/* iOS Target Configuration *\/     iosX64 {         binaries {             framework {                 baseName = \"GAMEFramework\"             }         }     }     iosArm64 {         binaries {             framework {                 baseName = \"GAMEFramework\"             }         }     }     iosSimulatorArm64 {         binaries {             framework {                 baseName = \"GAMEFramework\"             }         }     }      sourceSets {         \/* Main source sets *\/         val commonMain by getting         val jvmMain by getting         val jsMain by getting         val iosMain by creating         val iosX64Main by getting         val iosArm64Main by getting         val iosSimulatorArm64Main by getting          \/* Main hierarchy *\/         jvmMain.dependsOn(commonMain)         jsMain.dependsOn(commonMain)         iosMain.dependsOn(commonMain)         iosX64Main.dependsOn(iosMain)         iosArm64Main.dependsOn(iosMain)         iosSimulatorArm64Main.dependsOn(iosMain)          \/* Test source sets *\/         val commonTest by getting {             dependencies {                 implementation(kotlin(\"test\"))             }         }         val jvmTest by getting         val jsTest by getting         val iosTest by creating         val iosX64Test by getting         val iosArm64Test by getting         val iosSimulatorArm64Test by getting          \/* Test hierarchy *\/         jvmTest.dependsOn(commonTest)         jsTest.dependsOn(commonTest)         iosTest.dependsOn(commonTest)         iosX64Test.dependsOn(iosTest)         iosArm64Test.dependsOn(iosTest)         iosSimulatorArm64Test.dependsOn(iosTest)     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><a class=\"anchor\" name=\"write-code\" id=\"write-code\"><\/a><\/p>\n<h3>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u0441 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u044f\u0434\u0440\u0430 \u0438\u0433\u0440\u044b, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441 \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u0443\u0442\u0438\u00a0<em>core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/SayHello.kt<\/em>\u00a0\u0441 \u0442\u0430\u043a\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c\u2026<\/p>\n<pre><code class=\"kotlin\">package org.rubicon.game  import kotlin.js.JsExport  @JsExport class SayHello {     fun say() {         println(\"Hello from Kotlin Multiplatform\")     } }<\/code><\/pre>\n<p>\u2026\u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a \u043f\u0443\u043d\u043a\u0442\u0443 \u00ab<a href=\"#sdk-implements\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f SDK \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445<\/a>\u00bb, \u0433\u0434\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u043a\u0430\u043a \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0440\u0430\u043d\u0435\u0435 \u0432\u044b\u0431\u0440\u0430\u043b\u0438.<\/p>\n<p>\u041b\u0438\u0431\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0433\u0440\u044b \u0438 \u0437\u0430\u043e\u0434\u043d\u043e \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f SDK \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\n<p><a class=\"anchor\" name=\"design\" id=\"design\"><\/a><\/p>\n<h4>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0448 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0430\u043c:<\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0433\u0440\u044b;<\/p>\n<\/li>\n<li>\n<p>\u042d\u0442\u043e\u0442 \u043d\u0430\u0431\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b.<\/p>\n<\/li>\n<\/ul>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u0430\u044f:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043a\u043b\u0438\u043a\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0418\u0433\u0440\u0430\u0442\u044c\u00bb;<\/p>\n<\/li>\n<li>\n<p>View \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0438\u0433\u0440\u044b;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0433\u0440\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0438\u0433\u0440\u0443;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0438\u0433\u0440\u0430.<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/0c5\/6b6\/4f3\/0c56b64f3be61d6a599e3043eaa300c8.jpeg\" width=\"1693\" height=\"1103\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0c5\/6b6\/4f3\/0c56b64f3be61d6a599e3043eaa300c8.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p><a class=\"anchor\" name=\"sdk\" id=\"sdk\"><\/a><\/p>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f SDK<\/h4>\n<p>\u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043a\u043e\u0434\u0430, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c. \u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u00a0<strong>commonMain<\/strong>\u00a0\u0438 \u0442\u0430\u043c \u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0442\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0430 \u0438\u0433\u0440\u0430.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0432\u044b \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u044f \u043d\u0435 \u0445\u043e\u0442\u0435\u043b \u0432\u0435\u0441\u044c \u0435\u0433\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u044e \u0438 \u0434\u0443\u043c\u0430\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442, \u0433\u0434\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 \u043a\u043e\u0434\u0430, \u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u043c hello world \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u0431\u044b \u043a\u0435\u0439\u0441\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u0442\u043e \u043d\u0435 \u0445\u043e\u0447\u0435\u0442 \u043b\u0438\u0441\u0442\u0430\u0442\u044c \u043f\u043e\u0440\u0442\u044f\u043d\u043a\u0443 \u043b\u0443\u0447\u0448\u0435 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u0443\u0439\u0442\u0435 \u043d\u0430 github \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u00a0<a href=\"https:\/\/github.com\/Tihon-Ustinov\/tictactoe\">tictactoe<\/a>.<\/p>\n<p>\u041f\u043e \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0443\u043c\u0435\u0442\u044c \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043a\u0438\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043b\u0430\u0441\u0441\u00a0<strong>EventEmitter,<\/strong> \u0430 \u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00a0<strong>IEventEmitter<\/strong>.<\/p>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0435\u0441\u0442\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 View \u043f\u043e\u0434\u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u043e\u043b\u044f, \u0442\u043e \u043f\u0440\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043e\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0431\u044b\u043b \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u0440\u0435\u0441\u0442\u0438\u043a \u0438\u043b\u0438 \u043d\u043e\u043b\u0438\u043a. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u044a\u044f\u0432\u0438\u043c\u00a0<strong>IEvent<\/strong>\u00a0\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e\u00a0<strong>Event<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>interface core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/IEvent.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game  import kotlin.js.JsExport  \/**  * \u0421\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438  * @property type \u0422\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f  * @property source \u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f  *\/ @JsExport interface IEvent&lt;T : Enum&lt;T>, S> {     val type: T     val source: S      \/**      * \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u0438 \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0440\u043d\u0435\u0442 \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f      * *\/     operator fun component1(): T = this.type      \/**      * \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u0438 \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0440\u043d\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f      * *\/     operator fun component2(): S = this.source }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0435 \u043a\u043e\u0434\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e\u00a0<strong><a class=\"mention\" href=\"\/users\/Throws\">@Throws<\/a><a class=\"mention\" href=\"\/users\/JvmOverloads\">@JvmOverloads<\/a><a class=\"mention\" href=\"\/users\/JsName\">@JsName<\/a><a class=\"mention\" href=\"\/users\/JsExport\">@JsExport<\/a><\/strong>\u00a0\u2014 \u043e\u043d\u0430 \u043d\u0443\u0436\u043d\u0430 \u0437\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u0431\u044b\u043b\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u0430 JS, \u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b\u0438\u0441\u044c. \u0422\u0430\u043a \u0436\u0435 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e\u00a0<strong><a class=\"mention\" href=\"\/users\/Throws\">@Throws<\/a><a class=\"mention\" href=\"\/users\/JvmOverloads\">@JvmOverloads<\/a><a class=\"mention\" href=\"\/users\/JsName\">@JsName<\/a><\/strong>. \u041e\u043d\u0430 \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u2014 \u0432 JS \u043d\u0435\u0442 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u0440\u0435\u0434\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e\u00a0<strong><a class=\"mention\" href=\"\/users\/Throws\">@Throws<\/a><a class=\"mention\" href=\"\/users\/JvmOverloads\">@JvmOverloads<\/a><\/strong>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 Java. \u041f\u043b\u044e\u0441 \u0432 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u043d\u0438\u0436\u0435 \u043b\u0438\u0441\u0442\u0438\u043d\u0433\u0430\u0445 \u043a\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e\u00a0<strong><a class=\"mention\" href=\"\/users\/Throws\">@Throws<\/a><\/strong>\u00a0\u2014 \u043e\u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u0438 \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>class core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/events\/Event.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl.events  import org.rubicon.game.IEvent import kotlin.js.JsExport  @JsExport open class Event&lt;T : Enum&lt;T>, S>(     override val type: T,     override val source: S ) : IEvent&lt;T, S><\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044e\u00a0<strong>IEventEmitter<\/strong>\u00a0\u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u00a0<strong>EventEmitter<\/strong>. \u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u044f\u0432\u0438\u043c \u0443\u00a0<strong>IEventEmitter<\/strong>\u00a0\u0434\u0432\u0430 \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u0430:<\/p>\n<ul>\n<li>\n<p>T \u2014 \u044d\u0442\u043e \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c\u044b\u043c \u0442\u0438\u043f\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p>S \u2014 \u044d\u0442\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>Interface .\/core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/IEventEmitter.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game  import kotlin.js.JsExport   @JsExport class DuplicateListenersException(override val message: String) : Throwable(message)  \/**  * \u0422\u0438\u043f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438  * \u0434\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430 \u0432\u0445\u043e\u0434 \u0441\u043e\u0431\u044b\u0442\u0438\u0435  * \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043e\u043d\u0430 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c  * *\/ typealias EventCallBack&lt;T, S> = (IEvent&lt;T, S>) -> Unit  \/**  * \u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430  * *\/ @JsExport interface IEventEmitter&lt;T : Enum&lt;T>, S> {     \/**      * \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443      * *\/     @Throws(DuplicateListenersException::class)     fun on(eventType: T, callBack: EventCallBack&lt;T, S>)      \/**      * \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443      * *\/     fun del(eventType: T, callBack: EventCallBack&lt;T, S>)      \/**      * \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f      * *\/     fun once(eventType: T, callBack: EventCallBack&lt;T, S>) }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Class core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/events\/EventEmitter.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl.events  import org.rubicon.game.DuplicateListenersException import org.rubicon.game.EventCallBack import org.rubicon.game.IEvent import org.rubicon.game.IEventEmitter import kotlin.js.JsExport  @JsExport abstract class EventEmitter&lt;T : Enum&lt;T>, S> : IEventEmitter&lt;T, S> {     private val listeners: LinkedHashMap&lt;T, ArrayList&lt;EventCallBack&lt;T, S>>> = linkedMapOf()      override fun on(eventType: T, callBack: EventCallBack&lt;T, S>) {         val eventTypeCollection = listeners.getOrPut(eventType) {             arrayListOf()         }         if (callBack in eventTypeCollection) {             throw DuplicateListenersException(\"\u0414\u0430\u043d\u043d\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.\")         }         eventTypeCollection.add(callBack)     }      override fun del(eventType: T, callBack: EventCallBack&lt;T, S>) {         listeners[eventType]?.remove(callBack)     }      override fun once(eventType: T, callBack: EventCallBack&lt;T, S>) {         this.on(eventType) {             this.del(eventType, callBack)             callBack(it)         }     }      protected fun emit(event: IEvent&lt;T, S>) {         listeners[event.type]?.forEach {             it(event)         }     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0443\u0447\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043a\u0438\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0433\u0440\u044b\u00a0<strong>Game<\/strong>. \u041d\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0442\u0438\u043f\u044b \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441\u00a0<strong>Game<\/strong>\u00a0\u0431\u0443\u0434\u0435\u0442 \u043a\u0438\u0434\u0430\u0442\u044c.<\/p>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0433\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>GAME_OVER \u2014 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 \u0438\u0433\u0440\u044b. \u0411\u0443\u0434\u0435\u0442 \u043a\u0438\u0434\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u0435\u0441\u043b\u0438 \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u0430 \u0432\u044b\u0438\u0433\u0440\u0430\u043b\u0430, \u0438\u043b\u0438 \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0445\u043e\u0434\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438\u0441\u044c;<\/p>\n<\/li>\n<li>\n<p>CHANGE_CELL \u2014 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f (\u0442\u043e\u0433\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430, \u0433\u0434\u0435 \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f \u043a\u0440\u0435\u0441\u0442\u0438\u043a \u0438\u043b\u0438 \u043d\u043e\u043b\u0438\u043a). \u0411\u0443\u0434\u0435\u0442 \u043a\u0438\u0434\u0430\u0442\u044c\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0432 \u044f\u0447\u0435\u0439\u043a\u0443 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u0440\u0435\u0441\u0442\u0438\u043a, \u043d\u043e\u043b\u0438\u043a \u0438\u043b\u0438 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>Enum core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/events\/GameEventType.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl.events  import kotlin.js.JsExport  \/**  * \u0421\u043e\u0431\u044b\u0442\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0433\u0440\u044b  * *\/ @JsExport enum class GameEventType {     \/**      * \u0418\u0433\u0440\u0430 \u043e\u043a\u043e\u043d\u0447\u0435\u043d\u0430      * *\/     GAME_OVER,      \/**      * \u0418\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u043b\u044f      * *\/     CHANGE_CELL }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0447\u0442\u043e\u0431\u044b, \u0447\u0442\u043e\u0431\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00a0<strong>IGame<\/strong>\u00a0\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/p>\n<details class=\"spoiler\">\n<summary>Interface core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/IGame.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game  import org.rubicon.game.impl.events.GameEventType import kotlin.js.JsExport  \/**  * \u0418\u0433\u0440\u0430  * \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u0433\u0440\u044b \u043a\u0438\u0434\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e \u0438\u0433\u0440\u044b \u0438\u043b\u0438 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f  * *\/ @JsExport interface IGame : IEventEmitter&lt;GameEventType, IGame> {     \/**      * \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0438\u0433\u0440\u0443      *      * \u041a\u0438\u0434\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043f\u043e\u043b\u044f      * *\/     fun play()      \/**      * \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0433\u0440\u044b      * *\/     fun reset() }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u043e \u0434\u043b\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0430\u043c\u043e\u0439 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438\u00a0<strong>IGame<\/strong>\u00a0\u043d\u0430\u043c \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0435\u0449\u0435 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439:<\/p>\n<ol>\n<li>\n<p><strong>PlayerType<\/strong>\u00a0\u2014 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0438\u0439 \u0438\u0433\u0440\u043e\u043a\u0430, \u043a\u0440\u0435\u0441\u0442\u0438\u043a, \u043d\u043e\u043b\u0438\u043a \u0438\u043b\u0438 \u0435\u0433\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>Enum core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/PlayerType.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl  import kotlin.js.JsExport  \/**  * \u0422\u0438\u043f \u0438\u0433\u0440\u043e\u043a\u0430  * *\/ @JsExport enum class PlayerType {     \/**      * \u0418\u0433\u0440\u043e\u043a \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442      * *\/     NONE,      \/**      * \u0418\u0433\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0433\u0440\u0430\u0435\u0442 \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0430\u043c\u0438      * *\/     CROSS,      \/**      * \u0418\u0433\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0433\u0440\u0430\u0435\u0442 \u043d\u043e\u043b\u0438\u043a\u0430\u043c\u0438      * *\/     ZERO }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<ol start=\"2\">\n<li>\n<p><strong>IFieldCell<\/strong>\u00a0\u2014 \u044f\u0447\u0435\u0439\u043a\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a \u0441 \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u043e\u043c \u0438\u043b\u0438 \u043d\u043e\u043b\u0438\u043a\u043e\u043c \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435. \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u043a\u043b\u0438\u043a\u0430.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>Interface core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/IFieldCell.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game  import org.rubicon.game.impl.PlayerType import kotlin.js.JsExport  \/**  * \u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u0433\u0434\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0438 \u0438 \u043d\u043e\u043b\u0438\u043a\u0438  * *\/ @JsExport interface IFieldCell {     \/**      * \u041f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430      * *\/     fun click()      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u043a\u0438\u043c \u0438\u0433\u0440\u043e\u043a\u043e\u043c \u0431\u044b\u043b\u043e \u043d\u0430\u0436\u0430\u0442\u043e      * *\/     fun getState(): PlayerType      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 \u043f\u043e \u043e\u0441\u0438 X      * *\/     fun getX(): Int      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 \u043f\u043e \u043e\u0441\u0438 Y      * *\/     fun getY(): Int }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0418, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e\u00a0<strong>FieldCell<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>Class core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/FieldCell.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl  import org.rubicon.game.IFieldCell import org.rubicon.game.impl.events.Event import org.rubicon.game.impl.events.EventEmitter import kotlin.js.JsExport  @JsExport enum class FieldCellEvents {     CLICK }  @JsExport class FieldCell(     private val x: Int,     private val y: Int,     private var state: PlayerType = PlayerType.NONE ) : EventEmitter&lt;FieldCellEvents, FieldCell>(), IFieldCell {      \/**      * \u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0433\u0440\u044b \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043e \u043b\u0438\u0431\u043e \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u043e      * *\/     internal fun changeState(state: PlayerType) {         this.state = state     }      override fun click() {         \/\/ \u041c\u044b \u043a\u0438\u043d\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043a\u043b\u0438\u043a\u043d\u0443\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0443\u0436\u0435 \u043d\u0435 \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u043e \u0440\u0430\u043d\u044c\u0448\u0435         if (this.state == PlayerType.NONE) {             this.emit(Event(FieldCellEvents.CLICK, this))         }     }      override fun getState(): PlayerType = this.state      override fun getX(): Int = this.x     override fun getY(): Int = this.y }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<ol start=\"3\">\n<li>\n<p><strong>GameCellEvent<\/strong>\u00a0\u2014 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u044d\u0442\u043e\u0439 \u0441\u0430\u043c\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>Class core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/events\/GameCellEvent.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl.events  import org.rubicon.game.IGame import org.rubicon.game.impl.FieldCell import kotlin.js.JsExport  @JsExport class GameCellEvent(     source: IGame,     \/\/ \u042f\u0447\u0435\u0439\u043a\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f     val fieldCell: FieldCell ) : Event&lt;GameEventType, IGame>(GameEventType.CHANGE_CELL, source)<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<ol start=\"4\">\n<li>\n<p><strong>GameOverEvent<\/strong>\u00a0\u2014 \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 \u0438\u0433\u0440\u044b \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u043e\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u0435 \u0438 \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u043d\u043e\u0439 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u044f\u0447\u0435\u0435\u043a.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>Class core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/events\/GameOverEvent.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl.events  import org.rubicon.game.IGame import org.rubicon.game.impl.FieldCell import org.rubicon.game.impl.PlayerType import kotlin.js.JsExport  @JsExport class GameOverEvent(     game: IGame,     winLine: List&lt;FieldCell>? = null ) : Event&lt;GameEventType, IGame>(GameEventType.GAME_OVER, game) {     \/\/ \u041f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u043a Array \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0432 JS \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u0435\u0440\u043d\u0443\u043b \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432     val winLine = winLine?.toTypedArray()      \/\/ \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u044f \u043e\u0442\u0442\u0443\u0434\u0430     val winner: PlayerType = winLine?.first()?.getState() ?: PlayerType.NONE }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439, \u0441\u0430\u043c\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432 \u043d\u0430\u0448\u0435\u043c SDK, \u043d\u043e \u043d\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u2014 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441\u00a0<strong>Game<\/strong>. \u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u0433\u0440\u044b, \u0441\u0443\u0442\u044c \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u0430 \u0432\u0441\u0435\u043c, \u043a\u0442\u043e \u0438\u0433\u0440\u0430\u043b \u0432 \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0438-\u043d\u043e\u043b\u0438\u043a\u0438. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 3 x 3, \u0432\u044b\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442 \u0442\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0441\u0432\u043e\u0438 \u0437\u043d\u0430\u043a\u0438 \u0432 \u0442\u0440\u0451\u0445 \u043a\u043b\u0435\u0442\u043a\u0430\u0445 \u043f\u043e\u0434\u0440\u044f\u0434.<\/p>\n<p>\u041b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0430\u043a\u0430\u044f, \u0447\u0442\u043e \u043c\u044b:<\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u043b\u0435 \u0438\u0437 \u044f\u0447\u0435\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043a\u043b\u0438\u043a\u0430 \u044d\u0442\u0438\u0445 \u044f\u0447\u0435\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0438 \u043a\u043b\u0438\u043a\u0430 \u0441\u0442\u0430\u0432\u0438\u043c \u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a\u0442\u043e \u043a\u043b\u0438\u043a\u043d\u0443\u043b \u0441 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435\u043c \u043e\u0431 \u044d\u0442\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438\u0433\u0440\u044b;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0438\u0434\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0438 \u0438\u0433\u0440\u044b.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>Class core\/src\/commonMain\/kotlin\/org\/rubicon\/game\/impl\/Game.kt<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"kotlin\">package org.rubicon.game.impl  import org.rubicon.game.IEvent import org.rubicon.game.IGame import org.rubicon.game.impl.events.EventEmitter import org.rubicon.game.impl.events.GameCellEvent import org.rubicon.game.impl.events.GameEventType import org.rubicon.game.impl.events.GameOverEvent import kotlin.js.JsExport  @JsExport class Game : EventEmitter&lt;GameEventType, IGame>(), IGame {     \/\/ \u0421\u0440\u0430\u0437\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u043b\u0435 3 x 3 \u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043a\u043b\u0438\u043a\u0430     private val field: List&lt;List&lt;FieldCell>> = List(3) { y ->         List(3) { x ->             FieldCell(x, y).also {                 it.on(FieldCellEvents.CLICK, this::onClickFieldCell)             }         }     }      \/\/ \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0442\u043e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0445\u043e\u0434\u0438\u0442     private var currentPlayer: PlayerType = PlayerType.CROSS      \/\/ \u0412\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u043d\u044b\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u0438     private val winConditions: List&lt;List&lt;FieldCell>> by lazy {         this.getAllWinConditions()     }      \/**      * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043b\u0438\u043a\u0430 \u043f\u043e ICell      *      * \u041f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044f\u0447\u0435\u0439\u043a\u0438 \u043a\u043b\u0438\u043a\u043d\u0443\u0432\u0448\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430, \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0445\u043e\u0434 \u0438\u0433\u0440\u043e\u043a\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438\u0433\u0440\u044b      *      * *\/     private fun onClickFieldCell(event: IEvent&lt;FieldCellEvents, FieldCell>) {         if (this.currentPlayer != PlayerType.NONE) {             val fieldCell: FieldCell = event.source             this.changeFiledCellState(fieldCell, currentPlayer)             this.turnMove()             this.checkGameOver()         }     }      \/**      * \u041c\u0435\u043d\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043e\u0431 \u044d\u0442\u043e\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c      * *\/     private fun changeFiledCellState(fieldCell: FieldCell, state: PlayerType) {         fieldCell.changeState(state)         this.emit(GameCellEvent(this, fieldCell))     }      \/**      * \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430 \u043d\u0430 \u0435\u0433\u043e \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u0438\u043a\u0430 \u0438\u043b\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e      * *\/     private fun turnMove() {         this.currentPlayer = when (currentPlayer) {             PlayerType.CROSS -> PlayerType.ZERO             PlayerType.ZERO,             PlayerType.NONE -> PlayerType.CROSS         }     }      \/**      * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0438\u0433\u0440\u044b      * *\/     private fun checkGameOver() {         val winLine = this.winConditions.find { this.isMatchLine(it) }         val event = when {             winLine != null -> GameOverEvent(this, winLine)             !hasFreeCells() -> GameOverEvent(this)             else -> null         }         if (event != null) {             this.currentPlayer = PlayerType.NONE             this.emit(event)         }     }      \/**      * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u044f\u0447\u0435\u0435\u043a \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0435 \u043d\u0435 \u043a\u043b\u0438\u043a\u0430\u043b\u0438      * *\/     private fun hasFreeCells(): Boolean {         return this.field.any { row ->             row.any { it.getState() == PlayerType.NONE }         }     }      \/**      * \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u044f \u044f\u0447\u0435\u0435\u043a \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u043e\u0434\u043d\u0438\u043c \u0438\u0433\u0440\u043e\u043a\u043e\u043c      * *\/     private fun isMatchLine(row: List&lt;FieldCell>): Boolean {         if (row.isEmpty()) return false         val firstState = row.first().getState()         if (firstState == PlayerType.NONE) return false         return row.all { it.getState() == firstState }     }      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u043d\u044b\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438      * *\/     private fun getAllWinConditions(): List&lt;List&lt;FieldCell>> {         val result: ArrayList&lt;List&lt;FieldCell>> = arrayListOf()         val diagonal: ArrayList&lt;FieldCell> = arrayListOf()         val diagonalOpposite: ArrayList&lt;FieldCell> = arrayListOf()         for (i in 0..2) {             \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u0447\u043a\u0438             result.add(                 listOf(                     this.field[i][0],                     this.field[i][1],                     this.field[i][2],                 )             )             \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438             result.add(                 listOf(                     this.field[0][i],                     this.field[1][i],                     this.field[2][i],                 )             )             \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043f\u043e \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u0438             diagonal.add(this.field[i][i])             diagonalOpposite.add(this.field[2 - i][i])         }         result.add(diagonal)         result.add(diagonalOpposite)         return result     }      \/**      * \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0433\u0440\u0443 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u043b\u043e \u043f\u043e\u043b\u0435      * *\/     override fun play() {         \/\/ \u0421\u0443\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f         \/\/ \u041f\u043e\u044d\u0442\u043e\u043c\u0443 reset \u0441\u044e\u0434\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442         this.reset()     }      \/**      * \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044f\u0447\u0435\u0435\u043a \u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0438 \u043a\u0435\u043c \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043e      * *\/     override fun reset() {         this.currentPlayer = PlayerType.CROSS         for (y in 0 until this.field.size) {             for (x in 0 until this.field[y].size) {                 this.changeFiledCellState(this.field[y][x], PlayerType.NONE)             }         }     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u0441\u0451, SDK \u0433\u043e\u0442\u043e\u0432, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f Kotlin. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 JS.<\/p>\n<p><a class=\"anchor\" name=\"sdk-implements\" id=\"sdk-implements\"><\/a><\/p>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f SDK \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445<\/h4>\n<p><a class=\"anchor\" name=\"js-implement\" id=\"js-implement\"><\/a><\/p>\n<p><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 JS<\/strong><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u0442\u043e\u0433\u043e\u0432\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u043e\u0434 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 JS, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 gradle\u00a0<strong>jsBrowserProductionWebpack<\/strong>:<\/p>\n<pre><code>.\/gradlew jsBrowserProductionWebpack<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0443 \u0432\u0430\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f js-\u0444\u0430\u0439\u043b \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044f\u00a0<strong><em>core\/build\/distributions\/core.js<\/em><\/strong>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/d0a\/f22\/e53\/d0af22e539310a494a1c73c461787dea.jpeg\" width=\"538\" height=\"483\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d0a\/f22\/e53\/d0af22e539310a494a1c73c461787dea.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418\u043b\u0438 \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u0442 \u043e\u0442 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438, \u0442\u043e \u0442\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0431\u0440\u0430\u0442\u044c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u043e \u043f\u0443\u0442\u0438\u00a0<strong><em>build\/js\/packages\/tictactoe-core<\/em><\/strong><em>, <\/em>\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c npm \u043f\u0430\u043a\u0435\u0442\u043e\u043c c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 JS, \u0444\u0430\u0439\u043b\u043e\u043c\u00a0package.json\u00a0\u0438 *.d.ts-\u0444\u0430\u0439\u043b\u043e\u043c \u0432\u043d\u0443\u0442\u0440\u0438.<\/p>\n<p>\u041e\u0431\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 js. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u044d\u0442\u0438\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u0432 \u043b\u044e\u0431\u043e\u0439 js-\u043f\u0440\u043e\u0435\u043a\u0442. \u0427\u0442\u043e \u043c\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c.<\/p>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 js \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u2014 \u044d\u0442\u043e \u043e\u0434\u043d\u0430\u00a0<strong>index.html<\/strong>\u00a0\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 SDK \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f html-\u0442\u0435\u0433\u0430\u00a0<em>script<\/em>. \u0412 \u044d\u0442\u043e\u043c \u0436\u0435 \u0444\u0430\u0439\u043b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 SDK. \u0423\u0432\u0435\u0440\u0435\u043d, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u0435\u0435 \u0438 \u0447\u0438\u0449\u0435, \u043d\u043e \u044d\u0442\u043e \u043b\u0438\u0448\u044c \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 SDK, \u0430 \u043d\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>index.js<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;!DOCTYPE html> &lt;head>     &lt;meta charset=\"UTF-8\">     &lt;title>Tic Tac Toe&lt;\/title>     &lt;!--  \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u0440\u0430\u043d\u0435\u0435 SDK  -->     &lt;script src=\"..\/..\/core\/build\/distributions\/core.js\">&lt;\/script>     &lt;!--  \u041e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0441\u0442\u0438\u043b\u0438 \u043f\u043e\u043b\u044f \u0438 \u044f\u0447\u0435\u0435\u043a \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f  -->     &lt;style>         .field {             display: flex;             flex-wrap: wrap;             align-content: flex-start;             width: 900px;             height: 900px;             background-color: #e6e6e6;             border-radius: 10px;             padding: 10px 0 0 10px;          }          .field-cell {             color: black;             width: 290px;             height: 290px;             background-color: #a7c6c6;             margin: 0 10px 10px 0;             border-radius: 10px;             cursor: pointer;         }          #crossIcon, #circleIcon {             display: none;         }     &lt;\/style> &lt;\/head> &lt;!-- \u0421\u044e\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 --> &lt;div id=\"result\">&lt;\/div> &lt;!-- \u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0441\u044e\u0434\u0430 \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0435 \u0437\u0430\u043a\u0438\u043d\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e\u043b\u044f --> &lt;div class=\"field\" id=\"field\">&lt;\/div> &lt;!-- \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0438\u043a\u043e\u043d\u043a\u0438 X \u0438 O \u0432 HTML \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 --> &lt;div id=\"crossIcon\">     &lt;svg class=\"svg-icon\"          style=\"width: 100%; height: auto;vertical-align: middle;fill: currentColor;overflow: hidden;\"          viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">         &lt;path d=\"M810.65984 170.65984q18.3296 0 30.49472 12.16512t12.16512 30.49472q0 18.00192-12.32896 30.33088l-268.67712 268.32896 268.67712 268.32896q12.32896 12.32896 12.32896 30.33088 0 18.3296-12.16512 30.49472t-30.49472 12.16512q-18.00192 0-30.33088-12.32896l-268.32896-268.67712-268.32896 268.67712q-12.32896 12.32896-30.33088 12.32896-18.3296 0-30.49472-12.16512t-12.16512-30.49472q0-18.00192 12.32896-30.33088l268.67712-268.32896-268.67712-268.32896q-12.32896-12.32896-12.32896-30.33088 0-18.3296 12.16512-30.49472t30.49472-12.16512q18.00192 0 30.33088 12.32896l268.32896 268.67712 268.32896-268.67712q12.32896-12.32896 30.33088-12.32896z\"\/>     &lt;\/svg> &lt;\/div> &lt;div id=\"circleIcon\">     &lt;svg class=\"svg-icon\"          style=\"width: 100%; height: auto;vertical-align: middle;fill: currentColor;overflow: hidden;\"          viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">         &lt;path d=\"M512 85.333333a426.666667 426.666667 0 1 0 426.666667 426.666667A426.666667 426.666667 0 0 0 512 85.333333z m0 768a341.333333 341.333333 0 1 1 341.333333-341.333333 341.333333 341.333333 0 0 1-341.333333 341.333333z\"\/>     &lt;\/svg> &lt;\/div>  &lt;body> &lt;script>     \/**      * \u041e\u0431\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a SDK \u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0442\u043e \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0433\u0440\u044b      * *\/     const sdk = window.core.org.rubicon.game.impl     const {Game, PlayerType} = sdk     const {GameEventType} = sdk.events      \/\/ \u0418\u043a\u043e\u043d\u043a\u0438 \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u043e\u0432 \u0438 \u043d\u043e\u043b\u0438\u043a\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u044f\u0447\u0435\u0439\u043a\u0438     const crossSVG = document.getElementById(\"crossIcon\").innerHTML;     const circleSymbol = document.getElementById(\"circleIcon\").innerHTML;      \/\/ \u0421\u044e\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c HTML \u043a\u043d\u043e\u043f\u043a\u0438     \/\/ \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0448\u043b\u0438 \u043d\u0430\u0448\u0443 \u043a\u043d\u043e\u043f\u043a\u0443     \/\/ \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435     const buttonMap = new Map()      \/**      * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0438\u0433\u0440\u044b      *      * \u0412\u044b\u0432\u043e\u0434\u0438\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0430 \u0438\u0433\u0440\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443      * *\/     function gameOver(event) {         \/\/ \u0414\u043e\u0441\u0442\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u043e\u0431\u044b\u0442\u0438\u044f         const {winner, source} = event         const winnerText = document.createElement(\"H3\")         \/\/ \u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 \u0438\u0433\u0440\u043e\u043a\u0430 \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c \u043a\u0442\u043e \u0432\u044b\u0438\u0433\u0440\u0430\u043b         switch (winner) {             case PlayerType.NONE:                 winnerText.innerText = \"\u041d\u0438\u0447\u044c\u044f\"                 break             case PlayerType.CROSS:                 winnerText.innerText = \"\u0412\u044b\u0438\u0433\u0440\u0430\u043b\u0438 \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0438\"                 break             case PlayerType.ZERO:                 winnerText.innerText = \"\u0412\u044b\u0438\u0433\u0440\u0430\u043b\u0438 \u043d\u043e\u043b\u0438\u043a\u0438\"                 break         }         \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430         const resultElement = document.getElementById(\"result\")         const repeatButton = document.createElement(\"button\")         repeatButton.innerText = \"\u0418\u0433\u0440\u0430\u0442\u044c \u0435\u0449\u0435 \u0440\u0430\u0437\"         repeatButton.addEventListener(\"click\", () => {             source.reset()             resultElement.innerHTML = \"\"         })         \/\/ \u0412\u044b\u0432\u043e\u0434\u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u043a\u043d\u043e\u043f\u043a\u0443         resultElement.appendChild(winnerText)         resultElement.appendChild(repeatButton)     }      \/**      * \u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u044f\u0447\u0435\u0439\u043a\u0443 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043f\u043e ui \u043a\u043d\u043e\u043f\u043a\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0441\u044f \u043a\u043b\u0438\u043a \u044f\u0447\u0435\u0439\u043a\u0438 \u0438\u0437 SDK      * *\/     function createUICell(hash, fieldCell) {         const htmlCell = document.createElement(\"div\")         htmlCell.classList.add(\"field-cell\")         htmlCell.addEventListener(\"mousedown\", () => fieldCell.click())         document.getElementById(\"field\").appendChild(htmlCell)         buttonMap.set(hash, htmlCell)     }      \/**      *  \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0443\u0442\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u044f\u0447\u0435\u0435\u043a      * *\/     function updateView(event) {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0443         const {fieldCell} = event         const cellHash = `${fieldCell.getY()}-${fieldCell.getX()}`         if (!buttonMap.has(cellHash)) {             \/\/ \u0435\u0441\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u0434\u0430\u043d\u043d\u0443\u044e \u044f\u0447\u0435\u0439\u043a\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u043c html \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u0438             createUICell(cellHash, fieldCell)         }         \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 html \u043a\u043d\u043e\u043f\u043a\u0438         const uiElement = buttonMap.get(cellHash)         switch (fieldCell.getState()) {             case PlayerType.NONE:                 uiElement.innerHTML = \"\"                 break             case PlayerType.CROSS:                 uiElement.innerHTML = crossSVG                 break             case PlayerType.ZERO:                 uiElement.innerHTML = circleSymbol                 break         }     }      \/**      * \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438\u0433\u0440\u0443      * *\/     const game = new Game()     \/**      * \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f      * *\/     game.on(GameEventType.GAME_OVER, gameOver)     game.on(GameEventType.CHANGE_CELL, updateView)     \/**      * \u0418 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c      * *\/     game.play() &lt;\/script> &lt;\/body> &lt;\/html><\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e (\u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f SDK) \u043c\u044b \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 Kotlin \u043a\u043e\u0434 \u0432 JS \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/560\/e4e\/b70\/560e4eb708350f69bdd392019c0f3075.gif\" width=\"566\" height=\"604\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/560\/e4e\/b70\/560e4eb708350f69bdd392019c0f3075.gif\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0434 iOS.<\/p>\n<p><a class=\"anchor\" name=\"swift-implement\" id=\"swift-implement\"><\/a><\/p>\n<p><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Swift<\/strong><\/p>\n<p>\u041a\u0430\u043a \u0438 \u0434\u043b\u044f js \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434 \u043d\u0430 Kotlin \u0432 Framework, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u0440\u0443\u0436\u0438\u0442\u044c Xcode, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">.\/gradlew linkReleaseFrameworkIosArm64 linkReleaseFrameworkIosX64 &amp;&amp; xcodebuild -create-xcframework  -framework .\/core\/build\/bin\/iosArm64\/releaseFramework\/GAMEFramework.framework  -framework .\/core\/build\/bin\/iosX64\/releaseFramework\/GAMEFramework.framework  -output .\/core\/build\/bin\/core.xcframework<\/code><\/pre>\n<p>\u0413\u0434\u0435\u00a0<code>inkReleaseFrameworkIosArm64<\/code>\u00a0\u0438\u00a0<code>linkReleaseFrameworkIosX64<\/code>\u00a0\u2014 \u044d\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u043f\u043e\u0434 \u0446\u0435\u043b\u0435\u0432\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b iOS, \u0430\u00a0<code>xcodebuild\u00a0<\/code>\u2014 \u0441\u043a\u043b\u0435\u0439\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u043e\u0442 \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b <em>*.framework<\/em> \u0432 \u043e\u0434\u0438\u043d *<em>.xcframework<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u043c \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 kotlin \u0432 swift-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 .xcframework \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 swift. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 iOS-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 Xcode.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/6c3\/a09\/9c9\/6c3a099c911c8f4145b8379c2dc1b49c.jpeg\" width=\"1398\" height=\"900\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6c3\/a09\/9c9\/6c3a099c911c8f4145b8379c2dc1b49c.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 SwiftUI.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/1a2\/52e\/cd2\/1a252ecd2225566aa93d3449364a5fc4.jpeg\" width=\"729\" height=\"521\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1a2\/52e\/cd2\/1a252ecd2225566aa93d3449364a5fc4.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0448 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 framework \u0432 \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u041a\u043b\u0438\u043a\u0430\u0435\u043c \u043d\u0430 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043a\u043b\u0438\u043a\u0430\u0435\u043c\u00a0<strong>+<\/strong>\u00a0\u0432 \u043f\u0443\u043d\u043a\u0442\u0435\u00a0<strong>Frameworks, Libraries and Embedded content<\/strong>. \u0412 \u043e\u0442\u043a\u0440\u044b\u0432\u0448\u0435\u043c\u0441\u044f \u043e\u043a\u043d\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c\u00a0<strong>Add<\/strong>\u00a0<strong>other<\/strong>\u00a0\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u043d\u0435\u0435 \u043f\u0430\u043f\u043a\u0443\u00a0<strong><em>.\/core\/build\/bin\/core.xcframework<\/em><\/strong>;<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u2014 \u043d\u0430\u0448 framework \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435.<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/721\/004\/de4\/721004de4eb71434fed3bf3a5d452234.jpeg\" width=\"1789\" height=\"1021\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/721\/004\/de4\/721004de4eb71434fed3bf3a5d452234.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a framework \u0431\u044b\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 swift \u043a\u043e\u0434\u0435. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c baseName, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0432\u00a0<strong><em>.\/core\/build.gradle.kts<\/em><\/strong>. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 SDK \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 iOS. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0444\u0430\u0439\u043b\u00a0<strong>ContentView<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Xcode \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u043b \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041f\u0438\u0448\u0435\u043c \u0432 \u043d\u0451\u043c \u043a\u043e\u0434:<\/p>\n<details class=\"spoiler\">\n<summary>ContentView.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import SwiftUI \/\/ \u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 SDK \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0430 Kotlin import GAMEFramework  \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 SDK \u0438 \u0447\u0442\u043e\u0431\u044b View \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u043b\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043d\u0435\u0433\u043e class GameUI : ObservableObject {     \/\/ \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043e view     @Published var isGameOver: Bool = false     @Published var isGameStarted: Bool = false     @Published var winnerName: String = \"\"     @Published var field: [[String]] = [         [\" \", \" \", \" \"],         [\" \", \" \", \" \"],         [\" \", \" \", \" \"]     ]     \/\/ \u0418\u0433\u0440\u0430     private let game: Game = Game()     \/\/ \u042f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e\u043b\u044f     private var gameCells: [String: FieldCell] = [:]      \/\/ \u041f\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0438\u0433\u0440\u0430\u0442\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434     func start () {         do {             \/\/ \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u044f\u0447\u0435\u0435\u043a \u0438 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0438\u0433\u0440\u044b             try game.on(eventType: .changeCell, callBack: onChangeCell)             try game.on(eventType: .gameOver, callBack: onGameOver)         } catch {             print(\"\u041e\u0448\u0438\u0431\u043a\u0430\")         }         \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0438\u0433\u0440\u044b         game.play()         isGameStarted = true     }      \/\/ \u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b     func playAgain() {         isGameOver = false         game.reset()     }      \/\/ view \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043a\u0430\u043a\u0430\u044f \u043a\u043d\u043e\u043f\u043a\u0430 \u0431\u044b\u043b\u0430 \u043d\u0430\u0436\u0430\u0442\u0430,     \/\/ \u0430 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0431\u0443\u0434\u0443\u0442 \u0443\u0436\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0443 \u044f\u0447\u0435\u043a\u0438 \u043f\u043e\u043b\u044f \u0438\u0437 SDK     func clickButton(x: Int, y: Int) {         if (isGameOver || !isGameStarted) {             return         }         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c FieldCell \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0443 \u043d\u0435\u0433\u043e click         gameCells[makeHash(x: x, y: y)]?.click()     }      \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f     private func onChangeCell(event: IEvent) {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u044f\u0447\u0435\u043a\u0443 \u0438\u0437 \u0441\u043e\u0431\u044b\u0442\u0438\u044f         let fieldCell = (event as! GameCellEvent).fieldCell         \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0445\u0435\u0448 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u043c\u0430\u043f\u0443 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c         let hash = makeHash(x: Int(fieldCell.getX()), y: Int(fieldCell.getY()))         if (!gameCells.keys.contains(hash)) {             gameCells[hash] = fieldCell         }         \/\/ \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0442\u043e\u0431\u044b view \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u043b \u044f\u0447\u0435\u0439\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430\u0441\u044c         field[Int(fieldCell.getY())][Int(fieldCell.getX())] = stateToString(state: fieldCell.getState())     }      \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0438\u0433\u0440\u044b     private func onGameOver(event: IEvent) {         \/\/ \u0421\u0442\u0430\u0432\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0438\u0433\u0440\u044b \u0447\u0442\u043e\u0431\u044b \u0438\u0433\u0440\u043e\u043a \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043c\u043e\u0433 \u043a\u043b\u0438\u043a\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0438         isGameOver = true         \/\/ \u0418 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432\u044b\u0438\u0433\u0440\u0430\u0432\u0448\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443         switch ((event as! GameOverEvent).winner) {         case .zero:             winnerName = \"O \u043f\u043e\u0431\u0435\u0434\u0438\u043b\u0438\"         case .cross:             winnerName = \"X \u043f\u043e\u0431\u0435\u0434\u0438\u043b\u0438\"         default:             winnerName = \"\u041d\u0438\u0447\u044c\u044f\"         }     }      \/\/ \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044f\u0447\u0435\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043a\u043d\u043e\u043f\u043a\u0435     private func stateToString(state: PlayerType) -> String {         switch state {         case .cross:             return \"X\"         case .zero:             return \"O\"         default:             return \" \"         }     }      private func makeHash(x: Int, y: Int) -> String {         return String(x) + \"-\" + String(y)     } }  \/\/ \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 struct ContentView: View {     @ObservedObject var gameUI = GameUI()     var body: some View {         VStack(alignment: .center) {             \/\/ \u0411\u043b\u043e\u043a \u044f\u0447\u0435\u0435\u043a \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u0432 \u0446\u0438\u043a\u043b\u0435 \u043f\u043e\u043b\u0435 3 \u0445 3             ForEach((0...2), id: \\.self) { y in                 HStack(spacing: 5) {                     Group {                         ForEach((0...2), id: \\.self) { x  in                             Button(action: { gameUI.clickButton(x: x, y: y) }) {                                 \/\/ \u041e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u044e\u0449\u0435\u0435 \u044f\u0447\u0435\u0439\u043a\u0438                                 Text(gameUI.field[y][x])                             }                         }                     }                     \/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043d\u043e\u043f\u043e\u043a                     .frame(maxWidth:.infinity)                     .padding()                     .foregroundColor(Color.black)                     .font(.system(size: 64, weight: .bold, design: .default))                     .background(Color(red: 0.654, green: 0.654, blue: 0.776))                     .cornerRadius(5)                 }             }.opacity(gameUI.isGameStarted ? 1 : 0)             \/\/ \u0412\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0438\u0433\u0440\u044b \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b             Group {                 Text(gameUI.winnerName)                 Button(\"again\", action: gameUI.playAgain)             }.opacity(gameUI.isGameOver ? 1 : 0)             \/\/ \u041a\u043d\u043e\u043f\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b             Button(\"play\", action: gameUI.start)                 .font(.system(size: 32, weight: .bold, design: .default))                 .opacity(gameUI.isGameStarted ? 0 : 1)         }     } }  struct ContentView_Previews: PreviewProvider {     static var previews: some View {         ContentView()     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043d\u0435 \u0441\u0442\u043e\u0438\u043b\u043e \u043f\u0438\u0445\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b: \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u043e \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0434\u0435\u043c\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442 \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u0435\u0441\u0442\u044c. \u0412 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8b4\/fd3\/5ee\/8b4fd35eedfd84c5da6f39950370bc49.gif\" width=\"296\" height=\"640\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8b4\/fd3\/5ee\/8b4fd35eedfd84c5da6f39950370bc49.gif\"\/><figcaption><\/figcaption><\/figure>\n<p><a class=\"anchor\" name=\"java-implement\" id=\"java-implement\"><\/a><\/p>\n<p><strong>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Java<\/strong><\/p>\n<p>\u041d\u0435\u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438 \u043c\u0430\u0445\u0438\u043d\u0430\u0446\u0438\u044f\u043c\u0438 \u043c\u044b \u0443\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 js \u0438 swift, \u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043d\u043e \u043d\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0438\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u0420\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0435\u0442 \u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043f\u043e\u0434 Android, \u0438 \u043f\u043e-\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kotlin \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u043e\u0434 Android, \u043a\u0430\u043a\u00a0<a href=\"https:\/\/developer.android.com\/kotlin\/first\">\u043e\u0431\u044a\u044f\u0432\u0438\u043b Google<\/a>\u00a0\u0432 2019 \u0433\u043e\u0434\u0443, \u043d\u043e \u043c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0435\u0433\u043e \u043d\u0430 Java, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e SDK c java.<\/p>\n<p>\u041d\u0435\u0441\u043b\u043e\u0436\u043d\u043e \u0434\u043e\u0433\u0430\u0434\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0434\u043b\u044f JVM \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d .jar-\u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442. \u0427\u0442\u043e\u0431\u044b \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">.\/gradlew jvmJar<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0432 \u043f\u0430\u043f\u043a\u0435\u00a0<strong><em>core\/libs<\/em><\/strong>\u00a0\u0431\u0443\u0434\u0435\u0442 \u0444\u0430\u0439\u043b <strong><em>core-jvm-1.0.0.jar<\/em><\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0412 \u0432\u0430\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f, \u043d\u043e \u0444\u0430\u0439\u043b \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0443 \u00abjvm\u00bb.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/d5a\/3e7\/0c9\/d5a3e70c958ed93b07d90f279b35cac1.jpeg\" width=\"367\" height=\"530\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d5a\/3e7\/0c9\/d5a3e70c958ed93b07d90f279b35cac1.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 Android \u0431\u0443\u0434\u0435\u043c \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u0432 Android Studio. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c\u00a0<strong>Empty<\/strong>\u00a0<strong>Activity<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/9af\/8a0\/e41\/9af8a0e411d2052d57e73c7f91095faa.jpeg\" width=\"902\" height=\"648\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9af\/8a0\/e41\/9af8a0e411d2052d57e73c7f91095faa.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u044f\u0437\u044b\u043a Java.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/8bf\/3e7\/b9d\/8bf3e7b9d5a0be276cfb0b3d40c70d23.jpeg\" width=\"904\" height=\"647\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8bf\/3e7\/b9d\/8bf3e7b9d5a0be276cfb0b3d40c70d23.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u2014 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u00a0<strong><em>build.gradle<\/em><\/strong>. \u0412 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u043a Android-\u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0444\u0430\u0439\u043b \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <strong><em>Gradle Script<\/em><\/strong> \u2192 <strong><em>build.gradle (Module: TicTacToe.app)<\/em><\/strong>.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ad9\/ada\/32b\/ad9ada32b361c858c869fd95b0994710.jpeg\" width=\"436\" height=\"328\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ad9\/ada\/32b\/ad9ada32b361c858c869fd95b0994710.jpeg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u0434\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b dependencies. \u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043d\u0430\u00a0<code>kotlin-stdlib<\/code>\u00a0\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u0438\u0437 java \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u041f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 kotlin \u043b\u044f\u043c\u0431\u0434\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u00a0<code>Function1<\/code>), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u0411\u0435\u0437\u00a0<code>kotlin-stdlib<\/code>\u00a0\u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0438, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043c\u044b \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c, \u0430 \u0431\u0435\u0437 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430\u0448\u0430 \u0438\u0433\u0440\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043d\u0430\u00a0<code>kotlin-stdlib<\/code>, \u0442\u043e \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u00a0<code>IEventEmitter<\/code>\u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0435 \u043b\u044f\u043c\u0431\u0434\u0443, \u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>build.gradle (Module: TicTacToe.app)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">plugins {     id 'com.android.application' }  android {     compileSdk 32      defaultConfig {         applicationId \"com.example.tictactoe\"         minSdk 29         targetSdk 32         versionCode 1         versionName \"1.0\"          testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"     }      buildTypes {         release {             minifyEnabled false             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'         }     }     compileOptions {         sourceCompatibility JavaVersion.VERSION_1_8         targetCompatibility JavaVersion.VERSION_1_8     } }  dependencies {     \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043d\u0430 \u043d\u0430\u0448 SDK     implementation files('..\/..\/..\/core\/build\/libs\/core-jvm-1.0.0.jar')     \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 Kotlin \u043b\u044f\u043c\u0431\u0434     implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.7.10'      implementation 'androidx.appcompat:appcompat:1.3.0'     implementation 'com.google.android.material:material:1.4.0'     implementation 'androidx.constraintlayout:constraintlayout:2.0.4'     implementation files('..\/core\/build\/libs\/')     testImplementation 'junit:junit:4.13.2'     androidTestImplementation 'androidx.test.ext:junit:1.1.3'     androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 ide \u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 gradle \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043a\u043e\u0434\u0430 ide \u043f\u043e\u043d\u0438\u043c\u0430\u043b\u0430 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043d\u0430\u0448\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445:<\/p>\n<pre><code class=\"bash\">gradle --refresh-dependencies<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438 \u00ab\u0438\u0433\u0440\u0430\u0442\u044c\u00bb, \u00ab\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u00bb \u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c \u043f\u043e\u043b\u0435\u043c \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u041a\u043d\u043e\u043f\u043a\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>Layout activity_main.xml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"xml\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?> &lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"                                                    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"                                                    xmlns:tools=\"http:\/\/schemas.android.com\/tools\"                                                    android:layout_width=\"match_parent\"                                                    android:layout_height=\"match_parent\"                                                    tools:context=\".MainActivity\">      &lt;LinearLayout             android:id=\"@+id\/mainLinearLayout\"             android:layout_width=\"match_parent\"             android:layout_height=\"match_parent\"             android:orientation=\"vertical\">          &lt;LinearLayout                 android:id=\"@+id\/fieldLinearLayout\"                 android:visibility=\"invisible\"                 android:layout_width=\"match_parent\"                 android:layout_height=\"wrap_content\"                 android:orientation=\"vertical\">             &lt;!-- \u0421\u044e\u0434\u0430 \u0431\u0443\u0434\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0438 -->         &lt;\/LinearLayout>           &lt;!-- \u041a\u043d\u043e\u043f\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b -->         &lt;Button                 android:id=\"@+id\/buttonPlay\"                 android:layout_width=\"match_parent\"                 android:layout_height=\"wrap_content\"                 android:text=\"@string\/play\"\/>          &lt;!-- \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u0435 -->         &lt;TextView                 android:id=\"@+id\/textWinner\"                 android:layout_width=\"match_parent\"                 android:layout_height=\"wrap_content\"                 android:textAlignment=\"center\"                 android:textSize=\"32sp\"                 android:visibility=\"invisible\"\/>          &lt;!-- \u041a\u043d\u043e\u043f\u043a\u0430 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b -->         &lt;Button                 android:id=\"@+id\/buttonPlayAgain\"                 android:visibility=\"invisible\"                 android:layout_width=\"match_parent\"                 android:layout_height=\"wrap_content\"                 android:text=\"@string\/play_again\"\/>      &lt;\/LinearLayout> &lt;\/androidx.constraintlayout.widget.ConstraintLayout><\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 Java, \u0441\u0443\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0436\u0435, \u0432 \u0447\u0435\u043c \u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 \u2014 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043c\u043e\u0441\u0442 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438 SDK. \u0415\u0441\u043b\u0438 \u0447\u0443\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435, \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 \u043a\u043d\u043e\u043f\u043e\u043a. \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043b\u0438\u043a\u0430 \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0430\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u044f\u0447\u0435\u0439\u043a\u0435 \u0432 SDK.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f SDK. \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u044d\u0442\u0438\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>Class MainActivity.java<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">package com.example.tictactoe;  import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;  import android.os.Bundle; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView;  import org.rubicon.game.impl.FieldCell; import org.rubicon.game.impl.Game; import org.rubicon.game.impl.events.GameCellEvent; import org.rubicon.game.impl.events.GameEventType; import org.rubicon.game.impl.events.GameOverEvent;  import java.util.LinkedHashMap;  import kotlin.Unit; import kotlin.jvm.functions.Function1;  public class MainActivity extends AppCompatActivity {     \/\/ \u0421\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0438\u0433\u0440\u044b \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430     final private Game game = new Game();     \/\/ \u0417\u0434\u0435\u0441\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u043a\u043d\u043e\u043f\u043a\u0438 \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043a \u043d\u0438\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0438 \u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     final private LinkedHashMap&lt;String, Button> uiButtons = new LinkedHashMap&lt;>();      \/\/ \u0422\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0432 View     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u043e\u043b\u0435         this.createButtons();          \/\/ \u041f\u043e \u043a\u043b\u0438\u043a\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438\u0433\u0440\u044b \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438\u0433\u0440\u0443         final Button buttonPlay = findViewById(R.id.buttonPlay);         buttonPlay.setOnClickListener(v -> {             game.on(GameEventType.GAME_OVER, onGameOver);             game.on(GameEventType.CHANGE_CELL, onGameCellChange);             game.play();             buttonPlay.setVisibility(View.INVISIBLE);             findViewById(R.id.fieldLinearLayout).setVisibility(View.VISIBLE);         });          \/\/ \u041f\u043e \u043a\u043b\u0438\u043a\u0443 \u043a\u043d\u043e\u043f\u043a\u0438 \u0438\u0433\u0440\u0430\u0442\u044c \u043e\u043f\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438\u0433\u0440\u0443         final Button buttonPlayAgain = findViewById(R.id.buttonPlayAgain);         buttonPlayAgain.setOnClickListener(v -> {             findViewById(R.id.textWinner).setVisibility(View.INVISIBLE);             game.reset();             buttonPlayAgain.setVisibility(View.INVISIBLE);         });     }      \/\/ \u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0435 \u0438\u0433\u0440\u044b     private final Function1 onGameOver = o -> {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u043e\u0431\u0435\u0434\u0438\u0442\u0435\u043b\u0435         final GameOverEvent event = (GameOverEvent) o;         String winnerMessage = \"\";         switch (event.getWinner()) {             case NONE:                 winnerMessage = \"\u041d\u0438\u0447\u044c\u044f\";                 break;             case ZERO:                 winnerMessage = \"\u0412\u044b\u0438\u0433\u0440\u0430\u043b\u0438 O\";                 break;             case CROSS:                 winnerMessage = \"\u0412\u044b\u0438\u0433\u0440\u0430\u043b\u0438 X\";                 break;         }         \/\/ \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435         final TextView textView = findViewById(R.id.textWinner);         textView.setText(winnerMessage);         textView.setVisibility(View.VISIBLE);         findViewById(R.id.buttonPlayAgain).setVisibility(View.VISIBLE);         return Unit.INSTANCE;     };      \/\/ \u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f     private final Function1 onGameCellChange = o -> {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u044f\u0447\u0435\u0439\u043a\u0435         final GameCellEvent event = (GameCellEvent) o;         final FieldCell fieldCell = event.getFieldCell();         final String hash = makeHash(fieldCell.getX(), fieldCell.getY());         \/\/ \u0414\u0430\u043b\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u044e\u0449\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443         final Button uiButton = this.uiButtons.get(hash);         if (uiButton == null) {             return Unit.INSTANCE;         }         if (!uiButton.hasOnClickListeners()) {             uiButton.setOnClickListener(view -> {                 fieldCell.click();             });         }         switch (event.getFieldCell().getState()) {             case NONE:                 uiButton.setText(\"\");                 break;             case ZERO:                 uiButton.setText(\"O\");                 break;             case CROSS:                 uiButton.setText(\"X\");                 break;         }         return Unit.INSTANCE;     };      @NonNull     private String makeHash(int x, int y) {         return String.format(\"%s-%s\", x, y);     }      \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435     private void createButtons() {         final LinearLayout rowLayout = findViewById(R.id.fieldLinearLayout);         for (int y = 0; y &lt; 3; y++) {             final LinearLayout row = new LinearLayout(this);             for (int x = 0; x &lt; 3; x++) {                 final Button button = new Button(this);                 button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 64);                 row.addView(button, new LinearLayout.LayoutParams(                         ViewGroup.LayoutParams.WRAP_CONTENT,                         ViewGroup.LayoutParams.WRAP_CONTENT,                         1.0f                 ));                 \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c                 uiButtons.put(makeHash(x, y), button);             }             rowLayout.addView(row, new LinearLayout.LayoutParams(                     ViewGroup.LayoutParams.MATCH_PARENT,                     ViewGroup.LayoutParams.WRAP_CONTENT             ));         }     } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c. \u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9e5\/2d1\/40a\/9e52d140aaca82bac79dc1cc9889e0b1.gif\" width=\"330\" height=\"671\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9e5\/2d1\/40a\/9e52d140aaca82bac79dc1cc9889e0b1.gif\"\/><figcaption><\/figcaption><\/figure>\n<p><a class=\"anchor\" name=\"result\" id=\"result\"><\/a><\/p>\n<h3>\u0418\u0442\u043e\u0433<\/h3>\n<p>\u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0435\u0434\u0438\u043d\u043e\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u043e\u0439. \u041f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0432\u043d\u0435\u0441\u0442\u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043b\u043e\u0433\u0438\u043a\u0443 \u043c\u044b \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u044d\u0442\u043e \u0441\u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u043e\u0431\u0449\u0435\u043c \u043a\u043e\u0434\u0435. \u0412\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u0430\u043c\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e SDK \u0438 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c. \u0410 \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u043d\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 \u0438\u0437 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-dsl-reference.html#targets\">\u0441\u0430\u0439\u0442\u0435<\/a>, \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u043e\u0434 \u043d\u0443\u0436\u043d\u0443\u044e \u043d\u0430\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043d\u0435\u0439.<\/p>\n<p>\u041e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0438\u0437 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445: \u043e\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u0443\u0448\u0438 \u0434\u043e \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438. \u0414\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 API, \u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 User, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438. \u041f\u043b\u044e\u0441 \u0431\u0443\u0434\u0435\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u0435\u043d \u0432\u044b\u043d\u043e\u0441 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0441\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0432\u0435\u043b \u0432\u0430\u0441 \u0432 \u043a\u0443\u0440\u0441 \u0434\u0435\u043b\u0430 \u043f\u043e Kotlin Multiplatform, \u0438, \u043f\u0440\u043e\u0447\u0442\u044f \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e + \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0432 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b, \u0432\u044b \u043f\u043e\u0439\u043c\u0435\u0442\u0435, \u043d\u0443\u0436\u043d\u0430 \u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u0430 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f \u0438\u043b\u0438 \u043d\u0435\u0442 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<p>P.S. \u0415\u0441\u043b\u0438 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u2014 \u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438, \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/rostelecom\/blog\/682160\/\"> https:\/\/habr.com\/ru\/company\/rostelecom\/blog\/682160\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0430\u043a\u043e\u0439 \u0435\u0441\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a \u0443 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439, front-end \u0438 back-end \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u0440\u0430\u0441\u043f\u0438\u043b\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432? \u0414\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438. \u041e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u044f \u0432\u0438\u0434\u0435\u043b \u0441\u0442\u0430\u0442\u044c\u0438 \u0438\u043b\u0438 \u043d\u043e\u0432\u043e\u0441\u0442\u0438, \u0433\u0434\u0435 \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0436\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043a\u0430\u0442\u0438\u0442\u044c \u0440\u0435\u043b\u0438\u0437. \u0418 \u0435\u0441\u043b\u0438 \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u0432\u0441\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438 \u0435\u0441\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0442\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c? \u041e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438 \u0442\u0430\u043c.<\/p>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u0438\u043c\u0435\u0442\u044c \u0434\u0443\u0431\u043b\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0447\u0442\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 Kotlin Multiplatform \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432\u0441\u0435\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0439 \u0438\u0433\u0440\u044b \u00ab\u041a\u0440\u0435\u0441\u0442\u0438\u043a\u0438-\u043d\u043e\u043b\u0438\u043a\u0438\u00bb \u043d\u0430 \u0442\u0440\u0435\u0445 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 Browser (JS), iOS (Swift) \u0438 Android (Java) \u0441 \u043e\u0431\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043d\u0430 Kotlin.<\/p>\n<h3>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h3>\n<ul>\n<li>\n<p><a href=\"#about\">\u041e\u0431 \u0430\u0432\u0442\u043e\u0440\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#why-kotlin\">\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e Kotlin Multiplatform<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#practice\">\u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0430<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#create-project\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#environment\">\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#create-project-more\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#build-settings\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"#write-code\">\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#design\">\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sdk\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f SDK<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#sdk-implements\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f SDK \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445<\/a><\/p>\n<ul>\n<li>\n<p><a href=\"#js-implement\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 JS<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#swift-implement\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Swift<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#java-implement\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 Java<\/a><\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><a href=\"#result\">\u0418\u0442\u043e\u0433<\/a><\/p>\n<\/li>\n<\/ul>\n<p><a class=\"anchor\" name=\"about\" id=\"about\"><\/a><\/p>\n<h3>\u041e\u0431 \u0430\u0432\u0442\u043e\u0440\u0435<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044e\u0441\u044c \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0439 \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0438\u0448\u0443. \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0423\u0441\u0442\u0438\u043d\u043e\u0432 \u0422\u0438\u0445\u043e\u043d \u0438 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432\u00a0<a href=\"https:\/\/rtkit.ru\/\">\u0420\u043e\u0441\u0442\u0435\u043b\u0435\u043a\u043e\u043c \u0418\u0422<\/a>, \u0430 \u0435\u0441\u043b\u0438 \u0431\u044b\u0442\u044c \u0442\u043e\u0447\u043d\u0435\u0435 \u2014 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u00ab\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f\u00a0<a href=\"https:\/\/rtkit.ru\/products\/edinii-produktovii-katalog\">\u0415\u041f\u041a<\/a>\u00a0(\u0415\u0434\u0438\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430)\u00bb.<\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u043e\u0439 core-\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0433\u043e\u0434\u0443 \u0420\u043e\u0441\u0442\u0435\u043b\u0435\u043a\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u0433\u0438\u0431\u043a\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u0443\u0441\u043b\u0443\u0433. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 SDK, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u0441\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443: \u043e\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043e \u043f\u0440\u043e\u0441\u0447\u0435\u0442\u0430 \u0446\u0435\u043d\u044b.<\/p>\n<p>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043d\u0438\u0436\u0435 \u2014 \u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043e\u0434\u043d\u0430 \u0438\u0437 \u0432\u0438\u0442\u0440\u0438\u043d \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u044d\u0442\u043e\u0433\u043e SDK.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0421 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 SDK \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043b\u0438\u0447\u043d\u043e\u043c \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u0435 \u043d\u0430 \u0441\u0430\u0439\u0442\u0435, \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u043b\u0438 \u0432 \u043e\u0444\u0438\u0441\u0435 \u043f\u0440\u043e\u0434\u0430\u0436, \u0433\u0434\u0435 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0430\u043c \u0447\u0442\u043e-\u043b\u0438\u0431\u043e, \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 SDK.<\/p>\n<p><a class=\"anchor\" name=\"why-kotlin\" id=\"why-kotlin\"><\/a><\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e Kotlin Multiplatform<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0432\u044b\u0431\u0440\u0430\u0442\u044c Kotlin Multiplatform, \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0438 \u043d\u0430 \u0441\u043c\u0430\u0440\u0442\u0444\u043e\u043d\u0430\u0445. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u043c \u043f\u0440\u0438\u044f\u0442\u043d\u044b\u043c \u0431\u043e\u043d\u0443\u0441\u043e\u043c.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u044f\u0441\u044c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, \u0442\u043e \u043f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u2014 \u044d\u0442\u043e React Native \u0438 Progressive Web Applications (PWA). \u041e\u0434\u043d\u0430\u043a\u043e, \u043c\u044b \u0443\u0436\u0435 \u0438\u043c\u0435\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0430\u0437\u0443 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f, \u0438 webview \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u043e\u0436\u0435 \u043d\u0435 \u043b\u0443\u0447\u0448\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c. \u041f\u043e \u044d\u0442\u043e\u0439 \u0436\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043c\u044b \u043e\u0442\u043c\u0435\u043b\u0438 \u0438\u0434\u0435\u044e \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 flutter, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u0438\u043c\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043d\u0430 ios \u0438 android \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0432 js. \u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e \u043d\u0430\u0448 \u0432\u044b\u0431\u043e\u0440 \u0434\u043e \u0434\u0432\u0443\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:<\/p>\n<p>a) C\/C++ \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043a \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0438 \u043a js \u043a\u0430\u043a WebAssembly<\/p>\n<p>b) \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u043e\u0433\u0434\u0430 Kotlin Multiplatform.<\/p>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u043f\u043e C\/C++ \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e \u043d\u0430\u0448\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0434\u043e \u043e\u0434\u043d\u043e\u0433\u043e, \u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u043c\u044b \u043d\u0438 \u0440\u0430\u0437\u0443 \u043d\u0435 \u043f\u043e\u0436\u0430\u043b\u0435\u043b\u0438 \u043e \u0441\u0432\u043e\u0435\u043c \u0432\u044b\u0431\u043e\u0440\u0435. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043c\u044b \u043d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u0435\u0451 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0439. \u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 API \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0442\u043e\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043a\u043e\u0434, \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435 \u0441\u0430\u0439\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u0432\u0432\u043e\u0434\u0430 \u043d\u043e\u043c\u0435\u0440\u0430 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 API \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a API \u0432 \u043e\u0431\u0445\u043e\u0434 \u0444\u0440\u043e\u043d\u0442\u0430, \u0438 \u0442\u043e\u0433\u0434\u0430 API \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0441 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 Kotlin Multiplatform \u0432\u0441\u0451 \u0431\u043e\u043b\u0435\u0435-\u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e. \u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u043f\u043b\u044e\u0441\u044b \u043c\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u044d\u0442\u043e\u0439 \u043d\u0435\u0439.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u0442\u043e\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform.html\">Kotlin Multiplatform<\/a>\u00a0\u2014 \u044d\u0442\u043e \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 JetBrains, \u043e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 Kotlin \u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043d\u0430\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-dsl-reference.html#targets\">10 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c<\/a>. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u043c\u0435\u0442\u044c \u0434\u043b\u044f JVM *.jar \u0444\u0430\u0439\u043b, \u0434\u043b\u044f JS \u2014 *.js \u043c\u043e\u0434\u0443\u043b\u044c \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f *.d.ts, \u0438, \u043f\u0440\u043e\u0441\u0442\u0438\u0442\u0435 \u0437\u0430 \u0442\u0430\u0432\u0442\u043e\u043b\u043e\u0433\u0438\u044e, \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0442\u0438\u043f\u0430 *.framework \u0434\u043b\u044f Swift. \u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b.<\/p>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0438 \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440, \u0445\u043e\u0447\u0443 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043e\u0442\u0442\u0443\u0434\u0430 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u044e \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u0434\u0430:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0435 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0430\u043b\u044c\u0444\u0430-\u0432\u0435\u0440\u0441\u0438\u0438. \u041d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 \u0443\u0436\u0435 \u0433\u043e\u0434 \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0442\u044b\u0441\u044f\u0447\u0430\u0445 (\u0435\u0441\u043b\u0438 \u043d\u0435 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430\u0445) \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043c\u043e\u0433\u0443 \u0437\u0430\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0436\u0438\u0437\u043d\u0435\u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d, \u0438 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0440\u0435\u0448\u0430\u0435\u043c\u044b.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u044b \u0432\u044b\u044f\u0432\u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0442\u0430\u043a\u0438\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u044e\u0441\u044b:<\/p>\n<ul>\n<li>\n<p><strong>\u041e\u0434\u0438\u043d \u043a\u043e\u0434, \u043e\u0434\u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c.<\/strong>\u00a0\u041c\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0438\u043c\u0435\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0436\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044e, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u2014 \u044d\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0442\u0440\u0430\u0442 \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0434\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0445\u043e\u0442\u0435\u043b\u043e\u043a \u0431\u0438\u0437\u043d\u0435\u0441\u0430 \u0434\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f;<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430.<\/strong>\u00a0\u0412\u044b\u043d\u0435\u0441\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0435\u0434\u0438\u043d\u044b\u0439 SDK \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0435\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435\u043c. \u0418\u043c\u0435\u044f \u043e\u0434\u043d\u0443 \u043e\u0431\u0449\u0443\u044e \u0434\u043e\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438, \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u044b\u0435 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442 \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430. \u041d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0443\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0437 \u0432\u0438\u0434\u0443 \u043d\u0435\u043c\u0430\u043b\u043e\u0432\u0430\u0436\u043d\u044b\u0439 bus factor, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0436\u0435 \u0443 \u0442\u0440\u0451\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u0447\u0435\u043c \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0443 3 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0430 3 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043d\u0430 3 \u044f\u0437\u044b\u043a\u0430\u0445;<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f.<\/strong>\u00a0\u041e\u0447\u0435\u043d\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f JS. \u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0435\u0441\u0442\u044c TypeScript, \u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u044d\u0442\u043e \u0432 \u043f\u043b\u044e\u0441;<\/p>\n<\/li>\n<li>\n<p><strong>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/strong>\u00a0\u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u0442\u0435 \u043a\u043e\u0434 \u0431\u0435\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0435\u0437 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438, \u0432\u044b \u0440\u0430\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0437\u0434\u043d\u043e \u043d\u0430\u0447\u043d\u0435\u0442\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u0435\u0441\u0442\u0430 \u0432\u044b, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430, \u043f\u043b\u044e\u0441 \u0442\u0435\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0438 \u043f\u043e\u0432\u044b\u0448\u0430\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430. \u041d\u0430\u043f\u0438\u0441\u0430\u0432 \u043e\u0434\u0438\u043d \u0442\u0435\u0441\u0442, \u0432\u044b \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u0432\u0441\u0435 \u0432\u0430\u0448\u0438 \u0446\u0435\u043b\u0435\u0432\u044b\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b, \u0447\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u0440\u0435\u0441\u0443\u0440\u0441 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p><strong>\u042f\u0437\u044b\u043a.<\/strong>\u00a0\u041a\u0442\u043e \u0431\u044b \u0447\u0442\u043e \u043d\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u043d\u043e \u043b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f Kotlin \u2014 \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u0433\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u044f\u0437\u044b\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u043b\u044e\u0434\u044c\u043c\u0438 \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439. \u042d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0438\u043c\u0435\u0435\u0442\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u0435\u0451 [\u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443] \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0442\u044c, \u0430 \u043d\u0435 \u0432 \u043a\u0430\u043a\u043e\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u0443\u0441\u043b\u043e\u0432\u043d\u043e\u043c (\u0431\u0435\u0437 \u043e\u0431\u0438\u0434) Go: \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u043c\u0435\u0442\u043e\u0434, \u0432\u0438\u0434\u0438\u0448\u044c \u043a\u0443\u0447\u0443 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0448\u044c \u0431\u0435\u0437 \u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0438 \u043c\u0438\u043d\u0443\u0441\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u043e\u0442\u0435\u0440\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/strong>\u00a0\u042d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f JS \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 overhead. \u041e\u0434\u043d\u0430\u043a\u043e \u043f\u043e\u0442\u0435\u0440\u0438 \u043d\u0435 \u0442\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u044d\u0442\u043e\u0433\u043e;<\/p>\n<\/li>\n<li>\n<p><strong>\u042d\u043a\u0441\u043f\u0435\u0440\u0442\u0438\u0437\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/strong>\u00a0\u0425\u043e\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u043d\u043e \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u044b\u043a\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0434\u043b\u044f \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u043d\u0430\u0442\u044c \u043f\u043e\u043c\u0438\u043c\u043e Kotlin \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0442;<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f.<\/strong>\u00a0\u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u043f\u0438\u0448\u0435\u0442\u0435 \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u0434, \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0435\u0437\u0434\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e. \u0422\u043e, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043e\u0434\u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u0440\u0443\u0433\u0430\u044f, \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 Kotlin \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434 runBlocking, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u043a\u043e\u0434\u0435 Kotlin, Java \u0438 Swift, \u043d\u043e \u043e\u043d \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043a\u043e\u0434\u0435 JS, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e,\u00a0<a href=\"https:\/\/github.com\/Kotlin\/kotlinx.coroutines\/issues\/195#issuecomment-354458878\">\u0446\u0438\u0442\u0438\u0440\u0443\u044e<\/a>: \u00ab\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0430\u0437\u0443\u043c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 JS. \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u043d\u0430\u044f \u043d\u0430 JS, \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439\u00bb. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-connect-to-apis.html\">\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f<\/a>\u00a0(expect\/actual \u043a\u043b\u0430\u0441\u0441\u044b) \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0443\u043c\u0430\u044e, \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043e\u0431\u0449\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0434\u0430\u043d\u043e. \u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u0441\u0442\u043e\u0438\u0442 \u043b\u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u0434\u0430\u043b\u044c\u0448\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043f\u043e\u0437\u0436\u0435, \u0438\u043b\u0438, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u043c \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435, \u0438 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u044d\u0442\u043e \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p><a class=\"anchor\" name=\"practice\" id=\"practice\"><\/a><\/p>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u043a\u0430<\/h3>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043a\u0430\u043a \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u044f\u0434\u0440\u043e \u0438\u0433\u0440\u044b \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0438-\u043d\u043e\u043b\u0438\u043a\u0438 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0442\u0440\u0435\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 JS (Browser), Swift (iOS), Java (Android). \u0412\u0435\u0441\u044c \u0438\u0437\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 GitHub \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e\u00a0<a href=\"https:\/\/github.com\/Tihon-Ustinov\/tictactoe\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<p><a class=\"anchor\" name=\"create-project\" id=\"create-project\"><\/a><\/p>\n<h4>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p><a class=\"anchor\" name=\"environment\" id=\"environment\"><\/a><\/p>\n<p><strong>\u041e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435<\/strong><\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Kotlin Multiplatform \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u044b\u00a0<a href=\"https:\/\/github.com\/Kotlin\/kdoctor\">KDoctor<\/a>. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b\u0438, \u0447\u0442\u043e \u0432\u0441\u0451 \u0435\u0441\u0442\u044c, \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043b\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442. \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u0438\u043c.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0434\u043b\u044f \u0432\u0430\u0441 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435. \u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0434 iOS \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Kotlin Multiplatform \u043d\u0443\u0436\u0435\u043d Command Line Tools (\u043e\u0431\u044b\u0447\u043d\u043e \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 xcode), \u0430 \u043f\u043e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0435 Apple \u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043f\u0440\u043e\u0434\u0443\u043a\u0446\u0438\u044e Apple. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430 Hackintosh, \u0445\u043e\u0442\u044f, \u0447\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044f \u043d\u0435 \u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b.<\/p>\n<p>\u0421\u043a\u0430\u0447\u0430\u0442\u044c Command Line Tools \u043c\u043e\u0436\u043d\u043e \u0441\u00a0<a href=\"https:\/\/developer.apple.com\/download\/all\/\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0430\u0439\u0442\u0430 Apple \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432<\/a>.<\/p>\n<p><a class=\"anchor\" name=\"create-project-more\" id=\"create-project-more\"><\/a><\/p>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/strong><\/p>\n<p>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f\u00a0<a href=\"https:\/\/terrakok.github.io\/kmp-web-wizard\/\">Kotlin Multiplatform Wizard<\/a>. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Kotlin;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0446\u0435\u043b\u0435\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c\u00a0<strong>JVM<\/strong>,\u00a0<strong>JS<\/strong>,\u00a0<strong>iOS<\/strong>\u00a0(\u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435);<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u2014 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u041d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0442\u043e \u0442\u0435\u0441\u0442\u044b \u0432\u0430\u043c \u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u044f\u0442\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438 \u0440\u0430\u0437\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u0432 \u0432\u0430\u0448\u0443 \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432 \u0432\u0430\u0448\u0435\u0439 \u043b\u044e\u0431\u0438\u043c\u043e\u0439 IDE, \u043d\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c IntelliJ IDEA, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u043d\u0435\u0439 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Kotlin Multiplatform. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\u00a0<a href=\"https:\/\/kotlinlang.org\/docs\/multiplatform-connect-to-apis.html\">\u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f<\/a>\u00a0\u043a\u043b\u0430\u0441\u0441\u043e\u0432 IntelliJ IDEA \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u043a\u043b\u0430\u0441\u0441\u044b.<\/p>\n<p>Kotlin Multiplatform Wizard \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u0442\u0435\u0441\u0442\u043e\u0432: Platform.kt, CommonTest, PlatformTest. \u041d\u0430\u043c \u043e\u043d\u0438 \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0441\u0440\u0430\u0437\u0443 \u0443\u0434\u0430\u043b\u0438\u043c. \u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><a class=\"anchor\" name=\"build-settings\" id=\"build-settings\"><\/a><\/p>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438<\/strong><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0431\u043e\u0440\u043a\u0438 gradle \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-336967","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/336967","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=336967"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/336967\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=336967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=336967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=336967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}