যেমন যদি এটা যুক্তরাষ্ট্র এবং ফাংশন, যেখানে একটি ফাংশন একটি সিরিজ গঠিত হয় আপনি আপনার সিস্টেম দেখতে পারেন f[j]
ইনপুট দিয়ে x[j]
সিস্টেম রাষ্ট্র পরিবর্তন s[j]
দশায় s[j+1]
, তাই মত:
s[j+1] = f[j](s[j], x[j])
একটি রাষ্ট্র আপনার সমগ্র বিশ্বের ব্যাখ্যা। প্লেয়ারের অবস্থানগুলি, শত্রুর অবস্থান, স্কোর, অবশিষ্ট গোলাবারুদ ইত্যাদি আপনার গেমের ফ্রেম আঁকতে আপনার প্রয়োজনীয় সমস্ত কিছুই।
একটি ফাংশন এমন কিছু যা বিশ্বকে প্রভাবিত করতে পারে। একটি ফ্রেম পরিবর্তন, একটি কিপ্রেস, একটি নেটওয়ার্ক প্যাকেট।
ইনপুটটি ফাংশনটি গ্রহণ করে এমন ডেটা। একটি ফ্রেম পরিবর্তন হতে শেষ ফ্রেমটি কেটে যাওয়ার পরে সময় লাগতে পারে, কী চাপলে চেপে থাকা আসল কীটি পাশাপাশি শিফট কী টিপেছিল কিনা তা অন্তর্ভুক্ত থাকতে পারে।
এই ব্যাখ্যাটির জন্য, আমি নিম্নলিখিত অনুমানগুলি করব:
অনুমান 1:
গেমের প্রদত্ত রানের জন্য রাজ্যের পরিমাণ ফাংশনের পরিমাণের চেয়ে অনেক বড়। আপনার সম্ভবত কয়েক হাজার রাজ্য রয়েছে, তবে কেবল কয়েক ডজন ফাংশন (ফ্রেম পরিবর্তন, কীপ্রেস, নেটওয়ার্ক প্যাকেট ইত্যাদি)। অবশ্যই, ইনপুটগুলির পরিমাণ অবশ্যই রাজ্য বিয়োগের পরিমাণের সমান হতে হবে।
অনুমান 2:
একটি একক রাষ্ট্রের সঞ্চয় করার স্পেসিয়াল ব্যয় (মেমরি, ডিস্ক) কোনও ফাংশন এবং এর ইনপুট সংরক্ষণ করার চেয়ে অনেক বেশি।
অনুমান 3:
একটি রাজ্য উপস্থাপনের অস্থায়ী ব্যয় (সময়) একই, বা একটি রাজ্যের উপর কোনও ফাংশন গণনার চেয়ে মাত্রার মাত্র এক বা দুটি অর্ডারের বেশি।
আপনার রিপ্লে সিস্টেমের প্রয়োজনীয়তার উপর নির্ভর করে রিপ্লে সিস্টেম প্রয়োগের বিভিন্ন উপায় রয়েছে, তাই আমরা সহজতমটি দিয়ে শুরু করতে পারি। আমি দাবার খেলাটি কাগজের টুকরোতে রেকর্ড করে ব্যবহার করে একটি ছোট উদাহরণ তৈরি করব।
পদ্ধতি 1:
স্টোর s[0]...s[n]
। এটি খুব সহজ, খুব সোজা। অনুমান 2 এর কারণে এর স্পেসিয়াল ব্যয় বেশ বেশি।
দাবা জন্য, এটি প্রতিটি পদক্ষেপের জন্য পুরো বোর্ড অঙ্কন করে সম্পন্ন হবে।
পদ্ধতি 2:
আপনার যদি কেবল ফরওয়ার্ড রিপ্লে দরকার হয় তবে আপনি কেবল সঞ্চয় করতে পারেন s[0]
এবং তারপরে সংরক্ষণ করতে পারেন f[0]...f[n-1]
(মনে রাখবেন, এটি কেবল ফাংশনটির আইডির নাম) এবং x[0]...x[n-1]
(এই ফাংশনের প্রতিটিটির জন্য কী ইনপুট ছিল)। পুনরায় খেলতে, আপনি কেবল শুরু করে s[0]
গণনা করুন
s[1] = f[0](s[0], x[0])
s[2] = f[1](s[1], x[1])
এবং তাই ...
আমি এখানে একটি ছোট মন্তব্য করতে চাই। আরও বেশ কয়েকজন মন্তব্যকারী বলেছেন যে গেমটি "অবশ্যই সংঘবদ্ধ" " যে কেউ বলে যে কম্পিউটার বিজ্ঞান 101 আবার নেওয়া দরকার, কারণ আপনার গেমটি কোয়ান্টাম কম্পিউটারগুলিতে চালিত না হওয়া অবধি সমস্ত কম্পিউটার প্রোগ্রামগুলি বিশদ বিশিষ্ট ¹ কম্পিউটারকে এত দুর্দান্ত করে তোলে।
তবে আপনার প্রোগ্রামটি সম্ভবত বাহ্যিক প্রোগ্রামগুলির উপর নির্ভর করে, গ্রন্থাগারগুলি থেকে শুরু করে সিপিইউর প্রকৃত বাস্তবায়ন পর্যন্ত, আপনার ফাংশনগুলি প্ল্যাটফর্মগুলির মধ্যে একইরকম আচরণ করে তা নিশ্চিত করে তোলা বেশ কঠিন হতে পারে।
আপনি যদি সিউডো-এলোমেলো নম্বর ব্যবহার করেন তবে আপনি উত্পাদিত সংখ্যাগুলি আপনার x
ইনপুটটির অংশ হিসাবে সংরক্ষণ করতে পারেন , বা প্রিং ফাংশনটির রাজ্যটিকে আপনার রাজ্যের s
অংশ হিসাবে এবং এর প্রয়োগের ক্রিয়াকলাপ হিসাবে সংরক্ষণ করতে পারেন f
।
দাবা জন্য, এটি প্রাথমিক বোর্ড অঙ্কন করে সম্পন্ন হবে (যা জানা যায়) এবং তারপরে প্রতিটি পদক্ষেপটি বর্ণনা করে কোন টুকরোটি কোথায় গেছে। তারা আসলে এটি এভাবেই করে how
পদ্ধতি 3:
এখন, আপনি সম্ভবত আপনার রিপ্লেতে সন্ধান করতে সক্ষম হতে চান। এটি s[n]
একটি স্বেচ্ছাসেবকের জন্য গণনা করুন n
। পদ্ধতি 2 ব্যবহার করে, আপনি গণনা s[0]...s[n-1]
করার আগে আপনাকে গণনা করতে হবে s[n]
যা অনুমান 2 অনুসারে, বেশ ধীর হতে পারে।
এই বাস্তবায়ন করার জন্য, পদ্ধতি 3 পদ্ধতি 1 এবং 2 একটি সাধারণীকরণ হল: দোকান f[0]...f[n-1]
এবং x[0]...x[n-1]
মাত্র পদ্ধতি 2 মত, কিন্তু এ সঞ্চয় s[j]
, সব জন্য j % Q == 0
একটি ধ্রুবক দেওয়া Q
। সহজ শর্তে, এর অর্থ হ'ল আপনি প্রতিটি Q
রাজ্যের মধ্যে একটিতে বুকমার্ক সঞ্চয় করেন । উদাহরণস্বরূপ, জন্য Q == 100
, আপনি সঞ্চয়s[0], s[100], s[200]...
অর্ডার নিরূপণ করার জন্য s[n]
একটি অবাধ জন্য n
, আপনাকে অবশ্যই প্রথমে লোড পূর্বে সঞ্চিত s[floor(n/Q)]
, এবং তারপর থেকে সব ফাংশন নিরূপণ floor(n/Q)
করতে n
। সর্বাধিক, আপনি Q
ফাংশন গণনা করা হবে। এর ক্ষুদ্রতর মানগুলি Q
গণনা করার জন্য দ্রুত তবে অনেক বেশি স্থান গ্রহণ করে, তবে বৃহত্তর মানগুলি Q
কম স্থান গ্রহণ করে তবে গণনা করতে বেশি সময় নেয়।
পদ্ধতি 3 সহ Q==1
পদ্ধতি 1 এর সমান, অন্যদিকে পদ্ধতি 3 Q==inf
পদ্ধতি 2 এর মতোই।
দাবা জন্য, এটি প্রতিটি পদক্ষেপ অঙ্কন, পাশাপাশি প্রতি 10 বোর্ডের মধ্যে একটি (যেমন Q==10
) দ্বারা সম্পন্ন হবে।
পদ্ধতি 4:
আপনি রিপ্লে বিপরীত চান, আপনি পদ্ধতি 3. একটি ছোট প্রকরণ ধরুন করতে পারেন Q==100
, এবং আপনি গণনা করতে চান s[150]
মাধ্যমে s[90]
বিপরীত। আনমোডাইফাইড পদ্ধতি 3 দিয়ে আপনার 50 টি গণনা করতে হবে s[150]
এবং তারপরে আরও 49 টি গণনা পেতে হবে s[149]
এবং এ জাতীয়। আপনি যেহেতু s[149]
পাওয়ার জন্য ইতিমধ্যে গণনা করেছেন তাই আপনি প্রথমবারের জন্য গণনা s[150]
করার s[100]...s[150]
সময় একটি ক্যাশে তৈরি করতে পারেন s[150]
এবং তারপরে আপনাকে s[149]
এটি প্রদর্শনের দরকার হলে আপনি ইতিমধ্যে ক্যাশে রেখে যেতে পারেন।
আপনার প্রদত্ত যে কোনও s[j]
জন্য কেবল প্রতিবার গণনা করার সময় আপনাকে ক্যাশেটি পুনরায় জেনারেট করতে হবে । এবার, বৃদ্ধির ফলে আরও ছোট আকার হবে (কেবল ক্যাশে হবে) তবে দীর্ঘ সময় (কেবল ক্যাশে পুনরুদ্ধারের জন্য)। রাজ্য এবং ফাংশন গণনা করার জন্য প্রয়োজনীয় আকার এবং সময়গুলি জানা থাকলে এর জন্য একটি অনুকূল মান গণনা করা যেতে পারে।j==(k*Q)-1
k
Q
Q
দাবা জন্য, এটি প্রতিটি পদক্ষেপ অঙ্কন করে সম্পন্ন হবে, পাশাপাশি প্রতি 10 বোর্ডের মধ্যে একটিতে (যেমন Q==10
), তবে এটির জন্য পৃথক কাগজের টুকরো আঁকতে হবে, আপনি গণনা করেছেন এমন 10 টি বোর্ড।
পদ্ধতি 5:
যদি রাজ্যগুলি কেবল অতিরিক্ত পরিমাণে স্থান নেয় বা ফাংশনগুলি খুব বেশি সময় ব্যয় করে তবে আপনি এমন একটি সমাধান তৈরি করতে পারেন যা বাস্তবে প্রয়োগ করে (জাল নয়) বিপরীত পুনরায় খেলানো। এটি করার জন্য, আপনার অবশ্যই প্রতিটি ফাংশনের বিপরীত ফাংশন তৈরি করতে হবে। যাইহোক, এটির জন্য আপনার প্রতিটি ফাংশন একটি ইঞ্জেকশন প্রয়োজন। যদি এটি করণীয় হয় তবে f'
ফাংশনের বিপরীতটি চিহ্নিত করার জন্য f
গণনা s[j-1]
করা তত সহজ
s[j-1] = f'[j-1](s[j], x[j-1])
মনে রাখবেন যে এখানে, ফাংশন এবং ইনপুট উভয়ই j-1
নয় j
। আপনি যদি গণনা করে থাকেন তবে এই একই ফাংশন এবং ইনপুটটি আপনি ব্যবহার করতে পারেন
s[j] = f[j-1](s[j-1], x[j-1])
এই ফাংশনগুলির বিপরীতটি তৈরি করা জটিল অংশ। তবে আপনি সাধারণত পারবেন না, যেহেতু একটি গেমের প্রতিটি ফাংশনের পরে কিছু স্টেটের ডেটা সাধারণত হারিয়ে যায়।
এই পদ্ধতিটি যেমন হয়, গণনা বিপরীত করতে পারে s[j-1]
, তবে কেবল যদি আপনার কাছে থাকে s[j]
। এর অর্থ হ'ল আপনি কেবল পিছন দিকে রিপ্লেটি দেখতে পারবেন, আপনি যে বিন্দুতে পিছনের দিকে পুনরায় খেলতে চান তা থেকে শুরু করে। আপনি যদি একটি স্বেচ্ছাসেবী বিন্দু থেকে পিছনে পুনরায় খেলতে চান তবে আপনাকে অবশ্যই পদ্ধতি 4 এর সাথে এটি মিশ্রিত করতে হবে।
দাবা জন্য, এটি প্রয়োগ করা যাবে না, যেহেতু প্রদত্ত বোর্ড এবং পূর্ববর্তী পদক্ষেপের সাহায্যে আপনি জানতে পারবেন কোন টুকরোটি সরানো হয়েছিল, তবে এটি কোথা থেকে স্থানান্তরিত হয়েছিল not
পদ্ধতি 6:
অবশেষে, আপনি যদি আপনার সমস্ত ফাংশনগুলি ইঞ্জেকশনগুলির গ্যারান্টি দিতে না পারেন তবে আপনি এটি করার জন্য একটি ছোট কৌশল করতে পারেন। প্রতিটি ফাংশন কেবল একটি নতুন, স্টেটের পরিবর্তে ফিরে আসার পরিবর্তে, আপনি এটি ফেলে দেওয়া ডেটাও এটি ফিরিয়ে দিতে পারেন:
s[j+1], r[j] = f[j](s[j], x[j])
কোথায় r[j]
ফেলে দেওয়া ডেটা। এবং তারপরে আপনার বিপরীত ফাংশন তৈরি করুন যাতে তারা ফেলে দেওয়া ডেটা গ্রহণ করে, যেমন:
s[j] = f'[j](s[j+1], x[j], r[j])
এর উপরন্তু f[j]
এবং x[j]
, এছাড়াও আপনি সংরক্ষণ করতে হবে r[j]
প্রতিটি ফাংশন জন্য। আবারও, আপনি যদি সন্ধান করতে সক্ষম হতে চান তবে আপনার অবশ্যই বুকমার্কগুলি সংরক্ষণ করতে হবে, যেমন পদ্ধতি 4। সহ।
দাবা জন্য, এটি পদ্ধতি 2 এর সমান হবে তবে পদ্ধতি 2 এর বিপরীতে যা কেবলমাত্র কোন টুকরোটি কোথায় যায় তা আপনাকে জানাতে হবে, প্রতিটি টুকরোটি কোথা থেকে এসেছে store
বাস্তবায়ন:
যেহেতু এটি একটি নির্দিষ্ট গেমের জন্য, সমস্ত ধরণের রাজ্যের জন্য, সমস্ত ধরণের ফাংশন সহ কাজ করে, আপনি বিভিন্ন ধরণের ধারণা তৈরি করতে পারেন, এটি কার্যকর করা সহজ করে তুলবে। প্রকৃতপক্ষে, আপনি যদি পুরো গেম স্টেটের সাথে 6 পদ্ধতিটি বাস্তবায়ন করেন তবে আপনি কেবল ডেটা পুনরায় খেলতে সক্ষম হবেন না, তবে সময়মতো ফিরে যেতে পারবেন এবং যে কোনও মুহুর্ত থেকে আবার খেলা শুরু করতে পারবেন। এটা দুর্দান্ত ভয়ঙ্কর হবে।
সমস্ত গেমের স্থিতি সংরক্ষণের পরিবর্তে, আপনি কেবলমাত্র একটি ন্যূনতম ন্যূনতম সঞ্চয় করতে পারেন যা আপনাকে প্রদত্ত রাজ্যটি আঁকতে হবে এবং প্রতিটি নির্দিষ্ট পরিমাণে এই ডেটাটিকে সিরিয়ালাইজ করতে হবে। আপনার রাজ্যগুলি এই সিরিয়ালাইজেশন হবে এবং আপনার ইনপুটটি এখন দুটি সিরিয়ালাইজেশনের মধ্যে পার্থক্য করবে। এটি কাজ করার জন্য তাদের কীটি হ'ল বিশ্ব রাষ্ট্রের পাশাপাশি কিছুটা পরিবর্তন হলে সিরিয়ালিয়াল পরিবর্তন করা উচিত। এই পার্থক্যটি সম্পূর্ণ বিপরীতমুখী, সুতরাং বুকমার্কগুলির সাথে পদ্ধতি 5 কার্যকর করা খুব সম্ভব।
আমি কিছু বড় গেমগুলিতে এটি প্রয়োগ করে দেখেছি, বেশিরভাগ সাম্প্রতিক ডেটা তাত্ক্ষণিকভাবে পুনরায় প্লে করার জন্য যখন কোনও ইভেন্ট (fps এ টুকরো টুকরো টুকরো টুকরো টুকরো স্পোর্টস গেমসে একটি স্কোর) ঘটে থাকে।
আমি আশা করি এই ব্যাখ্যা খুব বিরক্তিকর ছিল না।
¹ এর অর্থ এই নয় যে কিছু প্রোগ্রামগুলি অ-নিরস্তক (যেমন এমএস উইন্ডোজ as) এর মতো কাজ করে। এখন গুরুত্ব সহকারে, আপনি যদি একটি ডিটারিস্টিনিস্টিক কম্পিউটারে একটি অ-সংজ্ঞাবিরোধী প্রোগ্রাম করতে পারেন তবে আপনি নিশ্চিতভাবে নিশ্চিত হতে পারেন যে আপনি একই সাথে ফিল্ডস মেডেল, ট্যুরিং অ্যাওয়ার্ড এবং সম্ভবত অস্কার এবং গ্র্যামিও এটির জন্য উপযুক্ত all