إنشاء لعبة تيك تاك تو. الأسس النظرية للتنمية

تحياتي أيها الأصدقاء الأعزاء! سأوضح في هذا الدرس كيف يمكنك إنشاء لعبة متصفح - tic-tac-toe، باستخدام جافا سكريبت! تعلمون جميعًا ما هي هذه اللعبة وكيفية لعبها، لكن دعوني أذكركم مرة أخرى:

Tic-tac-toe هي لعبة منطقية بين لاعبين في حقل مربع مكون من 3 × 3 خلايا (ربما أكبر). أحدهما يلعب بـ "الصلبان" والثاني بـ "أصابع القدم".

ملاحظة. كما هو الحال في جميع دروس جافا سكريبت المماثلة، في نهاية المقالة، يمكنك تنزيل الملف المصدر، وكذلك رؤية نتيجة العمل في مثال تجريبي!

وصف اللعبة التي يتم إنشاؤها

دعونا نلقي نظرة على ميزات اللعبة:

  • تبدأ اللعبة فورًا بعد تحميل الصفحة؛
  • يتم اختيار حق الذهاب أولاً بشكل عشوائي (إما أن تبدأ بالمشي أو بالكمبيوتر)؛
  • يتم اختيار العلامة التي ستراهن عليها بشكل عشوائي (علامة متقاطعة أو صفر)؛
  • إذا فاز اللاعب، يتم تمييز الرموز الفائزة (شريط من الصلبان أو الأصفار) باللون الأخضر؛
  • إذا خسر اللاعب أمام الكمبيوتر، فسيتم تمييز الشريط باللون الأحمر؛
  • يوجد فوق الحقل سطر من المعلومات حيث يتم عرض النتيجة (النصر أو الهزيمة).

المنطق

لم أتوصل إلى خوارزميات معقدة (عالمية) لملعب مساحته 3 × 3، بل ذهبت في الاتجاه الآخر - القوة الغاشمة! (المزيد عن هذا لاحقًا). لقد حددت ثلاث مراحل متسلسلة رئيسية يرتكز عليها كل المنطق:

المرحلة 1: التحقق لمعرفة ما إذا كان اللاعب قد فاز؟

في هذه المرحلة، نتحقق مما إذا كان هناك 3 خلايا (على نفس السطر) مملوءة بنفس رموز اللاعب (تقاطعات أو أصفار). أولئك. بغض النظر عن ماهية النقلة (حتى الأولى)، فإننا دائمًا نتحقق أولاً مما إذا كان اللاعب قد فاز. وهذا هو شكل النصر:

المرحلة 2: التحقق - هل يستطيع الكمبيوتر الفوز بالخطوة التالية؟

في هذه المرحلة، نبحث عن خط حيث سيكون هناك خليتين مملوءتين بالكمبيوتر وخلية واحدة فارغة - أي أننا نحاول الفوز بسبب عدم انتباه اللاعب. هذا ما تبدو عليه الهزيمة (أي انتصار الكمبيوتر):

المرحلة 3: لن نسمح لك بالفوز!

نحن هنا نبحث عن نفس السطر كما في المرحلة الثانية، يجب ملء خليتين فقط بعلامات لعبة اللاعب، أي في هذه المرحلة لا نسمح للكمبيوتر بالخسارة من خلال وضع علامة في خلية فارغة. تمثل كل مرحلة وظيفة مستقلة - يمكنك رؤية ذلك في كود js أدناه.

تطبيق

تخطيط الملعب بسيط للغاية - الكتلة الرئيسية تحتوي على سطر من المعلومات (الفئة - النتيجة) و 9 كتل، وهي عبارة عن خلايا (الفئة - كتلة) تخطيط HTML للخلايا:

دورك!

تعد خلية الفئة المساعدة ضرورية لتحديد الخلية المطلوبة بدقة في الملعب. أنماط CSS للملعب:

Krestiki_noliki (العرض: 306 بكسل؛ الهامش: 0 تلقائي؛ ) .krestiki_noliki .block (العرض: 100 بكسل؛ الارتفاع: 100 بكسل؛ الحد: 1 بكسل صلب #ccc؛ المؤشر: المؤشر؛ تعويم: يسار؛ محاذاة النص: المركز؛ حجم الخط: 100 بكسل؛ ارتفاع الخط: 94 بكسل؛ )

الآن دعونا نلقي نظرة على كود JS بأكمله، وبعد ذلك سأتحدث عن النقاط الرئيسية:

$(document).ready(function())( var znak_user = "O"; var znak_comp = "X"; var rand_num = Math.round((Math.random() * (9 - 1) + 1)); إذا (rand_num > 3)( var znak_comp = "O"; var znak_user = "X"; $(".cell"+rand_num).text(znak_comp); ) var Exit_flag = false; var win_user_array = ["123"، " 456"، "789"، "147"، "258"، "369"، "159"، "357"]؛ // تحديد وظيفة فوز اللاعب check_3_user(znak)( for (var i = 0; i< 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == znak){ $("."+first+",."+second+",."+third).css("background-color", "#83e2c3"); $(".result").text("Вы выиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } } } //Определяем возможность победы компьютера function check_2_comp(znak){ for (var i = 0; i < 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == "" && exit_flag == false){ $("."+third).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } if($("."+first).text() == znak && $("."+second).text() == "" && $("."+third).text() == znak && exit_flag == false){ $("."+second).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } if($("."+first).text() == "" && $("."+second).text() == znak && $("."+third).text() == znak && exit_flag == false){ $("."+first).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } } } //Определяем ход компьютера function check_2_user(znak){ for (var i = 0; i < 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if(exit_flag == false){ if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == ""){ $("."+third).text(znak_comp); exit_flag = true; } } if(exit_flag == false){ if($("."+first).text() == znak && $("."+second).text() == "" && $("."+third).text() == znak){ $("."+second).text(znak_comp); exit_flag = true; } } if($("."+first).text() == "" && $("."+second).text() == znak && $("."+third).text() == znak){ $("."+first).text(znak_comp); exit_flag = true; } if(exit_flag) break; } } $(".krestiki_noliki .block").click(function(){ //Если клетка пустая if($(this).text() == ""){ $(this).text(znak_user); check_3_user(znak_user); check_2_comp(znak_comp); check_2_user(znak_user); if(exit_flag == false){ for (var i = 1; i < 10; i++) { if($(".cell"+i).text() == ""){ $(".cell"+i).text(znak_comp); break; } } }else exit_flag = false; } }); });

أولاً، نعلن عن المتغيرات: znak_user - في هذا المتغير نقوم بتخزين العلامة التي سيلعب بها المستخدم (افتراضيًا، يتم تخزين الصفر هناك - هذا هو المربع الإنجليزي "O"). znak_comp - في هذا المتغير نقوم بتخزين العلامة التي سيلعب بها الكمبيوتر (افتراضيًا، يتم تخزين التقاطع هناك - هذا هو المربع الإنجليزي "X").

المنطق هو كما يلي: إذا كان الرقم العشوائي أكبر من 3، فإن الكمبيوتر يلعب بالأصفار، ويقوم (الكمبيوتر) بالخطوة الأولى.

يمكنك تغيير هذا المنطق بما يناسبك، على سبيل المثال، يمكنك إنشاء عدة أرقام عشوائية من أجل توفير المزيد من الخيارات لمن سيكون الأول وما هي العلامات. Exit_flag - هذه العلامة (المتغيرة) مسؤولة عن الخروج من الوظيفة، أي، على سبيل المثال، عندما يقوم الكمبيوتر بالفعل بحركته، وتحتاج إلى الخروج من الوظيفة وتمرير الحركة إلى اللاعب. win_user_array - تقوم هذه المصفوفة بتخزين جميع الخيارات الفائزة لملء الخلايا. ولتوضيح الأمر، دعونا نلقي نظرة على هذه الصورة:

كل عنصر من عناصر المصفوفة عبارة عن سلسلة من ثلاثة أرقام، وهي مجموعة فائزة، على سبيل المثال، إذا قمت بملء الخلايا تحت الأرقام 1 و 2 و 3، فسيحدث النصر (أو الهزيمة). كما ترون، هناك 8 خيارات فائزة إجمالاً، ومهمتنا هي دراسة كل هذه الخيارات. التالي يأتي 3 وظائف:

  1. check_3_user();
  2. check_2_comp();
  3. check_2_user();

تم توضيح الغرض من هذه الوظائف (في ثلاث خطوات) في قسم المنطق (أعلاه). يتم استدعاء هذه الوظائف من خلال النقر على أي من الخلايا الموجودة في الحقل. يتم تمرير معلمة (znak) إلى كل وظيفة - وهي علامة اللاعب أو الكمبيوتر (تقاطع أو صفر)، على سبيل المثال، إلى الوظيفة التي تحدد فوز اللاعب (check_3_user)، نقوم بتمرير علامة اللاعب بالترتيب للعثور على 3 علامات متطابقة على نفس السطر.

بعد ثلاث وظائف (إذا لم يقم الكمبيوتر بالتحرك بعد)، يقوم الكمبيوتر بملء إحدى الخلايا الحرة. هنا، يمكنك تعقيد طريقة اللعب، على سبيل المثال، من خلال جعلها بحيث إذا كانت الخلية المركزية حرة (الخلية رقم 5)، فقم بالمراهنة عليها أولاً؛ وإذا كانت مشغولة، فقم بالمراهنة في إحدى الزوايا الحرة (هذه هي الخلايا رقم 1 و3 و7 و9) وما إلى ذلك - بشكل عام، الأمر متروك لتقديرك.

وهذا، من حيث المبدأ، هو كل ما هو مطلوب لإنشاء مثل هذه اللعبة.

يمكنك الآن مشاهدة اللعبة باستخدام مثال تجريبي وتنزيل الملف المصدر (ملف واحد إجمالاً).

08/06/2018 - شكرًا لاهتمامكم بكاتب الرسالة: باتفاكان باغداساريان، تم إصلاح الخلل عندما كان لدى الكمبيوتر عدة الخيارات الممكنةتم طلاء الانتصارات وجميع تحركاته الفائزة (من 4 إلى 6 خلايا بدلاً من 3).

هذا كل شيء بالنسبة لي، أتمنى أن يكون هذا الدرس مفيدًا لك، أتمنى لك حظًا سعيدًا، إلى اللقاء!

كيفية كتابة روبوت لا يمكن التغلب عليه في لعبة tic-tac-toe، أو مقدمة لقاعدة minimax

من المحتمل جدًا أنه بعد مئات من ألعاب tic-tac-toe، تساءلت: ما هي الخوارزمية المثالية؟ ولكن إذا كنت هنا، فمن المحتمل أنك حاولت أيضًا كتابة تطبيق لهذه اللعبة. سنذهب أبعد من ذلك ونكتب روبوتًا سيكون من المستحيل التغلب عليه في لعبة tic-tac-toe. توقع سؤالك "لماذا؟"، فسنجيب: بفضل الخوارزمية.

مثل لاعب الشطرنج المحترف، تحسب هذه الخوارزمية تصرفات الخصم بعدة تحركات للأمام - حتى تصل إلى نهاية اللعبة، سواء كان ذلك انتصارًا أو هزيمة أو تعادلًا. بمجرد وصوله إلى هذه الحالة النهائية، سيمنح الذكاء الاصطناعي نفسه عددًا موجبًا من النقاط (في حالتنا +10) للفوز، وسالبًا (-10) للخسارة، ومحايدًا (0) للتعادل.

وفي الوقت نفسه، تقوم الخوارزمية بإجراء حسابات مماثلة لتحركات اللاعب. سيختار الحركة ذات أعلى الدرجات إذا تحرك الذكاء الاصطناعي، والحركة ذات أقل درجة إذا تحرك اللاعب. باستخدام هذه الاستراتيجية، يتجنب مينيماكس الهزيمة.

حاول لعب هذه اللعبة.

يمكن وصف خوارزمية minimax بسهولة على أنها دالة متكررة تقوم بما يلي:

  1. إرجاع قيمة إذا تم العثور على الحالة النهائية (+10، 0، -10)،
  2. يمر عبر جميع الخلايا الفارغة في الميدان،
  3. يستدعي الدالة minimax لكل منها (العودة)،
  4. يقيم القيم التي تم الحصول عليها
  5. ويعيد الأفضل.

إذا لم تكن على دراية بالتكرار، فعليك مشاهدة هذه المحاضرة من دورة Harvard CS50:

لفهم كيفية عمل Minimax، دعونا نكتب تنفيذه ونصمم سلوكه. سنتعامل مع هذا في القسمين التاليين.

تنفيذ الحد الأدنى

سننظر إلى الموقف الذي تقترب فيه اللعبة من نهايتها (انظر الصورة أدناه). نظرًا لأن minimax يمر بجميع حالات اللعبة الممكنة (وهناك مئات الآلاف منها)، فمن المنطقي التفكير في نهاية اللعبة - وبهذه الطريقة سيتعين علينا تتبع عدد أقل من استدعاءات الوظائف المتكررة (9 في المجموع).

دع الذكاء الاصطناعي يلعب بالصلبان، والشخص - بالأصفار.

لتسهيل العمل مع الحقل، دعنا نعلنه كمصفوفة مكونة من 9 عناصر بقيم تساوي محتويات الخلايا. دعونا نملأها بالصلبان وأصابع القدم، كما في الصورة أعلاه، ونسميها origBoard.

var origBoard = ["O"،1"،X"،X"،4،X"،6"،O"،O"]؛

بعد ذلك، سنعلن عن المتغيرين aiPlayer وhuPlayer ونخصص لهما القيمتين "X" و"O" على التوالي.

بالإضافة إلى ذلك، سنحتاج إلى وظيفة تبحث عن المجموعات الفائزة وترجع قيمة حقيقية إذا كان البحث ناجحًا، ووظيفة تخزن مؤشرات الخلايا المتاحة.

/* الحالة الأوليةمجالس يا | | X --------- X | | X --------- | يا | O */ var origBoard = ["O",1 ,X",X",4 ,X", 6 ,O","O"]; // شخص var huPlayer = “O”; // AI var aiPlayer = “X”; // تُرجع قائمة بمؤشرات الخلايا الفارغة على اللوحة functionemptyIndices(board)( return board.filter(s => s != "O" && s != "X"); ) // المجموعات الفائزة مع الأخذ بعين الاعتبار وظيفة المؤشرات الفوز (لوحة، لاعب)( if((لوحة == لاعب && لوحة == لاعب && لوحة == لاعب) || (لوحة == لاعب && لوحة == لاعب && لوحة == لاعب) || (لوحة = = لاعب && لوحة == لاعب && لوحة == لاعب) || (لوحة == لاعب && لوحة == لاعب && لوحة == لاعب) || (لوحة == لاعب && لوحة == لاعب && لوحة == لاعب) || |(لوحة == لاعب && لوحة == لاعب && لوحة == لاعب) || (لوحة == لاعب && لوحة == لاعب && لوحة == لاعب) || (لوحة == لاعب && لوحة == لاعب && لوحة = = لاعب)) (إرجاع صحيح؛) آخر (إرجاع خطأ؛))

لذلك دعونا نحدد دالة minimax باستخدام وسيطتين: newBoard وplayer. ثم سنجد مؤشرات الخلايا الحرة في الحقل ونمررها إلى المتغير availSpots.

// وظيفة minimax الرئيسية function minimax(newBoard, player)( // الخلايا المتوفرة var availSpots =emptyIndices(newBoard);

بالإضافة إلى ذلك، نحتاج إلى تتبع الحالات النهائية وإرجاع القيم المناسبة. إذا فاز "الصفر"، فأنت بحاجة إلى العودة -10، إذا كان "الصليب" - +10. إذا كان حجم مصفوفة availSpots صفرًا، فلا توجد خلايا حرة، وستنتهي اللعبة بالتعادل، ويجب إرجاع الصفر.

// التحقق من الحالة الطرفية (الفوز/الخسارة/التعادل) // وإرجاع القيمة وفقًا لذلك إذا (wining(newBoard, huPlayer))( return (score:-10); ) else if (wining(newBoard, aiPlayer)) (return (score:10); ) else if (availSpots.length === 0)(return (score:0); )

بعد ذلك، تحتاج إلى جمع النقاط من كل خلية فارغة. للقيام بذلك، سنقوم بإنشاء مصفوفة من الحركات ونمر عبر جميع الخلايا الفارغة في حلقة، ونضع المؤشرات والنقاط الخاصة بكل حركة في كائن الحركة.

ثم قمنا بتعيين فهرس الخلية الفارغة، التي تم تخزينها كرقم في origBoard، مساويًا لخاصية الفهرس لكائن النقل. ثم سننتقل كلاعب الحالي إلى خلية فارغة في الحقل الجديد newBoard ونستدعي وظيفة minimax من اللاعب الآخر والحقل الناتج newBoard . بعد ذلك، تحتاج إلى وضع خاصية النتيجة للكائن الذي تم إرجاعه بواسطة الدالة minimax في خاصية النتيجة للكائن المتحرك.

إذا لم يجد Minimax حالة نهائية، فإنه يستمر في التحرك بشكل متكرر بشكل أعمق في اللعبة حتى يصل إلى حالة نهائية. وبعد ذلك يقوم بنقل نقاط هذا "المستوى" من التكرار إلى مستوى أعلى.

أخيرًا، تقوم الدالة بإعادة تعيين التغييرات إلى newBoard وتضع كائن النقل في مصفوفة الحركات.

// مصفوفة لتخزين كافة الكائنات var التحركات = ; // قم بالتكرار عبر الخلايا المتاحة لـ (var i = 0; i< availSpots.length; i++){ //create an object for each and store the index of that spot var move = {}; move.index = newBoard]; // совершить ход за текущего игрока newBoard] = player; //получить очки, заработанные после вызова минимакса от противника текущего игрока if (player == aiPlayer){ var result = minimax(newBoard, huPlayer); move.score = result.score; } else{ var result = minimax(newBoard, aiPlayer); move.score = result.score; } // очистить клетку newBoard] = move.index; // положить объект в массив moves.push(move); }

يحتاج Minimax بعد ذلك إلى تحديد أفضل حركة من مجموعة الحركات. إنه يحتاج إلى الحركة بأعلى الدرجات إذا كان الذكاء الاصطناعي يتحرك، وبأقل درجة إذا كانت حركة بشرية. وبالتالي، إذا كانت قيمة player هي aiPlayer، فإن الخوارزمية تقوم بتهيئة المتغير bestScore إلى عدد صغير جدًا وتتكرر عبر مصفوفة الحركات: إذا كانت نتيجة الحركة تستحق نقاطًا أكبر من bestScore، فستتذكر الخوارزمية تلك الخطوة. في حالة التحركات ذات النقاط المتساوية، تتذكر الخوارزمية الحركة الأولى.

في حالة كون اللاعب مساويًا لـ huPlayer، يكون كل شيء متشابهًا - الآن فقط تتم تهيئة bestScore لعدد كبير، ويبحث minimax عن الحركة بأقل عدد من النقاط.

ونتيجة لذلك، يقوم minimax بإرجاع الكائن المخزن في bestMove .

// إذا كانت هذه حركة الذكاء الاصطناعي، فقم بالتمرير عبر الحركات وحدد الحركة التي تحتوي على أكبر عدد من النقاط var bestMove; إذا (player === aiPlayer)( var bestScore = -10000; for(var i = 0; i< moves.length; i++){ if(moves[i].score >bestScore)( bestScore = التحركات[i].score; bestMove = i; ) ) )else( // وإلا قم بالتكرار خلال الحركات وحدد الحركة بأقل عدد من النقاط var bestScore = 10000; for(var i = 0; i< moves.length; i++){ if(moves[i].score < bestScore){ bestScore = moves[i].score; bestMove = i; } } } // вернуть выбранный ход (объект) из массива ходов return moves; }

في القسم التالي، سنقوم بمحاكاة برنامجنا لفهم كيفية عمله.

مينيماكس في العمل

باستخدام الرسم البياني أدناه، سنقوم بتحليل نموذج الخوارزمية خطوة بخطوة.

ملحوظة: في الرسم التخطيطي، تشير الأرقام الكبيرة إلى الرقم التسلسلي لاستدعاء الوظيفة، وتشير المستويات إلى عدد الحركات التي قامت بها الخوارزمية.

  1. يتم تغذية origBoard وaiPlayer إلى الخوارزمية. فهو يقوم بإعداد قائمة بالخلايا الفارغة الثلاث التي تم العثور عليها، ويتحقق من محدودية الحالة، ويمر عبر جميع الخلايا الفارغة. تقوم الخوارزمية بعد ذلك بتغيير newBoard، وتضع aiPlayer في المربع الفارغ الأول. بعد ذلك، يستدعي نفسه من newBoard وhuPlayer وينتظر المكالمة الثانية لإرجاع قيمة.
  2. بينما لا يزال استدعاء الوظيفة الأول قيد التشغيل، يتم تشغيل الثاني، مما يؤدي إلى إنشاء قائمة من خليتين فارغتين، والتحقق من الحالة المحدودة، والتكرار عبر جميع الخلايا الفارغة. يقوم الاستدعاء الثاني بعد ذلك بتعديل newBoard عن طريق وضع huPlayer في المربع الفارغ الأول. بعد ذلك، يستدعي نفسه من newBoard وaiPlayer وينتظر المكالمة الثالثة لإرجاع قيمة.

  3. نظرًا لأن الاستدعاء الثاني عثر على خليتين فارغتين، يقوم minimax بتعديل newBoard عن طريق وضع huPlayer في الخلية الفارغة الثانية. ثم يطلق على نفسه اسم newBoard وaiPlayer.

  4. تقوم الخوارزمية بتجميع قائمة بالخلايا الفارغة وتسجل انتصار اللاعب بعد التحقق من محدودية الحالة. لذلك تقوم بإرجاع كائن بحقل نقاط (-10).

    في استدعاء الدالة الثاني، تتلقى الخوارزمية القيم التي يتم إرجاعها من المستوى الأدنى عن طريق استدعاءات الدالة الثالثة والرابعة. وبما أن حركة huPlayer أنتجت هاتين النتيجتين، فإن الخوارزمية تختار النتيجة الأصغر. وبما أنهما متماثلان، تختار الخوارزمية الخيار الأول وتمرره إلى استدعاء الوظيفة الأول.

    في هذه المرحلة، تلقى استدعاء الوظيفة الأول تقديرًا لانتقال aiPlayer إلى أول خلية فارغة. ثم يقوم بتعديل newBoard عن طريق وضع aiPlayer في المربع الفارغ الثاني. بعد ذلك، فإنه يطلق على نفسه من newBoard وhuPlayer.

  5. في استدعاء الوظيفة الخامسة، تقوم الخوارزمية بتجميع قائمة بالخلايا الفارغة وتسجيل انتصار الذكاء الاصطناعي بعد التحقق من محدودية الحالة. لذلك تقوم بإرجاع كائن مع حقل نقاط +10.

    بعد ذلك، يقوم الاستدعاء الأول بتعديل newBoard عن طريق وضع aiPlayer في الخلية الفارغة الثالثة. ثم يطلق على نفسه اسم newBoard وhuPlayer.

  6. يقوم الاستدعاء السادس بإنشاء قائمة من خليتين فارغتين، والتحقق من محدودية الحالة والتكرار عبر جميع الخلايا الفارغة. ثم يقوم بتعديل newBoard عن طريق وضع huPlayer في المربع الفارغ الأول. ثم يستدعي نفسه من newBoard وaiPlayer وينتظر المكالمة السابعة لإرجاع قيمة.
  7. يقوم الاستدعاء الجديد بإنشاء قائمة بخلية واحدة فارغة، والتحقق من الحالة المحدودة، وتعديل newBoard لوضع aiPlayer في الخلية الفارغة. بعد ذلك، يستدعي نفسه من newBoard وhuPlayer وينتظر هذا الاستدعاء لإرجاع قيمة.
  8. التحدي الثامن هو قائمة فارغةالخلايا الفارغة ويسجل انتصار aiPlayer بعد التحقق من حالة الأطراف. ولذلك، فإنه يعيد كائنًا بحقل عدد يساوي (+10) إلى المستوى الأعلى، وهو الاستدعاء السابع.

    تلقت المكالمة السابعة قيمة إيجابية واحدة فقط من المستويات الأدنى. وبما أنه تم الحصول على هذه القيمة أثناء دور aiPlayer، فإن الخوارزمية ترجع أكبر قيمة تم الحصول عليها. لذلك تقوم بإرجاع قيمة موجبة (+10) إلى المستوى الأعلى، المكالمة السادسة.

    نظرًا لأن الاستدعاء السادس عثر على خليتين فارغتين، يقوم minimax بتعديل newBoard عن طريق وضع huPlayer في الخلية الفارغة الثانية. ثم يطلق على نفسه اسم newBoard وaiPlayer.

  9. بعد ذلك، تقوم الخوارزمية بتجميع قائمة بالخلايا الفارغة وتسجيل انتصار aiPlayer بعد التحقق من محدودية الحالة. ولذلك، فإنه يعيد كائنًا بحقل نقاط يساوي (+10) إلى المستوى أعلاه.

    في هذه المرحلة، يجب على التحدي السادس الاختيار بين النتيجة (+10) التي أعادها التحدي السابع والنتيجة (-10) التي أعادها التحدي التاسع. نظرًا لأن حركة huPlayer أنتجت هاتين النتيجتين، فإن الخوارزمية تختار النتيجة الأصغر وتعيدها إلى المستوى التالي ككائن يحتوي على حقول النتيجة والفهرس.

    أخيرًا، يتم تقييم جميع الفروع الثلاثة للاستدعاء الأول (-10، +10، -10). وبما أن حركة aiPlayer أنتجت هذه النتائج الثلاث، فإن الخوارزمية تختار الكائن الذي يحتوي على أعلى الدرجات (+10) ومؤشره (4).

في السيناريو أعلاه، يقرر Minimax ذلك الاختيار الأمثلسيكون هناك انتقال إلى الساحة المركزية للميدان.

نهاية!

يجب أن تكون قد فهمت الآن كيفية عمل خوارزمية الحد الأدنى. حاول كتابة تطبيق بنفسك، أو انظر إلى مثال على GitHub أو CodePen وقم بتحسينه.

إذا كنت مهتمًا بموضوع الذكاء الاصطناعي في الألعاب، فنوصيك بقراءة موادنا حول هذا الموضوع.

الخطوة 1. تكوين معلمات النموذج 1. لتخصيص نموذج، قم بتعيين حجمه
510 نقطة أفقيًا و480 نقطة أفقيًا
رَأسِيّ. الحد الأقصى والحد الأدنى
تشير إلى حجم يساوي نفس القيم.
2. قم بتسمية الشكل "تيك تاك تو".
3. بالنسبة لخلفية النموذج، استخدم ملفًا من المجلد
الصور تحت اسم الخلفية.png، ووضعها
في وسط النموذج.
4. للحصول على أيقونة في سطر العنوان
استخدم ملف الاستخدام من المجلد
الصور تحت اسم Menu4.ico.
5. يجب تحديد لون خلفية النموذج
كريم النعناع.

الخطوة 2. إضافة زر وملصق إلى النموذج

1. بالنسبة للعناصر الموضوعة، قم بالتغيير
حجم الخط إلى 12 ومجموعة الخلفية
شفاف.

1. قم بإنشاء شريط قوائم يحتوي على العناصر الموجودة فيه
كما هو موضح في الصورة.

الخطوة 3. إضافة شريط القوائم إلى النموذج

1. في عنصر القائمة ملف، قم بإنشاء أمر
مخرج.
2. ل
فرق
مخرج
دعونا يصف
رمز البرنامج هو نفسه كما في
التطبيق السابق.

الخطوة 3. إضافة شريط القوائم إلى النموذج

1. في عنصر قائمة اللعبة، قم بإنشاء فريق
لعبة جديدة.
2. سنكتب أمر لعبة جديدة
رمز البرنامج في المستقبل عبر
بضع خطوات.

الخطوة 3. إضافة شريط القوائم إلى النموذج

1. في عنصر القائمة تعليمات، قم بإنشاء أمر
حول البرنامج.
2. بالنسبة للأمر حول البرنامج، قم بإنشاء أمر جديد
نموذج وكتابة رمز البرنامج
مماثلة كما في السابق
طلب.

1. عن طريق سحب كائن PictureBox إلى النموذج
تغيير حجمه إلى 100x100.
2. قم بتعيين خلفية شفافة.
3. ضع PictureBox كما هو موضح في
الصورة أعلى الخلية الأولى من حقل اللعبة.

الخطوة 4. إضافة كائنات PICTUREBOX إلى النموذج

1
2
3
4
5
6
7
8
9
1. نضع فوق الخلايا المتبقية
كائنات PictureBox، نسخ من الأول
كائن، وفقا للترقيم المشار إليه
الصور.

1. قبل كتابة التعليمات البرمجية
اللازمة في المجلد
\استوديو مرئي
2010\المشاريع\تيك تاك تو\X's
يجب إعادة تسجيل الأصفار\bin\Debug\
الملفات x.png، 0.png، none.png من مجلد الصور.
2. انقر نقرًا مزدوجًا بالماوس الأيسر على الأول
مربع صورة.

الخطوة 5. إضافة رمز لكائنات PICTUREBOX

1. قم بإنشاء مصفوفة ثنائية الأبعاد يمكن الوصول إليها لجميع العناصر الموجودة فيها
تم إنشاؤها في شكل عناصر 3x3 تتكون من أعداد صحيحة. حالا
نملأها بالأصفار عند الإعلان عنها. للخلايا الفارغة نحن
سنستخدم 0، لـ "التقاطعات" - 1، ولـ "الأصفار" - 1.

الخطوة 5. إضافة رمز لكائنات PICTUREBOX

في الإجراء عند النقر على الأول
PictureBox، أضف عامل التشغيل
خيار
أيّ
سوف
تحقق من حالة
خلايا المصفوفة. إذا كانت القيمة
خلايا الصفيف ستكون مساوية لـ 0، والتي
وهذا يعني أنه لا يوجد "صفر" ولا
"الصليب" ثم في هذه الخلية
المصفوفة مكتوبة 1 و in
PictureBox1
عرض
صورة "الصليب" وإذا
ستكون قيمة خلية الصفيف
يساوي 1 ثم يحتوي على
"الصليب" و 0 مكتوب فيه و
يتم عرض خلية فارغة.

الخطوة 5. إضافة رمز لكائنات PICTUREBOX

1
2
3
4
5
6
7
8
9



بالنسبة لخلايا الحقل المتبقية، قم بإضافة الكود
نفس كما في أول واحد يتغير فقط
رقم كائن PictureBox وعنوان الخلية
مجموعة مصفوفة.
مثال للخلية الثانية:

في الإجراء عند النقر فوق زر
يضيف
المشغل أو العامل
دورة
من يتحقق
جميع الخلايا ابتداء من الأول إلى
وجود الخلايا الفارغة. و إذا
الخلية فارغة،
ثم فيها
"الصفر" مكتوب، أي في
يتم كتابة خلية الصفيف -1.
للراحة في العمل المستقبلي
المتغيرات
أنا،
ي
أيّ
تستخدم لتكرار الحلقات
سنعلن عن النموذج بأكمله.

الخطوة 6. إضافة رمز لزر المشي

لعرض الأصفار على
الألعاب
مجال
ضروري
إضافة رمز البرنامج إلى الجسم
دورة فحص الخلايا للفراغ.
باستخدام عبارة متداخلة
المتفرعة
سوف
تجري
تحليل عنوان خلية الصفيف ل
إخراج صفر في الصحيح
مربع صورة.
نضيف أيضًا بيان استراحة
للإنهاء المبكر
حلقة عند العثور على فارغة
الخلايا.

الخطوة 6. إضافة رمز لزر المشي

للإشارة إلى حالة اللعبة
يتم استخدام عنصر الواجهة
التسمية1. منذ أن يتحرك اللاعب دائمًا
أولاً
الذي - التي
في
التحميلات
التطبيقات
ضروري
الخامس
عنصر
التسمية1
ضروري
يعكس
عبارات "لك
يتحرك."
ل
هذا
دعونا نخلق
عامل
إجابة
أيّ
دعونا نخصص هذه العبارة. أ
عند تحميل النموذج متغير
يجب أن يتم تعيينه للعنصر
Label1، لإنشاء ما يلزم
إجراءات
ضروري
انقر نقرا مزدوجا أولا
حسب النموذج

الخطوة 7. إضافة رمز البرنامج لعنصر قائمة اللعبة الجديد

عند الضغط على الأمر جديد
سيتم إعادة ضبط اللعبة
جميع خلايا المصفوفة، لتحل محل الكل
"الصلبان" و"أصابع القدم" على
خلايا فارغة. أيضا الاستنتاج
علامات "تحركك".

الخطوة 8. إخراج نتيجة اللعبة

للتحقق من نتائج التحركات
ضروري
تحليل
محتويات الصفوف والأعمدة و
الأقطار. إذا كانت جميع العناصر الثلاثة
تساوي 1 فهذا انتصار للاعب و
إذا كان ثلاثة -1 فهذه هزيمة
لاعب.
التحقق من النصر مطلوب
سلوك
قبل
تقدم
حاسوب،
أ
يفحص
الهزيمة بعد.
الأمر الأخير من الإجراء
سيتم عرض النتائج على الشاشة
تقدم.

الخطوة 8. إخراج نتيجة اللعبة

رمز البرنامج للتحقق من فوز المستخدم:
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
if (znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1 && znacheniyeYacheyki == 1) otvet = "أنت فزت";
رمز البرنامج للتحقق من فوز المستخدم:
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "لقد خسرت";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "لقد خسرت";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "لقد خسرت";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "لقد خسرت";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "لقد خسرت";
if (znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1 & znacheniyeYacheyki == -1) otvet = "لقد خسرت";
label1.Text = الإجابة؛

الخطوة 9 تحسين إمكانية اللعب

لتحسين إمكانية اللعب
بدلا من الإخراج التسلسلي
إلى أول فارغة
خلايا "الأصفار" ننفذها
الإخراج عبر مولد عشوائي
أعداد.
للقيام بذلك تحتاج إلى إضافة
متغير منطقي واحد
uslovie، وقم بتغيير نوع الحلقة من For
في حين، لأننا لا نعرف
العدد الدقيق للتكرار
مولد كهرباء أرقام عشوائيةالوداع
لن يقع في خلية فارغة.

وزارة التعليم والعلوم في روسيا

المؤسسة التعليمية لميزانية الدولة الفيدرالية للتعليم المهني العالي

"جامعة ولاية فولوغدا"

قسم الأتمتة وهندسة الحاسوب

مذكرة توضيحية لمشروع الدورة في التخصص

أساسيات البرمجة والخوارزميات

"تيك تاك تو"

مكتملطالب المجموعة EM-21

بوتوروفا إل يو.

قبلترزهوتسكايا إس يو.

مقدمة

1. تحليل المشكلة وتحديد متطلبات البرنامج المراد تطويره

1 غرض البرنامج ومستخدميه والوظائف الرئيسية والأهداف المنشودة أثناء التطوير

2 مراجعة البرامج المعروفة التي تؤدي وظائف مماثلة

3 الأساس النظري للتنمية

4 اختيار أدوات التطوير

جزء التصميم من التطوير

1 تطوير واجهة المستخدم

2.2 تطوير هياكل البيانات (في الخارجية وذاكرة الوصول العشوائي)

2.3 تطوير وتحليل الخوارزميات

تنفيذ البرنامج بلغة C++

1 بنية البرنامج

2 اختيار المكونات المرئية وغير المرئية القياسية

نتائج الإختبار

خاتمة

فهرس

التطبيقات

مقدمة

Tic-tac-toe هي لعبة منطقية بين خصمين في حقل مربع مكون من 3 × 3 خلايا أو أكبر (حتى "حقل لا نهاية له"). يلعب أحد اللاعبين بـ "الصلبان" والثاني بـ "أصابع القدم". أصبحت هذه اللعبة شائعة قبل وقت طويل من ظهور أجهزة الكمبيوتر، فقط قبل أن يتم لعبها بقطعة ورق عادية وقلم. تستخدم اللعبة الصينية التقليدية الحجارة السوداء والبيضاء.

في هذا العمل بالطبعيتم الحفاظ على القواعد الأساسية والحجم القياسي لملعب اللعبة (3 × 3 خلايا). من أجل راحة اللعبة، يتم ترك الحق في إجراء الخطوة الأولى للمستخدم، أي "الصلبان".

Tic Tac Toe هو برنامج مصمم للترفيه عن المستخدم، وبالتالي فإن واجهته، في هذه الدورة التدريبية، مصممة بأسلوب لعب مع مزيج من الألوان الإيجابية التي تزيد من الجزء العاطفي من عملية اللعبة.

هناك ثلاثة أنواع في اللعبة: X مقابل 0 - مستخدم مقابل مستخدم، "المستوى الأول مع الكمبيوتر" - لأولئك الذين يتعلمون فقط أساسيات اللعبة العالمية، والمستوى "المستوى الثاني مع الكمبيوتر" - لأولئك الذين واثقون تماما من انتصارهم. في المستويين 1 و 2، هناك ثلاث نتائج محتملة: "الفوز" و"الخسارة" و"التعادل". يتم تثبيت المكاسب إذا كانت الخطوط الرأسية أو الأفقية أو القطرية مملوءة بالكامل بالتقاطعات أو الأصفار.

إذا انتهت الخلايا الحرة للميدان، ولكن لا أحد يفوز، فستعتبر اللعبة منتهية بـ "التعادل".

1. تحليل المشكلة وتحديد متطلبات البرنامج المراد تطويره

واجهة البرنامج المتقاطعة

1.1 الغرض من البرنامج ومستخدميه والوظائف الرئيسية والأهداف المتبعة أثناء التطوير

الغرض من هذا البرنامج، في المقام الأول، هو الترفيه عن المستخدمين، وإضفاء البهجة على وقت انتظار الشخص، لأن أي عمل يتطلب الراحة، وهذه اللعبة البسيطة ستساعدك على الاسترخاء وإبعاد عقلك عن الشؤون اليومية. ينتمي "Tic Tac Toe" أيضًا إلى فئة الألعاب الفكرية والمنطقية المصممة لتدريب التفكير المنطقي وتسمح لك بتركيز الانتباه وتطوير الذاكرة.

الجمهور المستهدف من المستخدمين هم الأطفال والمراهقين، وكذلك البالغين. المعايير الرئيسية لاستخدام المنتج هي القدرة على قراءة النص المكتوب في البرنامج والقدرة على تحديد المهمة الضرورية للكمبيوتر باستخدام الأزرار.

ومن هذا يمكننا أن نستنتج أن المهام الرئيسية هي: مهمة الترفيه ومهمة تنمية الإمكانات المنطقية للشخص.

1.2 مراجعة البرامج المعروفة التي تؤدي وظائف مماثلة

يمكنك العثور على الإنترنت على عدد كبير من الأعمال التي تنفذ هذه اللعبة. يوجد حاليًا العديد من نظائرها لهذه اللعبة التي ابتعدت عن المعايير الأصلية. ومن أمثلة هذه البرامج برنامج "Tic-tac-toe on a Endless field" و"Tic-tac-toe 3D". كما أنه في العديد من الألعاب يتم استبدال "الصلبان" و"أصابع القدم" برموز أخرى، مثل "الحجارة" على سبيل المثال.

مشروع الدورة التدريبية الخاص بي هو تطبيق للكمبيوتر الشخصي. اللعبة مخصصة لمستخدم واحد، خصمه هو الذكاء الاصطناعي (أو الكمبيوتر)، ومستخدمين. يتم تقديمه في حقل كلاسيكي 3x3.

الأكثر إثارة للاهتمام وغير عادية، في رأيي، كانت لعبة "Tic Tac Toe 3D". ولهذا السبب اخترته للمقارنة.

تعد لعبة tic-tac-toe ثلاثية الأبعاد أكثر إثارة للاهتمام من تلك الموجودة على الورق أو على السبورة العادية. هناك المزيد من فرص الفوز والخسارة، والتعادلات أقل شيوعًا. يمكنك اللعب بمفردك – ضد الكمبيوتر – أو مع صديق. والشيء الأكثر غرابة هنا هو أنه للفوز، يمكنك إنشاء مزيج من ثلاث كرات من اللون الخاص بك (أسود أو أبيض) ليس فقط على مستوى واحد، ولكن أيضًا على طول مستوى الجدران وحتى قطريًا عبر الحقل بأكمله ( الشكل 1.1).

أرز. 1.1

من بين مجموعة واسعة من الألعاب حول موضوع مماثل، يمكننا تسليط الضوء في كل عمل على التنفيذ الفريد للخطة. كل مشروع يختلف عن الآخرين في فرديته.

1.3 الأساس النظري للتنمية

تحليل

لكل طرف خوارزميات معروفة تضمن التعادل في مباراة أي خصم، وإذا أخطأ خصمه تسمح له بالفوز. لذا فإن اللعبة في حالة "لا أحد يموت"<#"877528.files/image002.gif">

الشكل 1.2. شجرة مواقف اللعبة

تظهر شجرة جزئية لمواقف اللعبة في الشكل 1.2 للعبة tic-tac-toe. شجرة من مواقف اللعبة للعبة tic-tac-toe، حيث يذهب لاعب "العرضيات" أولاً ويتصرف وفقًا للخوارزمية المذكورة أعلاه، ويمكن للاعب "أصابع القدم" أن يفعل ما يريد (وقمة واحدة هي يُعطى للفعل العقلاني وغير العقلاني، أي أي شيء آخر)، ويتكون من 50 عقدة.

1.4 اختيار أدوات التطوير

لتحقيق أهدافنا، نحن بحاجة إلى بيئة تطوير تطبيقات متكاملة. ولذلك، تم تنفيذ تطوير المشروع في بيئة البرمجة Microsoft Visual Studio 2008.

Microsoft Visual Studio هو خط من منتجات Microsoft ، بما في ذلك بيئة التطوير المتكاملة البرمجيات وعدد من الأدوات الأخرى. تتيح لك هذه المنتجات التطوير على أساس وحدة التحكم التطبيقات وتطبيقات واجهة المستخدم الرسومية ، بما في ذلك دعم تقنية Windows Forms ، وكذلك المواقع الإلكترونية ، خدمات الويب كما هو الحال في مواطن ، والسيطرة عليها رموز لجميع الأنظمة الأساسية التي يدعمها Windows ،ويندوز موبايل ،ويندوز سي , .الإطار الصافي اكس بوكس , هاتف ويندوز .NET الإطار المضغوط و سيلفرلايت .

2. جزء التصميم من التطوير

2.1 تطوير واجهة المستخدم

عند إنشاء تطبيق ألعاب، من الضروري مراعاة أحد المكونات الرئيسية لنجاح المنتج - الواجهة. يجب أن تكون واجهة المستخدم الخاصة بالبرنامج، أولاً وقبل كل شيء، مفهومة وجذابة للمستخدم. عليك أن تحاول إزالة كل اللحظات التي من شأنها أن تشتت انتباه المستخدم أو تسبب له الانزعاج. يمكن تقسيم واجهة البرنامج بأكملها إلى مكونين.

) القائمة الرئيسية للبرنامج

أرز. 2.1 - القائمة الرئيسية للبرنامج

تم تصميم القائمة الرئيسية للسماح للمستخدم بالانضمام إلى أجواء الألعاب، لذلك تم تصميم الواجهة بألوان ملونة ومرحة. من خلال القائمة يمكنك الذهاب إلى الملعب، عرض قواعد اللعبة، أو الخروج من اللعبة.

) الملعب

الشكل 2.2 - الملعب

تحتوي ساحة اللعب على المنطقة المباشرة للعب، حيث يقوم اللاعب والكمبيوتر بوضع أيقوناتهما. قبل بدء اللعبة، يجب على المستخدم تحديد نوع اللعبة مثل "X vs 0" أو "المستوى الأول مع الكمبيوتر" أو "المستوى الثاني مع الكمبيوتر"، وإلا سيعطي البرنامج رسالة حول ما يجب فعله. زر يساعد اللاعب على العودة إلى القائمة الرئيسية. في النهاية، ستظهر نوافذ إضافية لإعلام المشارك بنتائج المباراة.

أرز. 2.3 - نوافذ نتائج اللعبة الإضافية

2.2 تطوير هياكل البيانات (في الخارجية وذاكرة الوصول العشوائي)

يتم استخدام ذاكرة الوصول العشوائي (RAM) لمصفوفة أحادية البعد تتكون من 9 عناصر تقوم بتخزين حالات الملعب، حيث تتوافق كل خلية من المصفوفة مع خلية في الملعب. يتم إنفاق الذاكرة أيضًا على المتغيرات الثابتة: رقم المستوى، ترتيب الدور.

يتطلب تشغيله 803 كيلو بايت من الذاكرة الحرة.

.3 تطوير وتحليل الخوارزميات

لتنفيذ خوارزمية التفكير الخاصة باللعبة، تحتاج إلى تعيين مصفوفة ثابتة من نوع gcnew (9)؛ حيث سيتم تخزين حالات الملعب، حيث تتوافق كل خلية من المصفوفة مع خلية. "0" - يتوافق مع خلية فارغة، إذا انتقل لاعب إلى الخلية، أي "X"، يتم تسجيل القيمة "1" وإذا قام الكمبيوتر بنقلة، أي "O"، يتم تسجيل القيمة "2". في البداية، جميع عناصر المصفوفة تساوي "0". من الضروري تعيين المستوى المتغير الثابت الذي يقوم بتخزين بيانات المستوى. هناك 3 مستويات إجمالاً في هذه اللعبة: يأخذ المستوى القيمة "1" إذا كان المستخدم قد اختار نوع اللعبة "X vs O"، والقيمة "2" إذا كان "المستوى الأول مع جهاز كمبيوتر"، والقيمة "3" " إذا كان "المستوى الثاني مع الكمبيوتر" " يقوم متغير اللاعب بتخزين ترتيب الدور ("صحيح" هو دور اللاعب، و"خطأ" هو دور الكمبيوتر). نظرًا لأن حق القيام بالخطوة الأولى يُمنح للمستخدم، في بداية اللعبة، فإن اللاعب = صحيح. يقوم المتغير الثابت للعلم بتخزين معلومات حول ما إذا كانت هناك خلايا فارغة في الملعب أم لا: إذا كانت العلامة = صحيح - أي خطأ - فلا توجد خلايا فارغة. يجب أن تحتوي خوارزمية التحقق على تكرار لمعلمات المصفوفة x وطرح الحل الخاص بها، والذي سيكون الأمثل لمزيد من اللعب. يتميز هذا البرنامج بمستويين من اللعب بالكمبيوتر. في المستوى 1، مهمة الكمبيوتر ليست التغلب على الخصم. لهذا هذه الوظيفةتقوم بإرجاع قيمة عشوائية للخلية التي سينتقل إليها الكمبيوتر. يتم عرض رمز هذه الخوارزمية في [الملحق 1]. يوضح الشكل 2.4 المخطط التفصيلي لتنفيذ الكود.

الحركة الأكثر ربحًا في بداية اللعبة هي الانتقال إلى وسط الملعب. في الدالة dif_level()، يتم التحقق من الشرط في البداية: إذا لم يذهب اللاعب إلى الحقل المركزي، فسيذهب الكمبيوتر إلى هناك. خلاف ذلك، إذا ذهب اللاعب إلى المركز، فسيتم استدعاء وظيفة الاختيار (2) للتحقق من مجموعة الكمبيوتر، وإذا كانت هناك فرصة للفوز، فقم بإرجاع رقم الخلية. إذا لم يتمكن الكمبيوتر من الفوز في الخطوة التالية، فسيتم استدعاء وظيفة الفحص (1): التحقق من مجموعة اللاعب. رقم الخلية التي كان من الممكن أن يفوز فيها اللاعب إذا تم إرجاع رهانه. إذا لم يكن هناك مثل هذه المجموعة، فسيتم استدعاء الدالة low_level().

الشكل 2.4. - مخطط الكتلة

الشكل 2.5. - مخطط الكتلة

3. تنفيذ البرنامج بلغة C++

.1 بنية البرنامج

ينفذ هذا البرنامج ثلاثة أشكال: القائمة الرئيسية (الشكل 2.1)، وساحة اللعب (الشكل 2.2)، وحقل المساعدة (قواعد اللعبة)؛ 12 لوحة، 9 منها رئيسية. أيضًا، في نهاية اللعبة، يظهر صندوق صور مع النتيجة، وهناك 5 صور في المجموع (الشكل 2.3).

يمكنك استخدام معالجات النقر على اللوحة كأساس، والتي يوجد منها 9 بالضبط في الملعب. يستدعي كل معالج عدة وظائف. في البداية هناك شرط، إذا اختار المستخدم نوع اللعبة "X مقابل 0"، فسيتم ملء الخلايا ببساطة بالقيم 1 أو 2 (تقاطع أو صفر). بعد ذلك تأتي الوظائف: إشارة التقدم (CrossZero())، والتي تغير التقاطع إلى الصفر والعكس صحيح، وحظر الخلايا المشغولة checkArray()، والعثور على الفائز الفائز(). تأخذ وظيفة الفائز () في الاعتبار جميع خيارات الفوز الممكنة، لذلك إذا قام أحد اللاعبين بصف 3 من قطعه (عرضية أو صفر) عموديًا أو أفقيًا أو قطريًا، فسوف يفوز. بخلاف ذلك، إذا كان الحقل ممتلئًا، ولكن لم يصطف أي من اللاعبين، فسيتم استدعاء وظيفة التحقق من التعادل (_friend())، والتي تتحقق مما إذا كانت هناك خلايا حرة متبقية في الملعب أم لا. إذا كانت fr = true، فلا توجد خلايا حرة في الحقل. إذا تغيرت القيمة، فهذا يعني أن هناك خلية حرة في الحقل.

يعمل الشرط الثاني إذا تم تحديد نوع اللعبة الثاني أو الثالث. ثم تسمى الوظيفة التي تم بها نقل الكمبيوتر: move(int n). ينقل رقم الخلية التي نقر عليها اللاعب. بعد ذلك تأتي الوظائف: مؤشر التقدم (CrossZero())، وحظر الخلايا المشغولة checkArray(). ثم يتم استدعاء وظيفة الفائز () التي تتحقق مما إذا كان اللاعب قد فاز بهذه النقلة أم لا. إذا لم يكن الأمر كذلك، فسيتم التحقق من وجود الخلايا الحرة. إذا كانت هناك خلايا حرة، فإن الكمبيوتر يتحرك. بعد ذلك، اعتمادًا على المستوى الذي اختاره اللاعب "1" أو "2"، يتم استدعاء الوظائف التالية: low_level(), dif_level(). تحدد الدالة low_level() مكان وضع الصفر بشكل عشوائي، وتقدم الدالة dif_level() خوارزمية خاصة ليفوز الكمبيوتر. بعد ذلك تأتي الوظائف: مؤشر التقدم (CrossZero())، وحظر الخلايا المشغولة checkArray(). ثم يتم استدعاء وظيفة الفائز () التي تتحقق مما إذا كان الكمبيوتر قد فاز بهذه الخطوة أم لا. إذا لم يكن الأمر كذلك، فسيتم التحقق من وجود الخلايا الحرة. إذا كانت هناك خلايا حرة، فإن اللاعب يتحرك.

.2 اختيار المكونات القياسية المرئية وغير المرئية

ولتنفيذ هذا العمل، تم اختيار المكونات التالية:

1) النموذج 1، مع المعلمات المعطاةالنص = تيك تاك تو، ControlBox = خطأ

2) f2، مع المعلمات المحددة BackColor، Text=Game

) comboBox1 مع معلمات العناصر المحددة:

× مقابل 0

المستوى الأول مع الكمبيوتر

المستوى الثاني مع الكمبيوتر

4) لوحة، مع معلمات BackColor المحددة، وقيم مختلفة للمعلمات المرئية والممكّنة. بالنسبة لبعض اللوحات، تمت كتابة أحداث مثل Click.

5) زر، مع المعلمات المحددة الخط، اللون الأمامي، اللون الخلفي، النص، لجميع الأزرار تمت كتابة أحداث مثل Click.

6) التسمية، مع المعلمات المحددة BackColor، الخط، اللون الأمامي، النص.

) PictureBox، مع المعلمات المحددة Image، SizeMode = StretchImage.

) textBox، مع المعلمات المحددة BackColor، Font، Fore Color، Text=” “.

4. نتائج الاختبار

لنختبر البرنامج من خلال تجربة 3 أنواع من الألعاب.

لنجرب إجراءات أزرار القائمة الرئيسية. الأزرار تعمل بشكل صحيح. دعونا نحاول بدء اللعبة دون اختيار نوع اللعبة. يعرض البرنامج رسالة خطأ ويطلب منك تحديد نوع اللعبة (الشكل 4.1)

الشكل 4.1.

دعنا نختار نوعًا واحدًا من اللعبة - "X مقابل 0"، أي. المستخدم مقابل المستخدم. في هذه المرحلة من اللعبة، يمكن للمستخدم أيضًا اللعب مع نفسه. (الشكل 4.2)

الشكل 4.2.

أثناء لعبة "المستوى 1 مع الكمبيوتر"، لا يحدد الكمبيوتر لنفسه هدف الفوز بالمشارك. هو فقط يضع الأصفار أماكن مجانيةمجالات. في هذه المرحلة، يمكن للمستخدم بسهولة التغلب على الكمبيوتر. على الرغم من وجود خيارات أخرى لتطوير الأحداث على هذا المستوى.

الشكل 4.3.

نوع اللعبة: "المستوى 2 مع الكمبيوتر". في هذه المرحلة، تقوم اللعبة بتحليل جميع الحركات وتحاول اختيار الحركة الأمثل. هنا أيضًا جميع السيناريوهات الثلاثة ممكنة، لأن يقوم الكمبيوتر بأول خطوة له إلى أي خلية حرة. في أغلب الأحيان تنتهي اللعبة بالتعادل.

الشكل 4.4.

يعمل البرنامج بنجاح على جميع المتغيرات التجريبية، دون أخطاء.

خاتمة

يمكننا أن نقول بثقة أن المهمة المحددة في بداية العمل قد اكتملت. أثناء التطوير، تم تخطيط وتطوير مشروع ريمكس للعبة الشهيرة "Tic Tac Toe". اللعبة تلبي المتطلبات المحددة وتؤدي وظائفها. نفذت في العمل أنواع مختلفةالألعاب ومستويات الصعوبة.

أثناء العمل، تم إتقان أساليب البرمجة الجديدة في بيئة تطوير متكاملة. تم دمج المعرفة القديمة حول العمل بلغة C++. استعدادًا للدورة التدريبية، تم تحليل الأساليب والخوارزميات المختلفة لتنفيذ هذه اللعبة.

على الرغم من البساطة الواضحة لهذا البرنامج، إلا أنه محفوف بعدد من الصعوبات التي يتم تنفيذها باستخدام جميع التقنيات الأساسية لبرنامج Visual C++.

مميزات هذا البرنامج هي:

خوارزمية مبنية بشكل واضح؛

واجهة بديهية؛

سهل الاستخدام؛

دليل مستخدم واضح تمامًا؛

لا إضافات غير ضرورية.

فهرس

1. http://www.pravilaigr.ru/xo.php

2. http://2igroka.com/stuff/sportivnye/krestiki_noliki_3d/15-1-0-14

3. https://www.draw.io/

http://pol-video.ru/QPW9QHEO2GU/uroki_s_krestiki-noliki_ch1.html

المرفق 1

خاص: int low_level())(// إجراء للخصم الخفيف;::Random^ rand = gcnew System::Random();(= rand->Next(0,8);

) while (x[r] != 0);r;

الملحق 2

خاص: bool check(int n)(k = -1;// يتحقق من جميع المجموعات ويعيد الحركة الصحيحة(x == n) (((x == n)&&(x == 0)) k =2; ((x == n)&&(x == 0)) k =1;((x == n)&&(x == 0)) k =6;((x == n)&&(x == 0)) ك =3;((x == n)&&(x == 0)) k =8;((x == n)&&(x == 0)) k =4;

)(x == n) (((x == n)&&(x == 0)) k =0;((x == n)&&(x == 0)) k =7;((x = = ن)&&(x == 0)) k =4;

)(x == n) (((x == n)&&(x == 0)) k =4;((x == n)&&(x == 0)) k =6;((x = = n)&&(x == 0)) k =8;((x == n)&&(x == 0)) k =5;

)(x == n) (((x == n)&&(x == 0)) k =0;((x == n)&&(x == 0)) k =5;((x = = ن)&&(x == 0)) k =4;

)(x == n) (((x == n)&&(x == 0)) k =0;((x == n)&&(x == 0)) k =3;((x = = n)&&(x == 0)) k =1;((x == n)&&(x == 0)) k =2;

)(x == n) (((x == n)&&(x == 0)) k =2;

)(x == n) (((x == n)&&(x == 0)) k =8;((x == n)&&(x == 0)) k =7;

)(x == n) (((x == n)&&(x == 0)) k =6;

)(ك!=-1) إرجاع صحيح؛وإلا قم بإرجاع خطأ؛

الملحق 3

خاص: int dif_level())(// عدو صعب

//return check(2);(x == 0) return (4);(check(2)) return k; آخر (تحقق (1)) العودة ك؛ آخر low_level();

طلب 4

خاص: void CrossZero())(// يغير التقاطع إلى صفر (مؤشر التقدم)(لاعب) (->Visible = true;->Visible = false;

) else (->Visible = true;->Visible = false;

): void checkArray())(// وظيفة التحقق مما إذا كان هناك شيء ما في الخلية، إذا كان هناك شيء ما، فلا يمكنك النقر فوق هذه الخلية بعد الآن. (x == 1) (panel1->BackgroundImage = Panel11->BackgroundImage ;panel1- >Enabled = false;)(x == 2) (panel1->BackgroundImage = Panel10->BackgroundImage;panel1->Enabled = false;)(x == 1) (panel2->BackgroundImage = Panel11->BackgroundImage ;panel2- >Enabled = false;)(x == 2) (panel2->BackgroundImage = Panel10->BackgroundImage;panel2->Enabled = false;)(x == 1) (panel3->BackgroundImage = Panel11->BackgroundImage ;panel3- >Enabled = false;)(x == 2) (panel3->BackgroundImage = Panel10->BackgroundImage;panel3->Enabled = false;)(x == 1) (panel4->BackgroundImage = Panel11->BackgroundImage ;panel4- >Enabled = false;)(x == 2) (panel4->BackgroundImage = Panel10->BackgroundImage;panel4->Enabled = false;)(x == 1) (panel5->BackgroundImage = Panel11->BackgroundImage ;panel5- >Enabled = false;)(x == 2) (panel5->BackgroundImage = Panel10->BackgroundImage;panel5->Enabled = false;)(x == 1) (panel6->BackgroundImage = Panel11->BackgroundImage ;panel6- >Enabled = false;)(x == 2) (panel6->BackgroundImage = Panel10->BackgroundImage;panel6->Enabled = false;)(x == 1) (panel7->BackgroundImage = Panel11->BackgroundImage ;panel7- >Enabled = false;)(x == 2) (panel7->BackgroundImage = Panel10->BackgroundImage;panel7->Enabled = false;)(x == 1) (panel8->BackgroundImage = Panel11->BackgroundImage ;panel8- >Enabled = false;)(x == 2) (panel8->BackgroundImage = Panel10->BackgroundImage;panel8->Enabled = false;)(x == 1) (panel9->BackgroundImage = Panel11->BackgroundImage ;panel9- >Enabled = false;)(x == 2) (panel9->BackgroundImage = Panel10->BackgroundImage;panel9->Enabled = false;)

): bool الفائز ())(// التحقق من الفائز وحظر جميع الخلايا المتبقية.

// علامة منطقية = خطأ؛(((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x = = 2)) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2) )) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2)) || ((x == x)&&(x == x)&&(x == 2)))( (lvl==1) ( photoPo->Visible = true;)(picturePr->Visible = true;)->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;-> Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;true;

)(((x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x x == x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)) || ((x = = x)&&(x == x)&&(x == 1)) || ((x == x)&&(x == x)&&(x == 1)))((lvl==1) (picturePx->Visible = true;)(picturePobeda->Visible = true;)->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;-> Enabled = false;->Enabled = false;->Enabled = false;->Enabled = false;true;

): void _friend())(fr = true;(int i = 0; i< 9; i++) if (x[i] == 0) {fr = false; break;}(fr) { pictureN->مرئي = صحيح؛)

): حركة باطلة (int n)(// وظيفة نقل الكمبيوتر = false;[n] = 1;= !player;();();(winner()) () ((int i = 0; i< 9; i++) if (x[i] == 0) flag = true;(flag){(lvl == 2) = 2; = 2;= !player;();();();

): System::Void Button1_Click(System::Object^ sender, System::EventArgs^ e) (// لعبة جديدة>Visible = false;>Visible = false;>Visible = false; >Visible = false; >Visible = false; = comboBox1->Text;(typeGame == "")(::Show("اختر نوع لعبتك أولاً!");

) else ((typeGame == "X vs 0") lvl = 1;(typeGame == "المستوى الأول مع كمبيوتر") lvl = 2;(typeGame == "المستوى الثاني مع الكمبيوتر") lvl = 3;( ); = صحيح;(int i = 0; i< 9; i++) x[i] = 0;->صورة الخلفية = لوحة 12-> صورة الخلفية؛ -> صورة الخلفية = لوحة 12 -> صورة الخلفية؛ -> صورة الخلفية = لوحة 12 -> صورة الخلفية؛ -> صورة الخلفية = لوحة 12 -> صورة الخلفية؛ -> صورة الخلفية = لوحة 12 -> صورة الخلفية؛ -> صورة الخلفية = لوحة 12 -> صورة الخلفية؛->صورة الخلفية = لوحة 12->صورة الخلفية؛->صورة الخلفية = لوحة 12->صورة الخلفية؛->صورة الخلفية = لوحة 12->صورة الخلفية؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛->ممكّن = صحيح؛

): System::Void Panel1_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 0;(lvl == 1)((player)( = 1;

)= !player;();();();

): System::Void Panel2_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 1;(lvl == 1)((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel3_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 2;(lvl == 1)((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel4_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 3;(lvl == 1)((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel5_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 4;(lvl == 1)((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel6_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 5;(lvl == 1) ((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel7_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 6;(lvl == 1) ((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel8_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 7;(lvl == 1) ((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Panel9_MouseClick(System::Object^ sender, System::Windows::Forms::MouseEventArgs^ e) (n = 8;(lvl == 1) ((player)( = 1;

)= !player;();();();

) وإلا إذا ((lvl == 2)||(lvl == 3))((n);

): System::Void Button2_Click(System::Object^ sender, System::EventArgs^ e) (();

): System::Void photoPx_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void photoPo_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void photoPobeda_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void photoPr_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

): System::Void photoN_Click(System::Object^ sender, System::EventArgs^ e) (>Visible = false;

انتباه! هذه نسخة تمهيدية من الدرس، وقد تكون موادها غير مكتملة.

قم بالدخول إلى الموقع كطالب

قم بتسجيل الدخول كطالب للوصول إلى المواد المدرسية

إنشاء تكوينات 1C: كتابة الجزء "Tic Tac Toe" 1/3

سوف نتعلم من خلال اللعب، وبالتالي سيكون مشروعنا الأول هو الإبداع للجميع
لعبة مألوفة منذ الطفولة - "تيك تاك تو".

قد تتساءل، ما علاقة الألعاب بـ 1C والمحاسبة والتداول؟ تقريبا لا شيء. لكن علينا أن نبدأ تدريجياً وبمرور الوقت سنصل إلى أتمتة المستودعات. في الوقت الحالي، لنبدأ صغيرًا.

قبل أن نبدأ في برمجة لعبة تيك تاك تو، دعونا نفكر في الأمر.

نحن نعلم بالفعل أن النموذج يحتوي على عناصر، أحدها هو الزر. الأزرار قادرة على تنفيذ الأوامر، وفي الوقت نفسه، لها خصائص تسمح لك بالتحكم في عرضها في النموذج (على سبيل المثال، العنوان).

على سبيل المثال، يمكنك استخدام زر لإنشاء حقل يحتوي على تسع مناطق نشطة (تلك الخلايا التي ننقر عليها ونسجل الإجراء، مع عرض النقوش في نفس الوقت على شكل "O" و"X"). الزر أكثر من مناسب لهذا الغرض.

ماذا نحتاج؟ من الواضح أننا سنحتاج إلى تذكر حركتنا وتذكر حركة الكمبيوتر. سنحتاج أيضًا إلى تغيير عناوين الأزرار: عندما ننقر، يكون عنوان الزر دائمًا "O"، وعندما يتحرك الكمبيوتر، يكون "X".

أولاً، سنحتاج إلى إنشاء قاعدة بيانات جديدة حيث سننشئ لعبتنا. هيا بنا نقوم بذلك.

الخطوة رقم 1: إنشاء قاعدة بيانات فارغة

لنقم بإنشاء قاعدة بيانات Tic-Tac-Toe فارغة.

تعليمات مفصلة

هيا نطلقاختصار 1C لفتح قائمة قواعد المعلومات المتوفرة على جهاز الكمبيوتر. أنت تقرأ نسخة تجريبية من الدرس، الدروس الكاملة متوفرة. نحن بحاجة إلى الخلق قاعدة جديدة، لذا اضغط على الزر " يضيف":

سيتم فتح نافذة الإضافة قاعدة المعلومات، حيث تحتاج إلى تحديد العنصر الأول " إنشاء قاعدة معلومات" وانقر على زر "التالي":

في النافذة التالية، حدد العنصر الثاني " إنشاء قاعدة معلومات بدون تكوين لتطوير تكوين جديد..." وانقر على زر "التالي" مرة أخرى:

في النافذة التالية، يطلب منا إدخال اسم قاعدة البيانات الجديدة، والتي سيتم عرضها ضمن قائمة قواعد البيانات. دعونا ندخل " تيك تاك تو" وانقر على زر "التالي":

في النافذة التالية، تحتاج إلى تحديد المسار إلى المجلد الفارغ الذي سيتم تخزين قاعدة بياناتنا فيه. في هذه الحالة، قمت بإنشاء المجلد " تيك تاك تو" في مجلد "قواعد بيانات 1C" على محرك الأقراص D:

في النافذة التالية، اترك جميع الإعدادات كإعداد افتراضي وانقر فوق " مستعد":

وبعد توقف قصير، تم إنشاء قاعدة البيانات وإضافتها إلى القائمة. هناك طريقتان رئيسيتان للعمل مع قاعدة البيانات: 1ج: المؤسسةو مكون:

في وضع التكوين، نقوم بتكوين قاعدة البيانات وبرمجتها، وفي وضع 1C:Enterprise نرى ما سيأتي منه.

الخطوة رقم 2: افتح المكوّن

دعونا نضغط على الزر " مكون"للدخول إلى وضع المكوّن:

الخطوة رقم 3: افتح شجرة التكوين

تنفيذ أمر القائمة " إعدادات"->"فتح التكوين":

تم فتح شجرة التكوين أمامنا، والتي تحتوي على أقسام التكوين المختلفة. نظرًا لأننا لم نقم بإنشاء أي شيء بعد، فهذه الأقسام فارغة:

الخطوة رقم 4: إضافة المعالجة

لوضع منطق لعبتنا، سوف نستخدم قسم "المعالجة". دعونا انقر انقر على اليمينعلى القسم " العلاجات" وحدد الأمر "إضافة":

لقد فتحت أمامنا نافذة لإنشاء معالجة جديدة. دعنا ندخل الاسم " تيك تاك تو". سيتم إدراج المرادف من تلقاء نفسه. وهذا يكفي لحفظ معالجتنا (التي لا تزال فارغة) في قاعدة البيانات. انقر فوق الزر "إغلاق":

الخطوة رقم 5: التصحيح الأول للبرنامج

يمكنك التحقق مما حدث من وضع المستخدم ( 1ج: المؤسسة). للوصول إليه مباشرة من المكوّن، قم بتنفيذ أمر القائمة " تصحيح الأخطاء"->"ابدأ التصحيح":

وبما أننا أجرينا تغييرًا على قاعدة البيانات، فسيتم سؤالنا عما إذا كنا نوافق على قبول هذا التغيير. سيتم طرح هذا السؤال علينا باستمرار أثناء عملية التطوير. نحن نتفق (زر " نعم"):

بدأت قاعدة البيانات في وضع "1C:Enterprise". أنت تقرأ نسخة تجريبية من الدرس، الدروس الكاملة متوفرة. ولكن كما نرى، فإن العمل معها لا يزال صعبا - ببساطة لا يوجد شيء للاختيار من بينها. إنه أمر غريب، لأننا أنشأنا بالفعل المعالجة، ومن الناحية النظرية، يجب أن تظهر على اللوحة الصفراء.




قمة