{"id":367493,"date":"2024-05-21T03:22:10","date_gmt":"2024-05-21T03:22:10","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=367493"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=367493","title":{"rendered":"<span>\u041a\u0430\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ChatGPT \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u0443 \u0432\u043e flutter<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0432\u0441\u0435\u043c. \u041a\u0430\u043a \u0440\u0430\u043d\u0435\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0432 \u0441\u0432\u043e\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445, \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0434\u043b\u044f \u0441\u0444\u0435\u0440\u044b \u0440\u0430\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0439. \u0418 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u0447\u0443 \u0441  \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a. <br \/>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0441\u0442\u0440\u043e\u0432\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 flood fill. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043d\u0430 pub.dev, \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0432 \u0442\u0435\u043e\u0440\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u043d\u0430 dart \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ChatGPT \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0432\u043e flutter \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/be1\/e6b\/dc9\/be1e6bdc97a087f253d67e4101231975.png\" width=\"296\" height=\"274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/be1\/e6b\/dc9\/be1e6bdc97a087f253d67e4101231975.png\"\/><\/figure>\n<hr\/>\n<h2>\u0420\u0435\u0441\u0435\u0440\u0447 \u0432 pub.dev<\/h2>\n<p>\u041d\u0430 pub.dev \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/pub.dev\/packages\/floodfill_image\" rel=\"noopener noreferrer nofollow\">floodfill_image<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f png \u0438 jpg \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/84e\/218\/9b5\/84e2189b5c3f120199b2572c9010a07f.gif\" width=\"600\" height=\"1000\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/84e\/218\/9b5\/84e2189b5c3f120199b2572c9010a07f.gif\"\/><\/figure>\n<p><strong>\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0444\u0438\u0447\u0438:<\/strong><br \/>1) \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0438 \u0441 \u0430\u0441\u0441\u0435\u0442\u043e\u0432<br \/>2) \u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430 \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f<br \/>3) \u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f<br \/>4) \u041c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u043e\u0442\u0442\u0435\u043d\u043a\u0443<br \/>5) \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e: \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 \u0440\u0430\u0441\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f, \u0438 \u0432\u0438\u0434\u0436\u0435\u0442 \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b:<\/strong><br \/>1) \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u043c\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c\u0438<br \/>2) \u0423\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<\/p>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/strong><br \/>1) \u041f\u0435\u0440\u0432\u043e\u0435, \u043d\u0430 \u0447\u0442\u043e \u044f \u043e\u0431\u0440\u0430\u0442\u0438\u043b \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, &#8212; \u044d\u0442\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0418\u0437-\u0437\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u044f\u0434\u043e\u043c \u0441 \u043a\u043e\u043d\u0442\u0443\u0440\u0430\u043c\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0431\u0435\u043b\u044b\u0435 \u043d\u0435\u0437\u0430\u043a\u0440\u0430\u0448\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (\u0432\u0438\u0434\u043d\u043e \u043d\u0430 \u0433\u0438\u0444\u043a\u0435)<br \/>2) \u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0438 \u043d\u0430 \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u0432\u043b\u0438\u044f\u0442\u044c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0430\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435<br \/>3) \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 2 \u043b\u0435\u0442 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u043b\u0430\u0441\u044c. \u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 0.0.8<\/p>\n<p>\u042d\u0442\u043e \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0445\u043e\u0440\u043e\u0448\u043e: \u0435\u0441\u043b\u0438 \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435\u0442 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432 \u0441 \u043d\u043e\u0432\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u043f\u043e\u043b\u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u0437\u0430\u0434\u0430\u0447\u0438, \u0442\u043e \u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0445\u043e\u0440\u043e\u0448\u043e.<br \/>\u041d\u043e \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b &#8212; \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043a\u043e\u0434 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u0442\u044c. \u0422\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u0441\u0442\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b \u0442\u043e\u0433\u0434\u0430, \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0435\u043b\u0430\u044e\u0442 \u0435\u0433\u043e \u0432\u0441\u0435 \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c.<\/p>\n<p>\u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u044d\u0442\u0438\u043c \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441 &#8212; \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u043c\u0435\u044e\u0449\u0443\u044e\u0441\u044f \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043a\u043e\u043f\u0430\u044f\u0441\u044c \u0432 \u0447\u0443\u0436\u043e\u043c \u043a\u043e\u0434\u0435, \u043b\u0438\u0431\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u0438. <\/p>\n<p>\u0418 \u044f \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0431\u0440\u0430\u043b \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u041d\u0435 \u0431\u0443\u0434\u0443 \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0444\u043e\u0440\u043a \u0438 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043f\u043e url, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439. \u0421\u043a\u0430\u0436\u0443 \u0442\u043e\u043b\u044c\u043a\u043e, \u0447\u0442\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438: \u043b\u0438\u043d\u0442\u0435\u0440 \u0440\u0443\u0433\u0430\u0435\u0442\u0441\u044f, \u0440\u0443\u043a\u0438 \u0447\u0435\u0448\u0443\u0442\u0441\u044f \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u0432\u0438\u0434\u0438\u0448\u044c.<\/p>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432, \u043c\u0430\u043b\u044b\u043c\u0438 \u043f\u043e\u0442\u0435\u0440\u044f\u043c\u0438 \u044f \u0434\u043e\u0441\u0442\u0438\u0433 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439: \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e. <\/p>\n<p>\u0418 \u043d\u0430 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u0440\u0435\u0448\u0435\u043d\u0430.<\/p>\n<hr\/>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043d\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043d\u0430 flutter, \u043d\u043e \u0435\u0441\u0442\u044c \u0413\u0443\u0433\u043b, \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u044f \u0438 ChatGPT<\/p>\n<h2>\u0427\u0442\u043e \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c flood fill?<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u044f \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u043a\u0430\u043a \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0432\u0443\u0437\u0430 &#8212; \u043f\u043e\u0433\u0443\u0433\u043b\u0438\u043b \u0438 \u043d\u0430\u0448\u0435\u043b \u043e\u0442\u0432\u0435\u0442 \u0432 \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u0438. \u0422\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e:<\/p>\n<blockquote>\n<p><strong>Flood fill<\/strong>, also called\u00a0<strong>seed fill<\/strong>, is a\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Flooding_algorithm\" rel=\"noopener noreferrer nofollow\">flooding algorithm<\/a>\u00a0that determines and alters the area\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Glossary_of_graph_theory#Connectivity\" rel=\"noopener noreferrer nofollow\">connected<\/a>\u00a0to a given node in a multi-dimensional\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Array_data_structure\" rel=\"noopener noreferrer nofollow\">array<\/a>\u00a0with some matching attribute. It is used in the &#171;bucket&#187; fill tool of\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Paint_program\" rel=\"noopener noreferrer nofollow\">paint programs<\/a>\u00a0to fill connected, similarly-colored areas with a different color, and in games such as\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Go_(game)\" rel=\"noopener noreferrer nofollow\">Go<\/a>\u00a0and\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Minesweeper_(video_game)\" rel=\"noopener noreferrer nofollow\">Minesweeper<\/a>\u00a0for determining which pieces are cleared. A variant called\u00a0<strong>boundary fill<\/strong>\u00a0uses the same algorithms but is defined as the area\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Glossary_of_graph_theory#Connectivity\" rel=\"noopener noreferrer nofollow\">connected<\/a>\u00a0to a given node that does not have a particular attribute.<\/p>\n<\/blockquote>\n<p>\u0422\u0443\u0442 \u043a\u0430\u043a \u0431\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e. \u041f\u0440\u043e\u0441\u0442\u043e \u0434\u0430\u043b\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043c\u043d\u043e\u0433\u043e\u043c\u0435\u0440\u043d\u043e\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435. <\/p>\n<p>\u0412 \u0442\u043e\u0439 \u0436\u0435 \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b 4 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430:<\/p>\n<ol>\n<li>\n<p>Stack-based recursive implementation (four-way)<\/p>\n<\/li>\n<li>\n<p>Span filling<\/p>\n<\/li>\n<li>\n<p>Graph-theoretic filling<\/p>\n<\/li>\n<li>\n<p>Walk-based filling (Fixed-memory method)<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043d\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u0432\u0443\u0445\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432, \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430, \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435 \u0438 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0440\u0430\u0432\u043d\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u043d\u0430\u043f\u0438\u0448\u0435\u043c, \u043a\u0430\u043a\u043e\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439:<\/p>\n<pre><code class=\"dart\">abstract class FloodFill {   final List&lt;List&lt;int>> image;   const FloodFill(this.image);   void fill(int startX, int startY, int newColor); }<\/code><\/pre>\n<h2>Stack-based recursive implementation <\/h2>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432 \u043f\u043b\u0430\u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0433\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f. \u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u044c, \u0430 \u043f\u043e\u0442\u043e\u043c \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435, \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u043c \u043f\u043e \u0432\u0441\u0435\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c. \u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5bf\/72c\/d85\/5bf72cd851c9afa9661adb05dbbb6447.png\" alt=\"\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u044f\" title=\"\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u044f\" width=\"1886\" height=\"336\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5bf\/72c\/d85\/5bf72cd851c9afa9661adb05dbbb6447.png\"\/><\/p>\n<div><figcaption>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u042f \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b ChatGPT \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 flood fill \u043d\u0430 Dart.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>Write me an implementation of this algorithm for dart language:<br \/>Flood-fill (node):  <br \/>If node is not Inside return. <br \/>Set the node <br \/>Perform Flood-fill one step to the south of node. <br \/>Perform Flood-fill one step to the north of node <br \/>Perform Flood-fill one step to the west of node <br \/>Perform Flood-fill one step to the east of node <br \/>Return.<\/p>\n<p>use such interface:<\/p>\n<p>abstract class FloodFill {<br \/> final List&lt;List&lt;int>> image;<br \/> const FloodFill(this.image);<br \/> void fill(int startX, int startY, int newColor);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">class BasicFloodFill extends FloodFill {  const BasicFloodFill(List&lt;List&lt;int>> image) : super(image);    @override   void fill(int startX, int startY, int newColor) {     int originalColor = image[startX][startY];     _floodFillUtil(startX, startY, originalColor, newColor);   }    void _floodFillUtil(int x, int y, int originalColor, int newColor) {     \/\/ Check if current node is inside the boundary and not already filled     if (!_isInside(x, y) || image[x][y] != originalColor) return;      \/\/ Set the node     image[x][y] = newColor;      \/\/ Perform flood-fill one step in each direction     _floodFillUtil(x + 1, y, originalColor, newColor); \/\/ South     _floodFillUtil(x - 1, y, originalColor, newColor); \/\/ North     _floodFillUtil(x, y - 1, originalColor, newColor); \/\/ West     _floodFillUtil(x, y + 1, originalColor, newColor); \/\/ East   }    bool _isInside(int x, int y) {     return x >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y >= 0 &amp;&amp; y &lt; image[0].length;   } }<\/code><\/pre>\n<p>\u0422\u043e\u0442 \u0436\u0435 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u043d\u043e \u0443\u0436\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ef6\/bb5\/46f\/ef6bb546fe94294645c7d12cf4b650a4.png\" alt=\"\u041e\u0447\u0435\u0440\u0435\u0434\u044c\" title=\"\u041e\u0447\u0435\u0440\u0435\u0434\u044c\" width=\"1886\" height=\"548\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ef6\/bb5\/46f\/ef6bb546fe94294645c7d12cf4b650a4.png\"\/><\/p>\n<div><figcaption>\u041e\u0447\u0435\u0440\u0435\u0434\u044c<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>Write me an implementation of this algorithm for dart language: <br \/>Flood-fill (node):   <br \/>Set Q to the empty queue or stack.   <br \/>Add node to the end of Q.   <br \/>While Q is not empty:     <br \/>Set n equal to the first element of Q.     <br \/>Remove first element from Q.     <br \/>If n is Inside:       <br \/>Set the n       <br \/>Add the node to the west of n to the end of Q.       <br \/>Add the node to the east of n to the end of Q.       <br \/>Add the node to the north of n to the end of Q.       <br \/>Add the node to the south of n to the end of Q.   <br \/>Continue looping until Q is exhausted.   <br \/>Return.  <\/p>\n<p>Use such interface:<br \/>abstract class FloodFill {<br \/> final List&lt;List&lt;int>> image;<br \/> const FloodFill(this.image);<br \/> void fill(int startX, int startY, int newColor);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">import 'dart:collection';  class Point {   final int x;   final int y;    const Point(this.x, this.y); }  class FloodFillQueueImpl extends FloodFill {   const FloodFillQueueImpl(List&lt;List&lt;int>> image) : super(image);    @override   void fill(int startX, int startY, int newColor) {     final int oldColor = image[startX][startY];     final Queue&lt;Point> queue = Queue();     queue.add(Point(startY, startX));      while (queue.isNotEmpty) {       final Point point = queue.removeFirst();       final int x = point.x;       final int y = point.y;        if (image[y][x] == oldColor) {         image[y][x] = newColor;          if (x > 0) {           queue.add(Point(x - 1, y));         }         if (x &lt; image[y].length - 1) {           queue.add(Point(x + 1, y));         }         if (y > 0) {           queue.add(Point(x, y - 1));         }         if (y &lt; image.length - 1) {           queue.add(Point(x, y + 1));         }       }     }   } }<\/code><\/pre>\n<h2>Span filling<\/h2>\n<p>\u042d\u0442\u043e\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0443\u0442\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043b\u0438\u043d\u0438\u0439 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0443\u0447\u0430\u0441\u0442\u043a\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u044d\u0442\u0438\u0445 \u043b\u0438\u043d\u0438\u0439 \u0441 \u043a\u0440\u0430\u044f\u043c\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a5b\/906\/bbb\/a5b906bbb80e255188f456e51b22c9be.png\" alt=\"span\" title=\"span\" width=\"1886\" height=\"980\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a5b\/906\/bbb\/a5b906bbb80e255188f456e51b22c9be.png\"\/><\/p>\n<div><figcaption>span<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>Write me an implementation of this algorithm for dart language: <br \/>fn fill(x, y):     <br \/>if not Inside(x, y) then return     <br \/>let s = new empty queue or stack     <br \/>Add (x, x, y, 1) to s     <br \/>Add (x, x, y &#8212; 1, -1) to s     <br \/>while s is not empty:         <br \/>Remove an (x1, x2, y, dy) from s         <br \/>let x = x1         <br \/>if Inside(x, y):             <br \/>while Inside(x &#8212; 1, y):                 <br \/>Set(x &#8212; 1, y)                 <br \/>x = x &#8212; 1             <br \/>if x &lt; x1:                 <br \/>Add (x, x1 &#8212; 1, y &#8212; dy, -dy) to s         <br \/>while x1 &lt;= x2:             <br \/>while Inside(x1, y):                 <br \/>Set(x1, y)                 <br \/>x1 = x1 + 1             <br \/>if x1 > x:                 <br \/>Add (x, x1 &#8212; 1, y + dy, dy) to s             <br \/>if x1 &#8212; 1 > x2:                 <br \/>Add (x2 + 1, x1 &#8212; 1, y &#8212; dy, -dy) to s             <br \/>x1 = x1 + 1             <br \/>while x1 &lt; x2 and not Inside(x1, y):                 <br \/>x1 = x1 + 1             <br \/>x = x1  <\/p>\n<p>Use such interface:  <br \/>abstract class abstract class FloodFill {<br \/> final List&lt;List&lt;int>> image;<br \/> const FloodFill(this.image);<br \/> void fill(int startX, int startY, int newColor);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">class FloodFillSpanImpl extends FloodFill {   const FloodFillSpanImpl(List&lt;List&lt;int>> image) : super(image);    \/\/ Check if the point is inside the canvas and matches the target color   bool _isInside(int x, int y, int targetColor) {     return x >= 0 &amp;&amp; y >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y &lt; image[0].length &amp;&amp; image[x][y] == targetColor;   }    \/\/ Set a point to the replacement color   void _setColor(int x, int y, int replacementColor) {     image[x][y] = replacementColor;   }    @override   void fill(int startX, int startY, int newColor) {     final targetColor = image[startX][startY];      if (!_isInside(startX, startY, targetColor)) return;      var s = &lt;List&lt;int>>[];     s.add([startX, startX, startY, 1]);     s.add([startX, startX, startY - 1, -1]);      while (s.isNotEmpty) {       var tuple = s.removeLast();       var x1 = tuple[0];       var x2 = tuple[1];       var y = tuple[2];       var dy = tuple[3];        var nx = x1;       if (_isInside(nx, y, targetColor)) {         while (_isInside(nx - 1, y, targetColor)) {           _setColor(nx - 1, y, newColor);           nx--;         }         if (nx &lt; x1) {           s.add([nx, x1 - 1, y - dy, -dy]);         }       }        while (x1 &lt;= x2) {         while (_isInside(x1, y, targetColor)) {           _setColor(x1, y, newColor);           x1++;         }         if (x1 > nx) {           s.add([nx, x1 - 1, y + dy, dy]);         }         if (x1 - 1 > x2) {           s.add([x2 + 1, x1 - 1, y - dy, -dy]);         }         x1++;         while (x1 &lt; x2 &amp;&amp; !_isInside(x1, y, targetColor)) {           x1++;         }         nx = x1;       }     }   } }<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 <strong>Graph-theoretic filling<\/strong> \u043d\u0435\u0442 \u0441\u043b\u043e\u0432\u0430\u043c\u0438 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u0430\u043a \u0443 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432, \u0438 \u043c\u043d\u0435 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445. \u0410 \u0432 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 <strong>Walk-based filling<\/strong> \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 \u0446\u0438\u043a\u043b\u0430\u0445, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0435\u0441\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0442\u0435\u0441\u0442\u044b. \u0411\u0443\u0434\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438, \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u0442\u0435\u0441\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">import 'package:flutter_test\/flutter_test.dart'; import 'package:painter\/features\/examples\/algorithms.dart';  void main() {   group(     'FloodFill classic',     () {       test('grid 30x30', () {         final Stopwatch stopwatch = Stopwatch()..start();          List&lt;List&lt;int>> image = [           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],         ];          BasicFloodFill(image).fill(7, 8, 2);          stopwatch.stop();         print('Elapsed time: ${stopwatch.elapsed}');          List&lt;List&lt;int>> result = [           [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 3, 3, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],         ];         expect(image, result);       });     },   );   group(     'FloodFill queued',     () {       test('grid 30x30', () {         final Stopwatch stopwatch = Stopwatch()..start();          List&lt;List&lt;int>> image = [           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],         ];          FloodFillQueueImpl(image).fill(7, 8, 2);          stopwatch.stop();         print('Elapsed time: ${stopwatch.elapsed}');         List&lt;List&lt;int>> result = [           [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 3, 3, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],         ];         expect(image, result);       });     },   );   group(     'FloodFill span',     () {       test('grid 30x30', () {         final Stopwatch stopwatch = Stopwatch()..start();          List&lt;List&lt;int>> image = [           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 3, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],         ];         final floodFill = FloodFillSpanImpl(image);         floodFill.fill(7, 8, 2);          stopwatch.stop();         print('Elapsed time: ${stopwatch.elapsed}');          List&lt;List&lt;int>> result = [           [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 0, 3, 3, 3, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2],           [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],         ];         expect(image, result);       });     },   ); } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u0437 \u0446\u0438\u0444\u0440 <\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bbb\/864\/b57\/bbb864b579df39546e60f8a386b96c65.png\" width=\"222\" height=\"952\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bbb\/864\/b57\/bbb864b579df39546e60f8a386b96c65.png\"\/><\/figure>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 +- \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:<\/p>\n<pre><code class=\"bash\">00:01 +0: FloodFill classic grid 30x30                                                                                                                    Elapsed time: 0:00:00.000300 00:01 +1: FloodFill queued grid 30x30                                                                                                                     Elapsed time: 0:00:00.000864 00:01 +2: FloodFill span grid 30x30                                                                                                                       Elapsed time: 0:00:00.000338 00:01 +3: All tests passed!    <\/code><\/pre>\n<p>\u041e\u0442\u0441\u044e\u0434\u0430 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u044b\u0432\u043e\u0434, \u0447\u0442\u043e \u043b\u0438\u0431\u043e ChatGPT \u043a\u0440\u0438\u0432\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b, \u043b\u0438\u0431\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f (\u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u0441 \u043e\u0447\u0435\u0440\u0435\u0434\u044f\u043c\u0438) \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u0430 \u043b\u0438\u0434\u0435\u0440 &#8212; \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f.<\/p>\n<hr\/>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 flutter \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h2>\n<h4>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/h4>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f, \u043a\u0430\u043a\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u043c\u0435\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u0438 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0434\u0436\u0435\u043d\u0435\u0440\u0438\u043a\u0438:<\/p>\n<pre><code class=\"dart\">abstract class FloodFill&lt;T, S> {   final T image;   const FloodFill(this.image);   void fill(int startX, int startY, S newColor); }<\/code><\/pre>\n<h4>\u0425\u0435\u043b\u043f\u0435\u0440\u044b<\/h4>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 dart:ui, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432-\u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0435\u0439.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0432 \u044d\u0442\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c. \u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0431\u0430\u0439\u0442\u044b. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b:<\/p>\n<pre><code class=\"dart\">import 'dart:async'; import 'dart:typed_data'; import 'dart:ui' as ui;  Future&lt;ByteData?> imageToBytes(ui.Image image) async {   final bytes = await image.toByteData(format: ui.ImageByteFormat.rawRgba);   return bytes; }  Future&lt;ui.Image> imageFromBytes(ByteData bytes, int imageWidth, int imageHeight) {   final Completer&lt;ui.Image> completer = Completer();   ui.decodeImageFromPixels(     bytes.buffer.asUint8List(),     imageWidth,     imageHeight,     ui.PixelFormat.rgba8888,     (img) {       completer.complete(img);     },   );   return completer.future; }<\/code><\/pre>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0446\u0432\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043c\u044b \u0442\u043e\u0436\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0431\u0430\u0439\u0442\u0430\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0442\u043e\u0436\u0435 \u043d\u0443\u0436\u043d\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0431\u0430\u0439\u0442\u044b \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. <\/p>\n<p>\u0426\u0432\u0435\u0442\u043d\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438 \u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e <strong>R<\/strong>, \u0437\u0435\u043b\u0435\u043d\u043e\u0433\u043e <strong>G<\/strong> \u0438 \u0441\u0438\u043d\u0435\u0433\u043e <strong>B<\/strong> \u0446\u0432\u0435\u0442\u043e\u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043e\u0442\u0442\u0435\u043d\u043a\u043e\u0432. \u041a \u044d\u0442\u043e\u0439 \u0441\u043c\u0435\u0441\u0438 \u0447\u0430\u0441\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f 4 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u0430\u043b\u044c\u0444\u0430 <strong>A<\/strong>, \u0438\u043b\u0438 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c. <\/p>\n<details class=\"spoiler\">\n<summary>\u0417\u0430\u043c\u0435\u0442\u043a\u0438 \u043e\u0442 \u043a\u044d\u043f\u0430<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0420\u0430\u0437\u043d\u044b\u0435 \u043e\u0442\u0442\u0435\u043d\u043a\u0438 \u0446\u0432\u0435\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0439 \u0438\u0437 0 \u0438 1 (\u043e\u0434\u0438\u043d \u0431\u0438\u0442). \u041f\u0440\u0438\u043d\u044f\u0442\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e 8 \u0431\u0438\u0442\u043e\u0432 (2^8 = 256 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432), \u0438\u043b\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u0430\u0439\u0442\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043e\u0434\u0438\u043d \u0446\u0432\u0435\u0442, \u0435\u0441\u043b\u0438 \u043e\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0435\u0439 RGBA, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u0430\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c 8&#215;4=32 \u043d\u0443\u043b\u0435\u0439 \u0438\u043b\u0438 \u0435\u0434\u0438\u043d\u0438\u0447\u0435\u043a, \u0438\u043b\u0438 32 \u0431\u0438\u0442\u043e\u0432, \u0438\u043b\u0438 4 \u0431\u0430\u0439\u0442\u043e\u0432.<br \/>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0431\u0430\u0439\u0442\u043e\u0432 \u0438\u0437 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0438\u0434\u0435\u0442 \u0434\u0440\u0443\u0433 \u0437\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u0447\u0435\u0440\u0435\u0437 4.<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u044b\u0448\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0431\u0430\u0439\u0442\u044b, \u0433\u0434\u0435 \u0446\u0432\u0435\u0442\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 RGBA, \u0430 Color \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 dart:ui \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0445\u0440\u0430\u043d\u0438\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 ARGB. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"dart\">void setPixelColor({   required int x,   required int y,   required ByteData bytes,      \/\/ for correct representation of color bytes' coordinates    \/\/ in an array of image bytes   required int imageWidth,     required ui.Color newColor, }) {   bytes.setUint32(     (x + y * imageWidth) * 4, \/\/ offset     colorToIntRGBA(newColor), \/\/ value   ); }  ui.Color getPixelColor({   required ByteData bytes,   required int x,   required int y,   required int imageWidth, }) {   final uint32 = bytes.getUint32((x + y * imageWidth) * 4);   return colorFromIntRGBA(uint32); }  int colorToIntRGBA(ui.Color color) {   \/\/ Extract ARGB components   int a = (color.value >> 24) &amp; 0xFF;   int r = (color.value >> 16) &amp; 0xFF;   int g = (color.value >> 8) &amp; 0xFF;   int b = color.value &amp; 0xFF;    \/\/ Convert to RGBA and combine into a single integer   return (r &lt;&lt; 24) | (g &lt;&lt; 16) | (b &lt;&lt; 8) | a; }  ui.Color colorFromIntRGBA(int uint32Rgba) {   \/\/ Extract RGBA components   int r = (uint32Rgba >> 24) &amp; 0xFF;   int g = (uint32Rgba >> 16) &amp; 0xFF;   int b = (uint32Rgba >> 8) &amp; 0xFF;   int a = uint32Rgba &amp; 0xFF;    \/\/ Convert to ARGB format and create a Color object   return ui.Color.fromARGB(a, r, g, b); }<\/code><\/pre>\n<p>\u0412-\u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u0445\u0435\u043b\u043f\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u0446\u0432\u0435\u0442\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e \u0441\u0443\u0442\u0438 \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043a\u0430\u043a \u0432 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u0439 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435. \u042f \u0437\u0430\u0434\u0430\u043b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>threshold = 50<\/code>:<\/p>\n<pre><code class=\"dart\">bool isAlmostSameColor({   required ui.Color pixelColor,   required ui.Color checkColor,   required int imageWidth, }) {   const int threshold = 50;   final int rDiff = (pixelColor.red - checkColor.red).abs();   final int gDiff = (pixelColor.green - checkColor.green).abs();   final int bDiff = (pixelColor.blue - checkColor.blue).abs();   return rDiff &lt; threshold &amp;&amp; gDiff &lt; threshold &amp;&amp; bDiff &lt; threshold; }<\/code><\/pre>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430<\/h2>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0435\u0441\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u043e \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0432 \u0440\u0430\u043d\u0435\u0435 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 FloodFill \u0443\u0436\u0435 \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0430\u043f\u0433\u0440\u0435\u0439\u0434:<\/p>\n<pre><code class=\"dart\">abstract class FloodFill&lt;T, S> {   final T image;   const FloodFill(this.image);   FutureOr&lt;T?> fill(int startX, int startY, S newColor); }<\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u043c\u0435\u0442\u043e\u0434 <code>fill()<\/code>  \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>T? image<\/code> \u0438\u043b\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0438\u043b\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u043c\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">class BasicFloodFill extends FloodFill&lt;List&lt;List&lt;int>>, int> {   const BasicFloodFill(List&lt;List&lt;int>> image) : super(image);    @override   List&lt;List&lt;int>>? fill(int startX, int startY, int newColor) {     int originalColor = image[startX][startY];     _floodFillUtil(startX, startY, originalColor, newColor);     return image;   }    void _floodFillUtil(int x, int y, int originalColor, int newColor) {     \/\/ Check if current node is inside the boundary and not already filled     if (!_isInside(x, y) || image[x][y] != originalColor) return;      \/\/ Set the node     image[x][y] = newColor;      \/\/ Perform flood-fill one step in each direction     _floodFillUtil(x + 1, y, originalColor, newColor); \/\/ South     _floodFillUtil(x - 1, y, originalColor, newColor); \/\/ North     _floodFillUtil(x, y - 1, originalColor, newColor); \/\/ West     _floodFillUtil(x, y + 1, originalColor, newColor); \/\/ East   }    bool _isInside(int x, int y) {     return x >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y >= 0 &amp;&amp; y &lt; image[0].length;   } }  class Point {   final int x;   final int y;    const Point(this.x, this.y); }  class FloodFillQueueImpl extends FloodFill&lt;List&lt;List&lt;int>>, int> {   const FloodFillQueueImpl(List&lt;List&lt;int>> image) : super(image);    @override   List&lt;List&lt;int>>? fill(int startX, int startY, int newColor) {     final int oldColor = image[startX][startY];     final int width = image[0].length;     final int height = image.length;     final Queue&lt;Point> queue = Queue();     queue.add(Point(startY, startX));      while (queue.isNotEmpty) {       final Point point = queue.removeFirst();       final int x = point.x;       final int y = point.y;        if (image[y][x] == oldColor) {         image[y][x] = newColor;          if (x > 0) {           queue.add(Point(x - 1, y));         }         if (x &lt; width - 1) {           queue.add(Point(x + 1, y));         }         if (y > 0) {           queue.add(Point(x, y - 1));         }         if (y &lt; height - 1) {           queue.add(Point(x, y + 1));         }       }     }     return image;   } }  class FloodFillSpanImpl extends FloodFill&lt;List&lt;List&lt;int>>, int> {   const FloodFillSpanImpl(List&lt;List&lt;int>> image) : super(image);    \/\/ Check if the point is inside the canvas and matches the target color   bool _isInside(int x, int y, int targetColor) {     return x >= 0 &amp;&amp; y >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y &lt; image[0].length &amp;&amp; image[x][y] == targetColor;   }    \/\/ Set a point to the replacement color   void _setColor(int x, int y, int replacementColor) {     image[x][y] = replacementColor;   }    @override   List&lt;List&lt;int>>? fill(int startX, int startY, int newColor) {     final targetColor = image[startX][startY];      if (!_isInside(startX, startY, targetColor)) return null;      var s = &lt;List&lt;int>>[];     s.add([startX, startX, startY, 1]);     s.add([startX, startX, startY - 1, -1]);      while (s.isNotEmpty) {       var tuple = s.removeLast();       var x1 = tuple[0];       var x2 = tuple[1];       var y = tuple[2];       var dy = tuple[3];        var nx = x1;       if (_isInside(nx, y, targetColor)) {         while (_isInside(nx - 1, y, targetColor)) {           _setColor(nx - 1, y, newColor);           nx--;         }         if (nx &lt; x1) {           s.add([nx, x1 - 1, y - dy, -dy]);         }       }        while (x1 &lt;= x2) {         while (_isInside(x1, y, targetColor)) {           _setColor(x1, y, newColor);           x1++;         }         if (x1 > nx) {           s.add([nx, x1 - 1, y + dy, dy]);         }         if (x1 - 1 > x2) {           s.add([x2 + 1, x1 - 1, y - dy, -dy]);         }         x1++;         while (x1 &lt; x2 &amp;&amp; !_isInside(x1, y, targetColor)) {           x1++;         }         nx = x1;       }     }     return image;   } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u043f\u0440\u043e\u0441\u0438\u043c ChatGPT \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>I have this interface<br \/> abstract class FloodFill&lt;T, S> {<br \/> final T image;<br \/> const FloodFill(this.image);<br \/> FutureOr&lt;T?> fill(int startX, int startY, S newColor);<br \/> }<\/p>\n<p>I need you to upgrade an implementation below for the new values:<\/p>\n<p>class BasicFloodFill extends FloodFill&lt;List&lt;List&lt;int>>, int> {<br \/> const BasicFloodFill(List&lt;List&lt;int>> image) : super(image);<\/p>\n<p><a class=\"mention\" href=\"\/users\/override\">@override<\/a><br \/> List&lt;List&lt;int>>? fill(int startX, int startY, int newColor) {<br \/> int originalColor = image[startX][startY];<br \/> _floodFillUtil(startX, startY, originalColor, newColor);<br \/> return image;<br \/> }<\/p>\n<p>void _floodFillUtil(int x, int y, int originalColor, int newColor) {<br \/> \/\/ Check if current node is inside the boundary and not already filled<br \/> if (!_isInside(x, y) || image[x][y] != originalColor) return;<\/p>\n<p>\/\/ Set the node<br \/> image[x][y] = newColor;<\/p>\n<p>\/\/ Perform flood-fill one step in each direction<br \/> _floodFillUtil(x + 1, y, originalColor, newColor); \/\/ South<br \/> _floodFillUtil(x &#8212; 1, y, originalColor, newColor); \/\/ North<br \/> _floodFillUtil(x, y &#8212; 1, originalColor, newColor); \/\/ West<br \/> _floodFillUtil(x, y + 1, originalColor, newColor); \/\/ East<\/p>\n<p>bool _isInside(int x, int y) {<br \/> return x >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y >= 0 &amp;&amp; y &lt; image[0].length;<br \/> }<br \/> }<\/p>\n<p>Where T is an ui.Image from the library dart:ui as ui, and S is an ui.Color also from this library.<\/p>\n<p>Please, use these helpers:<\/p>\n<p>Future&lt;ByteData?> imageToBytes(ui.Image image) async {<br \/> final bytes = await image.toByteData(format: ui.ImageByteFormat.rawRgba);<br \/> return bytes;<br \/> }<\/p>\n<p>Future&lt;ui.Image> imageFromBytes(ByteData bytes, int imageWidth, int imageHeight) {<br \/> final Completer&lt;ui.Image> completer = Completer();<br \/> ui.decodeImageFromPixels(<br \/> bytes.buffer.asUint8List(),<br \/> imageWidth,<br \/> imageHeight,<br \/> ui.PixelFormat.rgba8888,<br \/> (img) {<br \/> completer.complete(img);<br \/> },<br \/> );<br \/> return completer.future;<br \/> }<\/p>\n<p>bool isAlmostSameColor({<br \/> required ui.Color pixelColor,<br \/> required ui.Color checkColor,<br \/> required int imageWidth,<br \/> }) {<br \/> const int threshold = 50;<br \/> final int rDiff = (pixelColor.red &#8212; checkColor.red).abs();<br \/> final int gDiff = (pixelColor.green &#8212; checkColor.green).abs();<br \/> final int bDiff = (pixelColor.blue &#8212; checkColor.blue).abs();<br \/> return rDiff &lt; threshold &amp;&amp; gDiff &lt; threshold &amp;&amp; bDiff &lt; threshold;<br \/> }<\/p>\n<p>void setPixelColor({<br \/> required int x,<br \/> required int y,<br \/> required ByteData bytes,<br \/> required int imageWidth,<br \/> required ui.Color newColor,<br \/> }) {<br \/> bytes.setUint32(<br \/> (x + y * imageWidth) * 4,<br \/> colorToIntRGBA(newColor),<br \/> );<br \/> }<\/p>\n<p>ui.Color getPixelColor({<br \/> required ByteData bytes,<br \/> required int x,<br \/> required int y,<br \/> required int imageWidth,<br \/> }) {<br \/> final uint32 = bytes.getUint32((x + y * imageWidth) * 4);<br \/> return colorFromIntRGBA(uint32);<br \/> }<\/p>\n<p>int colorToIntRGBA(ui.Color color) {<br \/> \/\/ Extract ARGB components<br \/> int a = (color.value >> 24) &amp; 0xFF;<br \/> int r = (color.value >> 16) &amp; 0xFF;<br \/> int g = (color.value >> 8) &amp; 0xFF;<br \/> int b = color.value &amp; 0xFF;<\/p>\n<p>\/\/ Convert to RGBA and combine into a single integer<br \/> return (r &lt;&lt; 24) | (g &lt;&lt; 16) | (b &lt;&lt; 8) | a;<br \/> }<\/p>\n<p>ui.Color colorFromIntRGBA(int uint32Rgba) {<br \/> \/\/ Extract RGBA components<br \/> int r = (uint32Rgba >> 24) &amp; 0xFF;<br \/> int g = (uint32Rgba >> 16) &amp; 0xFF;<br \/> int b = (uint32Rgba >> 8) &amp; 0xFF;<br \/> int a = uint32Rgba &amp; 0xFF;<\/p>\n<p>\/\/ Convert to ARGB format and create a Color object<br \/> return ui.Color.fromARGB(a, r, g, b);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">import 'dart:async'; import 'dart:typed_data'; import 'dart:ui' as ui;  class ImageFloodFill extends FloodFill&lt;ui.Image, ui.Color> {   ImageFloodFill(ui.Image image) : super(image);    @override   Future&lt;ui.Image?> fill(int startX, int startY, ui.Color newColor) async {     ByteData? byteData = await imageToBytes(image);     if (byteData == null) return null;      int width = image.width;     int height = image.height;     ui.Color originalColor = getPixelColor(bytes: byteData, x: startX, y: startY, imageWidth: width);      _floodFillUtil(byteData, startX, startY, width, height, originalColor, newColor);          return imageFromBytes(byteData, width, height);   }    void _floodFillUtil(ByteData bytes, int x, int y, int width, int height, ui.Color originalColor, ui.Color newColor) {     \/\/ Check if current node is inside the boundary and not already filled     if (!_isInside(x, y, width, height) || !isAlmostSameColor(pixelColor: getPixelColor(bytes: bytes, x: x, y: y, imageWidth: width), checkColor: originalColor, imageWidth: width)) return;      \/\/ Set the node     setPixelColor(x: x, y: y, bytes: bytes, imageWidth: width, newColor: newColor);      \/\/ Perform flood-fill one step in each direction     _floodFillUtil(bytes, x + 1, y, width, height, originalColor, newColor); \/\/ East     _floodFillUtil(bytes, x - 1, y, width, height, originalColor, newColor); \/\/ West     _floodFillUtil(bytes, x, y - 1, width, height, originalColor, newColor); \/\/ North     _floodFillUtil(bytes, x, y + 1, width, height, originalColor, newColor); \/\/ South   }    bool _isInside(int x, int y, int width, int height) {     return x >= 0 &amp;&amp; x &lt; width &amp;&amp; y >= 0 &amp;&amp; y &lt; height;   } }<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u043b\u044f Queued \u0438 Span:<\/p>\n<details class=\"spoiler\">\n<summary>Queued<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">import 'dart:async'; import 'dart:typed_data'; import 'dart:ui' as ui; import 'dart:collection';  class ImageFloodFillQueueImpl extends FloodFill&lt;ui.Image, ui.Color> {   ImageFloodFillQueueImpl(ui.Image image) : super(image);    @override   Future&lt;ui.Image?> fill(int startX, int startY, ui.Color newColor) async {     ByteData? byteData = await imageToBytes(image);     if (byteData == null) return null;      int width = image.width;     int height = image.height;     ui.Color oldColor = getPixelColor(bytes: byteData, x: startX, y: startY, imageWidth: width);      final Queue&lt;Point> queue = Queue();     queue.add(Point(startX, startY));      while (queue.isNotEmpty) {       final Point point = queue.removeFirst();       final int x = point.x;       final int y = point.y;        if (isAlmostSameColor(pixelColor: getPixelColor(bytes: byteData, x: x, y: y, imageWidth: width), checkColor: oldColor, imageWidth: width)) {         setPixelColor(x: x, y: y, bytes: byteData, imageWidth: width, newColor: newColor);          if (x > 0) queue.add(Point(x - 1, y));         if (x &lt; width - 1) queue.add(Point(x + 1, y));         if (y > 0) queue.add(Point(x, y - 1));         if (y &lt; height - 1) queue.add(Point(x, y + 1));       }     }      return imageFromBytes(byteData, width, height);   } }  class Point {   final int x;   final int y;    const Point(this.x, this.y); }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Span<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"dart\">import 'dart:async'; import 'dart:typed_data'; import 'dart:ui' as ui;  class ImageFloodFillSpanImpl extends FloodFill&lt;ui.Image, ui.Color> {   ImageFloodFillSpanImpl(ui.Image image) : super(image);    @override   Future&lt;ui.Image?> fill(int startX, int startY, ui.Color newColor) async {     ByteData? byteData = await imageToBytes(image);     if (byteData == null) return null;      int width = image.width;     int height = image.height;     ui.Color targetColor = getPixelColor(bytes: byteData, x: startX, y: startY, imageWidth: width);      var s = &lt;List&lt;int>>[];     s.add([startX, startX, startY, 1]);     s.add([startX, startX, startY - 1, -1]);      while (s.isNotEmpty) {       var tuple = s.removeLast();       var x1 = tuple[0];       var x2 = tuple[1];       var y = tuple[2];       var dy = tuple[3];        var nx = x1;       if (_isInside(nx, y, width, height, byteData, targetColor)) {         while (_isInside(nx - 1, y, width, height, byteData, targetColor)) {           setPixelColor(x: nx - 1, y: y, bytes: byteData, imageWidth: width, newColor: newColor);           nx--;         }         if (nx &lt; x1) {           s.add([nx, x1 - 1, y - dy, -dy]);         }       }        while (x1 &lt;= x2) {         while (_isInside(x1, y, width, height, byteData, targetColor)) {           setPixelColor(x: x1, y: y, bytes: byteData, imageWidth: width, newColor: newColor);           x1++;         }         if (x1 > nx) {           s.add([nx, x1 - 1, y + dy, dy]);         }         if (x1 - 1 > x2) {           s.add([x2 + 1, x1 - 1, y - dy, -dy]);         }         x1++;         while (x1 &lt; x2 &amp;&amp; !_isInside(x1, y, width, height, byteData, targetColor)) {           x1++;         }         nx = x1;       }     }      return imageFromBytes(byteData, width, height);   }    bool _isInside(int x, int y, int width, int height, ByteData bytes, ui.Color targetColor) {     if (x &lt; 0 || x >= width || y &lt; 0 || y >= height) return false;     return isAlmostSameColor(pixelColor: getPixelColor(bytes: bytes, x: x, y: y, imageWidth: width), checkColor: targetColor, imageWidth: width);   } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430<\/h2>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0432\u0435\u0440\u0441\u0442\u0430\u0435\u043c \u044d\u043a\u0440\u0430\u043d\u0447\u0438\u043a, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0435.<\/p>\n<p><strong>\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f:<\/strong><\/p>\n<ol>\n<li>\n<p>\u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u043f\u043e url<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u0430\u043a\u0443\u044e-\u043b\u0438\u0431\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043e\u043d\u0430 \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u0446\u0432\u0435\u0442<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"dart\">import 'dart:typed_data'; import 'dart:ui' as ui;  import 'package:flutter\/material.dart';  import 'package:http\/http.dart' as http;  import 'flood_fill_raster.dart';  class FloodFillRasterScreen extends StatelessWidget {   const FloodFillRasterScreen({super.key});    @override   Widget build(BuildContext context) {     return Scaffold(       appBar: AppBar(         title: const Text('Flood Fill Raster'),       ),       body: const Center(child: FloodFillRaster()),     );   } }  class FloodFillRaster extends StatefulWidget {   const FloodFillRaster({super.key});    @override   State&lt;FloodFillRaster> createState() => _FloodFillRasterState(); }  class _FloodFillRasterState extends State&lt;FloodFillRaster> {   ui.Image? _image;    @override   void initState() {     super.initState();     _loadImage().then((image) {       setState(() {         _image = image;       });     });   }    Future&lt;ui.Image> _loadImage() async {     const url =         'https:\/\/sun9-77.userapi.com\/impg\/BiGYCxYxSuZgeILSzA0dtPcNC7935fdhpW36rg\/e3jk6CqTwkw.jpg?size=1372x1372&amp;quality=95&amp;sign=2afb3d42765f8777879e06c314345303&amp;type=album';      final response = await http.get(Uri.parse(url));      final Uint8List data = response.bodyBytes;     final ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());     final ui.FrameInfo fi = await codec.getNextFrame();     return fi.image;   }    void _onTapDown(TapDownDetails details) async {     final Offset localPosition = details.localPosition;     final int x = localPosition.dx.toInt();     final int y = localPosition.dy.toInt();      const ui.Color newColor = Colors.red;     final image = await ImageFloodFillImpl(_image!).fill(x, y, newColor);     setState(() {       _image = image;     });   }    @override   Widget build(BuildContext context) {     if (_image == null) {       return const Center(         child: CircularProgressIndicator(),       );     }     return FittedBox(       child: GestureDetector(         onTapDown: _onTapDown,         child: CustomPaint(           size: Size(_image!.width.toDouble(), _image!.height.toDouble()),           painter: ImagePainter(_image!),         ),       ),     );   } }  class ImagePainter extends CustomPainter {   final ui.Image image;    const ImagePainter(this.image);    @override   void paint(Canvas canvas, Size size) {     canvas.drawImage(image, Offset.zero, Paint()..filterQuality = FilterQuality.high);   }    @override   bool shouldRepaint(ImagePainter oldDelegate) => true; }<\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u043f\u043e url \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/pub.dev\/packages\/http\" rel=\"noopener noreferrer nofollow\">http<\/a>. <\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043b\u0435\u0436\u0430\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <code>import 'flood_fill_raster.dart';<\/code><\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 <code>ui.Image<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u0438\u0434\u0436\u0435\u0442 <code>CustomPaint<\/code>. <\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0445\u0435\u043d\u0434\u043b\u0438\u043d\u0433\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>GestureDetector<\/code>. <\/p>\n<\/li>\n<\/ol>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5db\/0ee\/57d\/5db0ee57dcf63a397cf1bbf345402f90.gif\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\" width=\"296\" height=\"640\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5db\/0ee\/57d\/5db0ee57dcf63a397cf1bbf345402f90.gif\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>ImageFloodFillQueueImpl<\/code>. \u0422\u0430\u043a \u0436\u0435 \u0432\u0441\u0435 \u043e\u043a \u0441 <code>ImageFloodFillSpanImpl<\/code>. <\/p>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>ImageFloodFillImpl<\/code>, \u0433\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f, \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u0438, \u0432 \u043f\u0440\u0438\u0440\u043e\u0434\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u0443\u0436\u0435 \u043d\u0435 \u0441\u0442\u0430\u043b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5aa\/488\/3d7\/5aa4883d74824d2e3485a47fd8dbcf36.png\" width=\"1534\" height=\"398\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5aa\/488\/3d7\/5aa4883d74824d2e3485a47fd8dbcf36.png\"\/><\/figure>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0432 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432 \u0441\u0440\u0430\u0432\u043d\u0438\u043c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0443 \u043e\u0431\u043e\u0438\u0445 \u0438\u0437 \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043f\u0443\u0442\u0435\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043e\u0434\u043d\u0443 \u0442\u043e\u0447\u043a\u0443 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"dart\">  void _onTapDown(TapDownDetails details) async {     final Offset localPosition = details.localPosition;     final int x = localPosition.dx.toInt();     final int y = localPosition.dy.toInt();      const ui.Color newColor = Colors.red;      final Stopwatch stopwatchQueue = Stopwatch()..start();     await ImageFloodFillQueueImpl(_image!).fill(x, y, newColor);     stopwatchQueue.stop();     print('Queue: ${stopwatchQueue.elapsedMilliseconds} ms');          final Stopwatch stopwatchSpan = Stopwatch()..start();     await ImageFloodFillSpanImpl(_image!).fill(x, y, newColor);     stopwatchSpan.stop();     print('Span: ${stopwatchSpan.elapsedMilliseconds} ms');      \/\/ setState(() {     \/\/   _image = image;     \/\/ });   }<\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u043c\u0435\u0440 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/pub.dev\/packages\/floodfill_image\" rel=\"noopener noreferrer nofollow\">floodfill_image<\/a> \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <a href=\"https:\/\/github.com\/garlen-javier\/FloodFill_Image\/blob\/main\/lib\/src\/floodfill_painter.dart#L93\" rel=\"noopener noreferrer nofollow\">fill<\/a><\/p>\n<pre><code class=\"dart\">void fill(Offset position) async {     final date_0 = DateTime.now();     int pX = position.dx.toInt();     int pY = position.dy.toInt();      if (_filler == null) return;      if (pX &lt; 0 || pY &lt; 0) return;      int touchColor = _filler!.image!.getPixelSafe(pX, pY);     if (_checkAvoidColor(touchColor)) return;     if (onFloodFillStart != null) onFloodFillStart!(position, image);      _filler?.setTargetColor(touchColor);     await _filler!.floodFill(pX, pY);      ui.decodeImageFromPixels(       _filler!.image!.getBytes(),       _filler!.image!.width,       _filler!.image!.height,       ui.PixelFormat.rgba8888,       (output) async {         image = output;         final date_1 = DateTime.now();         print('Flood fill time: ${date_1.difference(date_0).inMilliseconds} ms');         notifier!.value = position.toString() + touchColor.toString();         if (onFloodFillEnd != null) onFloodFillEnd!(output);       },     );   }<\/code><\/pre>\n<p>\u0418 \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c \u044d\u043a\u0440\u0430\u043d:<\/p>\n<pre><code class=\"dart\">class FloodFillRasterScreen extends StatelessWidget {   const FloodFillRasterScreen({super.key});    @override   Widget build(BuildContext context) {     return Scaffold(       appBar: AppBar(         title: const Text('Flood Fill Raster'),       ),       body: const SingleChildScrollView(           child: Column(         children: [           FloodFillRaster(),           FittedBox(             child: FloodFillImage(               imageProvider: NetworkImage(                   'https:\/\/sun9-77.userapi.com\/impg\/BiGYCxYxSuZgeILSzA0dtPcNC7935fdhpW36rg\/e3jk6CqTwkw.jpg?size=1372x1372&amp;quality=95&amp;sign=2afb3d42765f8777879e06c314345303&amp;type=album'),               fillColor: Colors.red,               avoidColor: [Colors.black],               tolerance: 50,             ),           ),         ],       )),     );   } }<\/code><\/pre>\n<p><strong>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3ae\/df3\/6e4\/3aedf36e42dbdc23a82e32714d6dad57.png\" width=\"1454\" height=\"422\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3ae\/df3\/6e4\/3aedf36e42dbdc23a82e32714d6dad57.png\"\/><\/figure>\n<p>\u041f\u0435\u0440\u0432\u044b\u0435 \u0442\u0440\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 &#8212; \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439. \u041d\u0438\u0436\u043d\u0438\u0435 &#8212; \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439.<br \/>Span \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0435\u0434\u0443\u0442 \u0441\u0435\u0431\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e, Queue &#8212; \u043e\u0442\u0441\u0442\u0430\u0435\u0442 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439.<\/p>\n<hr\/>\n<h2>\u0418\u0442\u043e\u0433\u0438<\/h2>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u0443 \u0440\u0430\u0441\u0442\u0440\u043e\u0432\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 flood fill, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0443\u0441\u043b\u0443\u0433\u0430\u043c\u0438 ChatGPT \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430, \u0438 \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <a href=\"https:\/\/pub.dev\/packages\/floodfill_image\" rel=\"noopener noreferrer nofollow\">floodfill_image<\/a> \u0441 \u043d\u0430\u0448\u0435\u0439.<\/p>\n<p>\u042f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043a\u043e\u043c\u0443-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u0430\u043b\u0430 \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u0434\u0435\u0439, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ChatGPT \u0432 \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/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\/articles\/791886\/\"> https:\/\/habr.com\/ru\/articles\/791886\/<\/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<p>\u041f\u0440\u0438\u0432\u0435\u0442 \u0432\u0441\u0435\u043c. \u041a\u0430\u043a \u0440\u0430\u043d\u0435\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0432 \u0441\u0432\u043e\u0438\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445, \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0434\u043b\u044f \u0441\u0444\u0435\u0440\u044b \u0440\u0430\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0439. \u0418 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u0447\u0443 \u0441  \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a. <br \/>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0441\u0442\u0440\u043e\u0432\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 flood fill. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043d\u0430 pub.dev, \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0432 \u0442\u0435\u043e\u0440\u0438\u044e \u044d\u0442\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u043d\u0430 dart \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ChatGPT \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0432\u043e flutter \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<figure class=\"\"><\/figure>\n<hr\/>\n<h2>\u0420\u0435\u0441\u0435\u0440\u0447 \u0432 pub.dev<\/h2>\n<p>\u041d\u0430 pub.dev \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/pub.dev\/packages\/floodfill_image\" rel=\"noopener noreferrer nofollow\">floodfill_image<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f png \u0438 jpg \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p><strong>\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0444\u0438\u0447\u0438:<\/strong><br \/>1) \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0438 \u0441 \u0430\u0441\u0441\u0435\u0442\u043e\u0432<br \/>2) \u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430 \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f<br \/>3) \u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f<br \/>4) \u041c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u043e\u0442\u0442\u0435\u043d\u043a\u0443<br \/>5) \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e: \u043a\u043e\u043b\u043b\u0431\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 \u0440\u0430\u0441\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f, \u0438 \u0432\u0438\u0434\u0436\u0435\u0442 \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b:<\/strong><br \/>1) \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u043c\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c\u0438<br \/>2) \u0423\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<\/p>\n<p><strong>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/strong><br \/>1) \u041f\u0435\u0440\u0432\u043e\u0435, \u043d\u0430 \u0447\u0442\u043e \u044f \u043e\u0431\u0440\u0430\u0442\u0438\u043b \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, &#8212; \u044d\u0442\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u0418\u0437-\u0437\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u044f\u0434\u043e\u043c \u0441 \u043a\u043e\u043d\u0442\u0443\u0440\u0430\u043c\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u0431\u0435\u043b\u044b\u0435 \u043d\u0435\u0437\u0430\u043a\u0440\u0430\u0448\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (\u0432\u0438\u0434\u043d\u043e \u043d\u0430 \u0433\u0438\u0444\u043a\u0435)<br \/>2) \u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0438 \u043d\u0430 \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u0432\u043b\u0438\u044f\u0442\u044c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0430\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435<br \/>3) \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 2 \u043b\u0435\u0442 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u043b\u0430\u0441\u044c. \u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 0.0.8<\/p>\n<p>\u042d\u0442\u043e \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0445\u043e\u0440\u043e\u0448\u043e: \u0435\u0441\u043b\u0438 \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043d\u0435\u0442 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432 \u0441 \u043d\u043e\u0432\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u043f\u043e\u043b\u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0432\u043e\u0438 \u0437\u0430\u0434\u0430\u0447\u0438, \u0442\u043e \u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0445\u043e\u0440\u043e\u0448\u043e.<br \/>\u041d\u043e \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b &#8212; \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043a\u043e\u0434 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u0442\u044c. \u0422\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u0441\u0442\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b \u0442\u043e\u0433\u0434\u0430, \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0435\u043b\u0430\u044e\u0442 \u0435\u0433\u043e \u0432\u0441\u0435 \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c.<\/p>\n<p>\u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u044d\u0442\u0438\u043c \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441 &#8212; \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u043c\u0435\u044e\u0449\u0443\u044e\u0441\u044f \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043a\u043e\u043f\u0430\u044f\u0441\u044c \u0432 \u0447\u0443\u0436\u043e\u043c \u043a\u043e\u0434\u0435, \u043b\u0438\u0431\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u0438. <\/p>\n<p>\u0418 \u044f \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0431\u0440\u0430\u043b \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u041d\u0435 \u0431\u0443\u0434\u0443 \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0444\u043e\u0440\u043a \u0438 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043f\u043e url, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0442\u0430\u0442\u0435\u0439. \u0421\u043a\u0430\u0436\u0443 \u0442\u043e\u043b\u044c\u043a\u043e, \u0447\u0442\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438: \u043b\u0438\u043d\u0442\u0435\u0440 \u0440\u0443\u0433\u0430\u0435\u0442\u0441\u044f, \u0440\u0443\u043a\u0438 \u0447\u0435\u0448\u0443\u0442\u0441\u044f \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0442\u044c \u0432\u0441\u0435, \u0447\u0442\u043e \u0432\u0438\u0434\u0438\u0448\u044c.<\/p>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u043a\u043e\u043d\u0446\u043e\u0432, \u043c\u0430\u043b\u044b\u043c\u0438 \u043f\u043e\u0442\u0435\u0440\u044f\u043c\u0438 \u044f \u0434\u043e\u0441\u0442\u0438\u0433 \u043f\u0435\u0440\u0432\u044b\u0445 \u0434\u0432\u0443\u0445 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439: \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e. <\/p>\n<p>\u0418 \u043d\u0430 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u0440\u0435\u0448\u0435\u043d\u0430.<\/p>\n<hr\/>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043d\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043d\u0430 flutter, \u043d\u043e \u0435\u0441\u0442\u044c \u0413\u0443\u0433\u043b, \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u044f \u0438 ChatGPT<\/p>\n<h2>\u0427\u0442\u043e \u0437\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c flood fill?<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441, \u044f \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u043a\u0430\u043a \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0432\u0443\u0437\u0430 &#8212; \u043f\u043e\u0433\u0443\u0433\u043b\u0438\u043b \u0438 \u043d\u0430\u0448\u0435\u043b \u043e\u0442\u0432\u0435\u0442 \u0432 \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u0438. \u0422\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e:<\/p>\n<blockquote>\n<p><strong>Flood fill<\/strong>, also called\u00a0<strong>seed fill<\/strong>, is a\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Flooding_algorithm\" rel=\"noopener noreferrer nofollow\">flooding algorithm<\/a>\u00a0that determines and alters the area\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Glossary_of_graph_theory#Connectivity\" rel=\"noopener noreferrer nofollow\">connected<\/a>\u00a0to a given node in a multi-dimensional\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Array_data_structure\" rel=\"noopener noreferrer nofollow\">array<\/a>\u00a0with some matching attribute. It is used in the &#171;bucket&#187; fill tool of\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Paint_program\" rel=\"noopener noreferrer nofollow\">paint programs<\/a>\u00a0to fill connected, similarly-colored areas with a different color, and in games such as\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Go_(game)\" rel=\"noopener noreferrer nofollow\">Go<\/a>\u00a0and\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Minesweeper_(video_game)\" rel=\"noopener noreferrer nofollow\">Minesweeper<\/a>\u00a0for determining which pieces are cleared. A variant called\u00a0<strong>boundary fill<\/strong>\u00a0uses the same algorithms but is defined as the area\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Glossary_of_graph_theory#Connectivity\" rel=\"noopener noreferrer nofollow\">connected<\/a>\u00a0to a given node that does not have a particular attribute.<\/p>\n<\/blockquote>\n<p>\u0422\u0443\u0442 \u043a\u0430\u043a \u0431\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e. \u041f\u0440\u043e\u0441\u0442\u043e \u0434\u0430\u043b\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043c\u043d\u043e\u0433\u043e\u043c\u0435\u0440\u043d\u043e\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435. <\/p>\n<p>\u0412 \u0442\u043e\u0439 \u0436\u0435 \u0412\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b 4 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430:<\/p>\n<ol>\n<li>\n<p>Stack-based recursive implementation (four-way)<\/p>\n<\/li>\n<li>\n<p>Span filling<\/p>\n<\/li>\n<li>\n<p>Graph-theoretic filling<\/p>\n<\/li>\n<li>\n<p>Walk-based filling (Fixed-memory method)<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043d\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u0432\u0443\u0445\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432, \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430, \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435 \u0438 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0440\u0430\u0432\u043d\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u043d\u0430\u043f\u0438\u0448\u0435\u043c, \u043a\u0430\u043a\u043e\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439:<\/p>\n<pre><code class=\"dart\">abstract class FloodFill {   final List&lt;List&lt;int>> image;   const FloodFill(this.image);   void fill(int startX, int startY, int newColor); }<\/code><\/pre>\n<h2>Stack-based recursive implementation <\/h2>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432 \u043f\u043b\u0430\u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0433\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f. \u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f &#8212; \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u044c, \u0430 \u043f\u043e\u0442\u043e\u043c \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u0435, \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u043c \u043f\u043e \u0432\u0441\u0435\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c. \u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044e \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u042f \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b ChatGPT \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 flood fill \u043d\u0430 Dart.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>Write me an implementation of this algorithm for dart language:<br \/>Flood-fill (node):  <br \/>If node is not Inside return. <br \/>Set the node <br \/>Perform Flood-fill one step to the south of node. <br \/>Perform Flood-fill one step to the north of node <br \/>Perform Flood-fill one step to the west of node <br \/>Perform Flood-fill one step to the east of node <br \/>Return.<\/p>\n<p>use such interface:<\/p>\n<p>abstract class FloodFill {<br \/> final List&lt;List&lt;int>> image;<br \/> const FloodFill(this.image);<br \/> void fill(int startX, int startY, int newColor);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">class BasicFloodFill extends FloodFill {  const BasicFloodFill(List&lt;List&lt;int>> image) : super(image);    @override   void fill(int startX, int startY, int newColor) {     int originalColor = image[startX][startY];     _floodFillUtil(startX, startY, originalColor, newColor);   }    void _floodFillUtil(int x, int y, int originalColor, int newColor) {     \/\/ Check if current node is inside the boundary and not already filled     if (!_isInside(x, y) || image[x][y] != originalColor) return;      \/\/ Set the node     image[x][y] = newColor;      \/\/ Perform flood-fill one step in each direction     _floodFillUtil(x + 1, y, originalColor, newColor); \/\/ South     _floodFillUtil(x - 1, y, originalColor, newColor); \/\/ North     _floodFillUtil(x, y - 1, originalColor, newColor); \/\/ West     _floodFillUtil(x, y + 1, originalColor, newColor); \/\/ East   }    bool _isInside(int x, int y) {     return x >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y >= 0 &amp;&amp; y &lt; image[0].length;   } }<\/code><\/pre>\n<p>\u0422\u043e\u0442 \u0436\u0435 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u043d\u043e \u0443\u0436\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041e\u0447\u0435\u0440\u0435\u0434\u044c<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>Write me an implementation of this algorithm for dart language: <br \/>Flood-fill (node):   <br \/>Set Q to the empty queue or stack.   <br \/>Add node to the end of Q.   <br \/>While Q is not empty:     <br \/>Set n equal to the first element of Q.     <br \/>Remove first element from Q.     <br \/>If n is Inside:       <br \/>Set the n       <br \/>Add the node to the west of n to the end of Q.       <br \/>Add the node to the east of n to the end of Q.       <br \/>Add the node to the north of n to the end of Q.       <br \/>Add the node to the south of n to the end of Q.   <br \/>Continue looping until Q is exhausted.   <br \/>Return.  <\/p>\n<p>Use such interface:<br \/>abstract class FloodFill {<br \/> final List&lt;List&lt;int>> image;<br \/> const FloodFill(this.image);<br \/> void fill(int startX, int startY, int newColor);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">import 'dart:collection';  class Point {   final int x;   final int y;    const Point(this.x, this.y); }  class FloodFillQueueImpl extends FloodFill {   const FloodFillQueueImpl(List&lt;List&lt;int>> image) : super(image);    @override   void fill(int startX, int startY, int newColor) {     final int oldColor = image[startX][startY];     final Queue&lt;Point> queue = Queue();     queue.add(Point(startY, startX));      while (queue.isNotEmpty) {       final Point point = queue.removeFirst();       final int x = point.x;       final int y = point.y;        if (image[y][x] == oldColor) {         image[y][x] = newColor;          if (x > 0) {           queue.add(Point(x - 1, y));         }         if (x &lt; image[y].length - 1) {           queue.add(Point(x + 1, y));         }         if (y > 0) {           queue.add(Point(x, y - 1));         }         if (y &lt; image.length - 1) {           queue.add(Point(x, y + 1));         }       }     }   } }<\/code><\/pre>\n<h2>Span filling<\/h2>\n<p>\u042d\u0442\u043e\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0443\u0442\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044f \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043b\u0438\u043d\u0438\u0439 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0443\u0447\u0430\u0441\u0442\u043a\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u044d\u0442\u0438\u0445 \u043b\u0438\u043d\u0438\u0439 \u0441 \u043a\u0440\u0430\u044f\u043c\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>span<\/figcaption><\/div>\n<\/figure>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u043c\u043f\u0442<\/summary>\n<div class=\"spoiler__content\">\n<blockquote>\n<p>Write me an implementation of this algorithm for dart language: <br \/>fn fill(x, y):     <br \/>if not Inside(x, y) then return     <br \/>let s = new empty queue or stack     <br \/>Add (x, x, y, 1) to s     <br \/>Add (x, x, y &#8212; 1, -1) to s     <br \/>while s is not empty:         <br \/>Remove an (x1, x2, y, dy) from s         <br \/>let x = x1         <br \/>if Inside(x, y):             <br \/>while Inside(x &#8212; 1, y):                 <br \/>Set(x &#8212; 1, y)                 <br \/>x = x &#8212; 1             <br \/>if x &lt; x1:                 <br \/>Add (x, x1 &#8212; 1, y &#8212; dy, -dy) to s         <br \/>while x1 &lt;= x2:             <br \/>while Inside(x1, y):                 <br \/>Set(x1, y)                 <br \/>x1 = x1 + 1             <br \/>if x1 > x:                 <br \/>Add (x, x1 &#8212; 1, y + dy, dy) to s             <br \/>if x1 &#8212; 1 > x2:                 <br \/>Add (x2 + 1, x1 &#8212; 1, y &#8212; dy, -dy) to s             <br \/>x1 = x1 + 1             <br \/>while x1 &lt; x2 and not Inside(x1, y):                 <br \/>x1 = x1 + 1             <br \/>x = x1  <\/p>\n<p>Use such interface:  <br \/>abstract class abstract class FloodFill {<br \/> final List&lt;List&lt;int>> image;<br \/> const FloodFill(this.image);<br \/> void fill(int startX, int startY, int newColor);<br \/> }<\/p>\n<\/blockquote>\n<\/div>\n<\/details>\n<pre><code class=\"dart\">class FloodFillSpanImpl extends FloodFill {   const FloodFillSpanImpl(List&lt;List&lt;int>> image) : super(image);    \/\/ Check if the point is inside the canvas and matches the target color   bool _isInside(int x, int y, int targetColor) {     return x >= 0 &amp;&amp; y >= 0 &amp;&amp; x &lt; image.length &amp;&amp; y &lt; image[0].length &amp;&amp; image[x][y] == targetColor;   }    \/\/ Set a point to the replacement color   void _setColor(int x, int y, int replacementColor) {     image[x][y] = replacementColor;   }    @override   void fill(int startX, int startY, int newColor) {     final targetColor = image[startX][startY];      if (!_isInside(startX, startY, targetColor)) return;      var s = &lt;List&lt;int>>[];     s.add([startX, startX, startY, 1]);     s.add([startX, startX, startY - 1, -1]);      while (s.isNotEmpty) {       var tuple = s.removeLast();       var x1 = tuple[0];       var x2 = tuple[1];       var y = tuple[2];       var dy = tuple[3];        var nx = x1;       if (_isInside(nx, y, targetColor)) {         while (_isInside(nx - 1, y, targetColor)) {           _setColor(nx - 1, y, newColor);           nx--;         }         if (nx &lt; x1) {           s.add([nx, x1 - 1, y - dy, -dy]);         <\/code><\/pre>\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-367493","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/367493","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=367493"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/367493\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=367493"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=367493"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=367493"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}