Menu
CoddyTech
flag Ar iconالعربيةdown icon

نمط الأوامر

جزء من قسم البرمجة كائنية التوجّه في رحلة GDScript على Coddy. الدرس 50 من 65.

يحوّل نمط Command الإجراء إلى كائن. يخزّن الكائن كل ما يلزم لتنفيذ الإجراء، لذا يمكنك الاحتفاظ به في قائمة، أو تنفيذه لاحقًا، أو التراجع عنه.

لكل أمر الطريقتان نفسيهما، وتُعلَن عنهما فئة أب مجرّدة:

# command.gd
@abstract
class_name Command
extends RefCounted

@abstract func execute() -> void
@abstract func undo() -> void

يحتفظ الأمر الملموس بالكائن الذي يعمل عليه، ويُسمى المستقبل، وببيانات الإجراء. المستقبل هنا هو Hero الذي لديه var x := 0:

# move_command.gd
class_name MoveCommand
extends Command

var hero: Hero
var dx: int

func _init(target: Hero, step: int) -> void:
	hero = target
	dx = step

func execute() -> void:
	hero.x += dx

func undo() -> void:
	hero.x -= dx

ينفّذ المستدعي الأوامر ويتذكرها. ولا يحتاج مطلقًا إلى معرفة ما يفعله الأمر:

# command_history.gd
class_name CommandHistory
extends RefCounted

var done: Array[Command] = []

func run(command: Command) -> void:
	command.execute()
	done.append(command)

func undo_last() -> void:
	if done.is_empty():
		return
	var last: Command = done.pop_back()
	last.undo()
# main.gd
var hero := Hero.new()
var history := CommandHistory.new()
history.run(MoveCommand.new(hero, 3))
history.run(MoveCommand.new(hero, 2))
print(hero.x)
history.undo_last()
print(hero.x)
5
3

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

تسير المراجع في اتجاه واحد: تشير الأوامر إلى البطل، ولا يعرف البطل عنها شيئًا. وإذا خزّن البطل أوامره أيضًا، فستُبقي الكائنات بعضها بعضًا حيّةً ولن يُحرَّر أيٌّ منها أبدًا.

challenge icon

التحدي

سهل

يتحرك بطل على شبكة، ويمكن التراجع عن كل حركة. يعرّف Command (command.gd) الدالتين execute() وundo()، ويحتوي Hero (hero.gd) على x وy وposition_text(). اكتب:

  • MoveCommand: يخزّن المُنشئ البطل والخطوتين step_x وstep_y. تضيف execute() الخطوتين إلى x وy الخاصتين بالبطل، وتطرحهما undo().
  • CommandHistory: تنفّذ run(command) الأمر وتخزّنه. تتراجع undo_last() عن أحدث أمر مخزّن، وتزيله، وتُرجع true؛ وإذا لم يكن هناك شيء مخزّن، فتُرجع false.

يقرأ الكود المُعطى عدد الإجراءات التالية، ثم يقرأ إجراءً واحدًا في كل سطر (up أو down أو left أو right أو undo)، ويطبع الموقع بعد كل إجراء. تُنقص up قيمة y بمقدار واحد. بالنسبة إلى right وup وundo وundo وundo، يكون الناتج:

right -> (1, 0)
up -> (1, -1)
undo -> (1, 0)
undo -> (0, 0)
Nothing to undo

ضع الكود في move_command.gd وcommand_history.gd. يحتوي main.gd على كود الإدخال والإخراج المُعطى، ولا يمكن تعديله.

جرّب بنفسك

extends Node

func _ready():
	# كود الإدخال/الإخراج المقدَّم: اتركه كما هو
	var hero := Hero.new()
	var history := CommandHistory.new()
	var steps := {"up": [0, -1], "down": [0, 1], "left": [-1, 0], "right": [1, 0]}
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var action := OS.read_string_from_stdin()
		if action == "undo":
			if history.undo_last():
				print("undo -> ", hero.position_text())
			else:
				print("Nothing to undo")
		else:
			var step: Array = steps[action]
			history.run(MoveCommand.new(hero, step[0], step[1]))
			print(action, " -> ", hero.position_text())
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجّه

تدرّب بنفسك: مترجم GDScript عبر الإنترنت