আমি প্রোগ্রামিং শেখানোর বিষয়ে কোনো বিশেষজ্ঞ নই, কিন্তু যখন আমি কোনো বিষয়ে আরও ভালো করতে চাই, তখন আমি এটির সাথে মজা করার উপায় খুঁজে বের করার চেষ্টা করি। উদাহরণস্বরূপ, যখন আমি শেল স্ক্রিপ্টিংয়ে আরও ভাল হতে চেয়েছিলাম, তখন আমি ব্যাশে মাইনসুইপার গেমের একটি সংস্করণ প্রোগ্রামিং করে অনুশীলন করার সিদ্ধান্ত নিয়েছিলাম।
আপনি যদি একজন অভিজ্ঞ ব্যাশ প্রোগ্রামার হন এবং মজা করার সময় আপনার দক্ষতা বাড়াতে চান, তাহলে টার্মিনালে মাইনসুইপারের নিজস্ব সংস্করণ লিখতে অনুসরণ করুন। সম্পূর্ণ উৎস কোড এই GitHub সংগ্রহস্থলে পাওয়া যায়।
প্রস্তুত হচ্ছে
আমি যেকোন কোড লেখা শুরু করার আগে, আমি আমার গেম তৈরি করার জন্য প্রয়োজনীয় উপাদানগুলির রূপরেখা দিয়েছিলাম:
- একটি মাইনফিল্ড প্রিন্ট করুন
- গেমপ্লে লজিক তৈরি করুন
- উপলব্ধ মাইনফিল্ড নির্ধারণ করতে যুক্তি তৈরি করুন
- উপলব্ধ এবং আবিষ্কৃত (নিষ্কৃত) খনির গণনা রাখুন
- এন্ডগেম লজিক তৈরি করুন
একটি মাইনফিল্ড প্রিন্ট করুন
৷মাইনসুইপারে, গেম ওয়ার্ল্ড হল লুকানো কোষগুলির একটি 2D অ্যারে (কলাম এবং সারি)। প্রতিটি কোষে একটি বিস্ফোরক মাইন থাকতে পারে বা নাও থাকতে পারে। প্লেয়ারের উদ্দেশ্য হল এমন কোষগুলিকে প্রকাশ করা যেখানে কোন খনি নেই এবং কখনও খনি প্রকাশ না করা। গেমটির ব্যাশ সংস্করণ একটি 10x10 ম্যাট্রিক্স ব্যবহার করে, যা সহজ ব্যাশ অ্যারে ব্যবহার করে প্রয়োগ করা হয়।
প্রথমত, আমি কিছু র্যান্ডম ভেরিয়েবল বরাদ্দ করি। এই বোর্ডে মাইন স্থাপন করা যেতে পারে যে অবস্থান. অবস্থানের সংখ্যা সীমিত করে, এর উপরে তৈরি করা সহজ হবে। যুক্তিটি আরও ভাল হতে পারে, তবে আমি গেমটিকে সহজ এবং কিছুটা অপরিপক্ক রাখতে চেয়েছিলাম। (আমি মজা করার জন্য এটি লিখেছি, কিন্তু আমি আনন্দের সাথে এটিকে আরও ভাল দেখাতে আপনার অবদানকে স্বাগত জানাব।)
নীচের ভেরিয়েবলগুলি হল কিছু ডিফল্ট ভেরিয়েবল, ফিল্ড প্লেসমেন্টের জন্য এলোমেলোভাবে কল করার জন্য ঘোষণা করা হয়েছে, a-g ভেরিয়েবলের মতো, আমরা আমাদের নিষ্কাশনযোগ্য খনিগুলি গণনা করতে তাদের ব্যবহার করব:
# ভেরিয়েবল
স্কোর=0 # গেমের স্কোর সংরক্ষণ করতে ব্যবহার করা হবে
নিচের # ভেরিয়েবলগুলি এলোমেলোভাবে আমাদের খনি থেকে নিষ্কাশনযোগ্য কোষ/ক্ষেত্রগুলি পেতে ব্যবহার করা হবে।
a="1 10 -10 -1"
b="-1 0 1"
c="0 1"
d="-1 0 1 -2 -3"
e="1 2 20 21 10 0 -10 -20 -23 -2 -1"
f="1 2 3 35 30 20 22 10 0 -10 -20 -25 -30 -35 - 3 -2 -1"
g="1 4 6 9 10 15 20 25 30 -30 -24 -11 -10 -9 -8 -7"
#
# ঘোষণা
ডিক্লেয়ার -একটি রুম # একটি অ্যারে রুম ঘোষণা করুন, এটি আমাদের আমার প্রতিটি সেল/ক্ষেত্রকে প্রতিনিধিত্ব করবে।
এর পরে, আমি কলাম (0-9) এবং সারি (a-j) দিয়ে আমার বোর্ড প্রিন্ট করি, গেমটির মাইনফিল্ড হিসাবে পরিবেশন করার জন্য একটি 10x10 ম্যাট্রিক্স তৈরি করি। (এম> .
এটিকে একটি ফাংশন বলা যাক, লাঙল, আমরা প্রথমে শিরোনামটি মুদ্রণ করি:দুটি ফাঁকা লাইন, কলামের শিরোনাম, এবং খেলার ক্ষেত্রের শীর্ষের রূপরেখার জন্য একটি লাইন:
printf '\n\n'
printf '%s' " a b c d e f g h i j"
printf '\n %s\n' "---- ------------------------"
এরপর, আমি r নামে একটি কাউন্টার ভেরিয়েবল স্থাপন করি , কতগুলি অনুভূমিক সারি জনবহুল হয়েছে তার ট্র্যাক রাখতে। মনে রাখবেন, আমরা একই কাউন্টার ভেরিয়েবল 'r ব্যবহার করব ' পরে গেম কোডে আমাদের অ্যারে সূচক হিসাবে। একটি ব্যাশে এর জন্য লুপ, seq ব্যবহার করে 0 থেকে 9 পর্যন্ত বাড়াতে কমান্ড, আমি একটি সংখ্যা প্রিন্ট করি (d% ) সারি সংখ্যা প্রতিনিধিত্ব করতে ($row, যা seq দ্বারা সংজ্ঞায়িত করা হয় ):
$(seq 0 9) এ সারির জন্যr=0 # আমাদের কাউন্টার
do
printf '%d ' "$row" # 0-9 থেকে সারি সংখ্যাগুলি মুদ্রণ করুন
আমরা এখান থেকে এগিয়ে যাওয়ার আগে, এখন পর্যন্ত আমরা কী করেছি তা পরীক্ষা করা যাক। আমরা [a-j] ক্রম প্রিন্ট করেছি প্রথমে অনুভূমিকভাবে এবং তারপরে আমরা [0-9] পরিসরে সারি সংখ্যা প্রিন্ট করি , আমরা আমাদের ব্যবহারকারীদের ইনপুট স্থানাঙ্ক হিসাবে কাজ করার জন্য এই দুটি ব্যাপ্তি ব্যবহার করব খনিটি নিষ্কাশন করার জন্য।
পরবর্তী, প্রতিটি সারির মধ্যে, একটি কলাম ছেদ আছে, তাই এটি একটি নতুন এর জন্য খোলার সময় লুপ. এটি প্রতিটি কলাম পরিচালনা করে, তাই এটি মূলত খেলার ক্ষেত্রে প্রতিটি ঘর তৈরি করে। আমি কিছু সহায়ক ফাংশন যোগ করেছি যা আপনি উত্স কোডে সম্পূর্ণ সংজ্ঞা দেখতে পারেন। প্রতিটি কক্ষের জন্য, ক্ষেত্রটিকে একটি খনির মতো দেখাতে আমাদের কিছু প্রয়োজন, তাই আমরা একটি কাস্টম ফাংশন ব্যবহার করে একটি ডট (.) দিয়ে খালিগুলিকে শুরু করি is_null_field . এছাড়াও, প্রতিটি কক্ষের মান সংরক্ষণ করার জন্য আমাদের একটি অ্যারে ভেরিয়েবল প্রয়োজন, আমরা পূর্বনির্ধারিত গ্লোবাল অ্যারে ভেরিয়েবল রুম ব্যবহার করব একটি সূচক ভেরিয়েবল r সহ . হিসাবে r ইনক্রিমেন্ট, আমরা কোষের উপর পুনরাবৃত্তি করি, পথে মাইন ফেলে।
$(seq 0 9) এ কলের জন্য; do
((r+=1)) # কলামের ক্রমানুসারে এগিয়ে যাওয়ার সাথে সাথে কাউন্টারটি বৃদ্ধি করুন
is_null_field $r # একটি ফাংশন ধরে নিন যা পরীক্ষা করবে, যদি ক্ষেত্রটি খালি থাকে, যদি তাই হয়, তাহলে এটি দিয়ে আরম্ভ করুন। একটি বিন্দু(.)
printf '%s \e[33m%s\e[0m ' "|" "${room[$r]}" # পরিশেষে বিভাজক প্রিন্ট করুন, মনে রাখবেন যে, ${room[$r]} এর প্রথম মান হবে '.', যেহেতু এটি সবেমাত্র শুরু করা হয়েছে।
#close col লুপ
সম্পন্ন
পরিশেষে, আমি প্রতিটি সারির নীচে একটি লাইন দিয়ে বোর্ডটিকে ভালভাবে সংজ্ঞায়িত করে রাখি, এবং তারপর সারি লুপটি বন্ধ করে দিই:
printf '%s\n' "|" # লাইন শেষ বিভাজক প্রিন্ট করুন
printf ' %s\n' "-------------------------------- ---------"
লুপের জন্য # বন্ধ সারি
সম্পন্ন
printf '\n\n'
সম্পূর্ণ লাঙল ফাংশন এর মত দেখাচ্ছে:
লাঙ()
{
r=0
printf '\n\n'
printf '%s' " a b c d e f g h i j "
printf '\n %s\n' "----------------------------------- -----"
সারির জন্য $(seq 0 9); কর
printf '%d ' "$row"
$(seq 0 9) এ কলের জন্য; করবেন
((r+=1))
is_null_field $r
printf '%s \e[33m%s\e[0m ' "|" "${রুম[$r]}"
সম্পন্ন
printf '%s\n' "|"
printf ' %s\n' "-------------------------------------- ---"
সম্পন্ন
printf '\n\n'
}
is_null_field এর প্রয়োজন সম্পর্কে সিদ্ধান্ত নিতে আমার কিছু সময় লেগেছে , তাই এর এটা কি ঘনিষ্ঠভাবে কটাক্ষপাত করা যাক. খেলার শুরু থেকেই আমাদের একটি নির্ভরযোগ্য অবস্থা দরকার। এই পছন্দটি নির্বিচারে - এটি একটি সংখ্যা বা যেকোনো অক্ষর হতে পারে। আমি সব কিছুকে ডট (.) হিসাবে ঘোষণা করার সিদ্ধান্ত নিয়েছি কারণ আমি বিশ্বাস করি এটি গেমবোর্ডটিকে সুন্দর দেখায়। এটি দেখতে কেমন তা এখানে:
is_null_field()
{
local e=$1 # আমরা ইতিমধ্যেই অ্যারে রুমের জন্য সূচী 'r' ব্যবহার করেছি, আসুন এটিকে 'e' বলি
যদি [[ -z "${room [$e]}" ]];তারপর
রুম[$r]="।" # এখানেই আমরা সেল/মাইনফিল্ড শুরু করার জন্য ডট(.) রাখি
fi
}
এখন যেহেতু, আমার কাছে আমাদের খনিতে সমস্ত সেল শুরু হয়েছে, আমি নীচে দেখানো একটি সাধারণ ফাংশন ঘোষণা করে এবং পরে কল করে সমস্ত উপলব্ধ খনিগুলির একটি গণনা পাই:
get_free_fields()
{
free_fields=0 # ভেরিয়েবল শুরু করুন
for n in $(seq 1 ${#room[@]}); কর
যদি [[ "${রুম[$n]}" ="।" ]]; তারপর # সেলগুলিতে প্রাথমিক মান ডট(.) আছে কিনা তা পরীক্ষা করুন, তারপর এটিকে একটি মুক্ত ক্ষেত্র হিসাবে গণনা করুন।
(free_fields+=1))
fi
সম্পন্ন
}
এখানে মুদ্রিত মাইনফিল্ড, যেখানে [a-j] কলাম, এবং [0-9 ] হল সারি।
প্লেয়ার চালানোর জন্য যুক্তি তৈরি করুন
প্লেয়ার লজিক খনিতে স্থানাঙ্ক হিসাবে stdin থেকে একটি বিকল্প পড়ে এবং মাইনফিল্ডের সঠিক ক্ষেত্রটি বের করে। এটি কলাম এবং সারি ইনপুটগুলি বের করতে ব্যাশের প্যারামিটার প্রসারণ ব্যবহার করে, তারপর কলামটিকে একটি সুইচে ফিড করে যা বোর্ডে তার সমতুল্য পূর্ণসংখ্যার স্বরলিপি নির্দেশ করে, এটি বোঝার জন্য, 'o'তে মানগুলি বরাদ্দ করা হয়েছে দেখুন শক্তিশালী> নীচের সুইচ কেস বিবৃতিতে। উদাহরণস্বরূপ, একজন খেলোয়াড় c3 লিখতে পারে , যা Bash দুটি অক্ষরে বিভক্ত করে:c এবং 3 . সরলতার জন্য, আমি কীভাবে অবৈধ এন্ট্রি পরিচালনা করা হয় তা এড়িয়ে যাচ্ছি।
colm=${opt:0:1} # প্রথম অক্ষর, বর্ণমালা পান
ro=${opt:1:1} # দ্বিতীয় অক্ষর পান, অঙ্ক
ক্ষেত্রে $colm in
a ) o=1;; # পরিশেষে, বর্ণমালাটিকে তার সমতুল্য পূর্ণসংখ্যার স্বরলিপিতে রূপান্তর করুন।
b ) o=2;;
c ) o=3;;
d ) o=4;;
e ) o=5;;
f ) o=6;;
g ) o=7;;
h ) o=8;;
i ) o=9;;
j ) o=10;;
esac
তারপর এটি সঠিক সূচক গণনা করে এবং সেই ক্ষেত্রে ইনপুট স্থানাঙ্কের সূচী নির্ধারণ করে।
এছাড়াও শুফ এর প্রচুর ব্যবহার রয়েছে এখানে কমান্ড করুন, শুফ একটি লিনাক্স ইউটিলিটি যা তথ্যের একটি র্যান্ডম পারমুটেশন প্রদান করার জন্য ডিজাইন করা হয়েছে যেখানে -i বিকল্পটি নির্দেশ করে সূচী বা সম্ভাব্য ব্যাপ্তি পরিবর্তন করার জন্য এবং -n ফেরত দেওয়া সর্বোচ্চ সংখ্যা বা আউটপুট নির্দেশ করে। ডাবল বন্ধনী ব্যাশে গাণিতিক মূল্যায়নের অনুমতি দেয়, এবং আমরা সেগুলি এখানে খুব বেশি ব্যবহার করব।
ধরা যাক আমাদের আগের উদাহরণটি c3 প্রাপ্ত হয়েছে stdin এর মাধ্যমে। তারপর, ro=3 এবং o=3 উপরের সুইচ কেস স্টেটমেন্ট থেকে c রূপান্তরিত এর সমতুল্য পূর্ণসংখ্যাতে, চূড়ান্ত সূচক 'i' গণনা করতে এটিকে আমাদের সূত্রে রাখুন।
i=$(((ro*10)+o)) # চূড়ান্ত সূচক গণনা করতে BODMAS নিয়ম অনুসরণ করুন।
is_free_field $i $(shuf -i 0-5 -n 1) # একটি কাস্টম ফাংশন কল করুন যা পরীক্ষা করে যে চূড়ান্ত সূচকের মান একটি খালি/মুক্ত সেল/ক্ষেত্রে নির্দেশ করে কিনা।
কিভাবে চূড়ান্ত সূচক 'i বুঝতে এই গণিত মাধ্যমে হাঁটা ' গণনা করা হয়:
i=$(((ro*10)+o))
i=$(((3*10)+3))=$((30+3))=33
চূড়ান্ত সূচকের মান হল 33৷ আমাদের বোর্ডে, উপরে মুদ্রিত, চূড়ান্ত সূচকটি 33 তম ঘরে নির্দেশ করে এবং এটি 3য় (0 থেকে শুরু হয়, অন্যথায় 4র্থ) সারি এবং 3য় (C) কলাম হওয়া উচিত৷
উপলব্ধ মাইনফিল্ড নির্ধারণ করতে যুক্তি তৈরি করুন
একটি খনি বের করার জন্য, স্থানাঙ্কগুলি ডিকোড করার পরে এবং সূচকটি পাওয়া যায়, প্রোগ্রামটি সেই ক্ষেত্রটি উপলব্ধ কিনা তা পরীক্ষা করে। যদি এটি না হয়, প্রোগ্রামটি একটি সতর্কতা প্রদর্শন করে এবং প্লেয়ার অন্য স্থানাঙ্ক বেছে নেয়৷
এই কোডে, একটি সেল পাওয়া যায় যদি এটিতে একটি বিন্দু থাকে (. ) চরিত্র। এটি উপলব্ধ অনুমান, কক্ষের মান পুনরায় সেট করা হয় এবং স্কোর আপডেট করা হয়৷ যদি একটি কক্ষ অনুপলব্ধ হয় কারণ এতে একটি বিন্দু নেই, তাহলে একটি পরিবর্তনশীল not_allowed সেট করা হয় সংক্ষিপ্ততার জন্য, গেমের যুক্তিতে সতর্কীকরণ বিবৃতির বিষয়বস্তুর জন্য গেমের সোর্স কোড দেখার জন্য আমি এটি আপনার উপর ছেড়ে দিচ্ছি।
is_free_field()
{
local f=$1
local val=$2
not_allowed=0
যদি [[ "${room[$f]} "="" ]]; তারপর
রুম[$f]=$val
স্কোর=$((স্কোর+ভাল))
else
not_allowed=1
fi
}প্রে>
যদি প্রবেশ করা স্থানাঙ্কটি উপলব্ধ থাকে, খনিটি আবিষ্কৃত হয়, যেমনটি নীচে দেখানো হয়েছে। যখন h6 ইনপুট হিসাবে প্রদান করা হয়, কিছু মান এলোমেলোভাবে আমাদের মাইনফিল্ডে জনবহুল, এই মানগুলি মিনিট বের করার পরে ব্যবহারকারীর স্কোরে যোগ করা হয়।
এখন আমরা শুরুতে ঘোষিত ভেরিয়েবলগুলি মনে রাখবেন, [a-g], আমি এখন সেগুলিকে এখানে ব্যবহার করব এলোমেলো মাইনগুলি বের করার জন্য যা তাদের মান m ভেরিয়েবলে নির্ধারণ করে। ব্যাশ পরোক্ষ ব্যবহার করে। সুতরাং, ইনপুট স্থানাঙ্কের উপর নির্ভর করে, প্রোগ্রামটি অতিরিক্ত সংখ্যার একটি এলোমেলো সেট বেছে নেয় (m ) মূল ইনপুট স্থানাঙ্কে যোগ করে অতিরিক্ত ক্ষেত্রগুলি গণনা করতে (উপরে দেখানো হয়েছে) এখানে i ( দ্বারা প্রতিনিধিত্ব করা হয়েছে) উপরে গণনা করা হয়েছে) .
অনুগ্রহ করে X অক্ষরটি নোট করুন৷ নীচের কোড স্নিপেটে, আমাদের একমাত্র গেম-ওভার ট্রিগার, আমরা শুফ এর সৌন্দর্যের সাথে এলোমেলোভাবে উপস্থিত হওয়ার জন্য এটিকে আমাদের শাফেল তালিকায় যুক্ত করেছি কমান্ড, এটি যেকোন সংখ্যক সুযোগের পরে উপস্থিত হতে পারে বা আমাদের ভাগ্যবান বিজয়ী ব্যবহারকারীর জন্যও উপস্থিত হতে পারে না৷
m=$(shuf -e a b c d e f g X -n 1) # শাফেলে একটি অতিরিক্ত অক্ষর X যোগ করুন, যখন m=X, তার গেমওভার
যদি [[ "$m" !="X" ]]; তাহলে # X হবে আমাদের বিস্ফোরক মাইন (গেম-ওভার) ট্রিগার
সীমা ${!m}; do # !m প্রতিনিধিত্ব করে m
ক্ষেত্র=$(shuf -i 0-5 -n 1) # আবার একটি এলোমেলো সংখ্যা এবং
সূচক=$((i+সীমা)) # আমাদের সূচকে m এর মান যোগ করুন এবং m এর শেষ উপাদানে না পৌঁছা পর্যন্ত একটি নতুন সূচক গণনা করুন।
is_free_field $index $field
সম্পন্ন হয়েছেআমি চাই যে সমস্ত প্রকাশিত সেল প্লেয়ার দ্বারা নির্বাচিত সেলের সাথে সংলগ্ন হোক৷
৷
উপলব্ধ এবং নিষ্কাশিত খনিগুলির একটি গণনা রাখুন
প্রোগ্রামটি মাইনফিল্ডে উপলব্ধ কোষগুলির ট্র্যাক রাখতে হবে; অন্যথায়, সমস্ত কক্ষ প্রকাশিত হওয়ার পরেও এটি প্লেয়ারকে ইনপুট করার জন্য জিজ্ঞাসা করে। এটি বাস্তবায়নের জন্য, আমি free_fields নামে একটি ভেরিয়েবল তৈরি করি , প্রাথমিকভাবে এটি 0 তে সেট করা হয়েছে। একটি এর জন্য লুপ আমাদের মাইনফিল্ডে উপলব্ধ কোষ/ক্ষেত্রের অবশিষ্ট সংখ্যা দ্বারা সংজ্ঞায়িত। যদি একটি কক্ষে একটি বিন্দু থাকে (. ), তারপর মুক্ত_ক্ষেত্রের গণনা বৃদ্ধি করা হয়।
get_free_fields()
{
free_fields=0
for n in $(seq 1 ${#room[@]}); কর
যদি [[ "${রুম[$n]}" ="।" ]]; তারপর
((free_fields+=1))
fi
সম্পন্ন
}অপেক্ষা করুন, যদি, free_fields=0 ? তার মানে, আমাদের ব্যবহারকারী সব মাইন বের করে নিয়েছিলেন। আরও ভালভাবে বোঝার জন্য অনুগ্রহ করে নির্দ্বিধায় সঠিক কোডটি দেখুন৷
৷যদি [[ $free_fields -eq 0 ]]; তাহলে # ভাল তার মানে আপনি সব মাইন বের করেছেন।
printf '\n\n\t%s:%s %d\n\n' "আপনি জিতেছেন" "আপনি স্কোর করেছেন" "$score"
প্রস্থান 0
fiগেমওভারের জন্য যুক্তি তৈরি করুন
গেমওভার পরিস্থিতির জন্য, আমরা কিছু নিফটি লজিক ব্যবহার করে টার্মিনালের মাঝখানে মুদ্রণ করি যে এটি কীভাবে কাজ করে তা অন্বেষণ করার জন্য আমি পাঠকের উপর ছেড়ে দিই।
যদি [[ "$m" ="X" ]]; তারপর
g=0 # প্যারামিটার সম্প্রসারণে এটি ব্যবহার করতে
রুম[$i]=X # সূচকটি ওভাররাইড করুন এবং j এর জন্য X
{42..49} এ প্রিন্ট করুন; মাইনফিল্ডের মাঝখানে # করুন,
out="gameover"
k=${out:$g:1} # প্রতিটি কক্ষে একটি করে বর্ণমালা মুদ্রণ করুন
ঘরে[$j]=${k^^}
((g+=1))
সম্পন্ন
fiঅবশেষে, আমরা সেই দুটি লাইন প্রিন্ট করতে পারি যেগুলো সবচেয়ে বেশি প্রতীক্ষিত।
যদি [[ "$m" ="X" ]]; তারপর
printf '\n\n\t%s:%s %d\n' "গেমওভার" "আপনি স্কোর করেছেন" "$স্কোর"
printf '\n\n\t%s\n \n' "আপনি মাত্র $free_fields মাইন দূরে ছিলেন।"
প্রস্থান 0
fi
এটা, লোকেরা! আপনি যদি আরও জানতে চান, আমার GitHub রেপো থেকে এই মাইনসুইপার গেম এবং বাশ-এর অন্যান্য গেমের সোর্স কোড অ্যাক্সেস করুন। আমি আশা করি এটি আপনাকে আরও ব্যাশ শিখতে এবং এটি করার সময় মজা করার জন্য কিছু অনুপ্রেরণা দেবে।