ট্র্যাক
/
Go
Go
/
অনুশীলনী
/
দাবা বোর্ড
দাবা বোর্ড

দাবা বোর্ড

লার্নিং অনুশীলনী

ভূমিকা

Go-তে আপনি for আর একটি ইনডেক্স ব্যবহার করে slice-এর ওপর ইটারেশন করতে পারেন, অথবা range ব্যবহার করতে পারেন। range দিয়ে আবার map-এর ওপরও ইটারেশন করা যায়।

প্রতিটি ইটারেশন দুটি মান রিটার্ন করে: ইনডেক্স/কী (key) আর সেই ইনডেক্স/কী (key)-এর জায়গায় থাকা এলিমেন্টের একটি কপি।

একটি স্লাইসের ওপর ইটারেশন

একেবারে জলের মতো সহজ, স্লাইসের ওপর লুপ চলে, আর ক্রমও প্রত্যাশিত মতোই।

xi := []int{10, 20, 30}
for i, x := range xi {
  fmt.Println(i, x)
}
// outputs:
// 0, 10
// 1, 20
// 2, 30

একটি ম্যাপের ওপর ইটারেশন

ম্যাপের ওপর ইটারেশন করলে নতুন একটি সমস্যা দেখা দেয়। এখন ক্রমটি র্যান্ডম।

hash := map[int]int{9: 10, 99: 20, 999: 30}
for k, v := range hash {
  fmt.Println(k, v)
}
// outputs, for example:
// 99 20
// 999 30
// 9 10
Note

উপরের আউটপুটটি ভুল বলে মনে হতে পারে, কারণ ম্যাপটি ডিক্লেয়ার করার সময় প্রথম যে কী (key)/মান জোড়াটি লেখা হয়েছিল, অর্থাৎ 9 10, সেটিই সবার আগে প্রিন্ট হবে, সবার শেষে নয়, এমনটাই স্বাভাবিকভাবে প্রত্যাশা করা যায়। তবে ম্যাপে স্বভাবতই কোনো নির্দিষ্ট ক্রম থাকে না, তাই এর কোনো প্রথম বা শেষ কী (key)/মান জোড়াও নেই। এই কারণে ম্যাপের এন্ট্রিগুলোর ওপর ইটারেশন করলে কোন এন্ট্রি কোন ক্রমে দেখা হবে তা র্যান্ডম, কোনো নির্দিষ্ট প্যাটার্ন মানে না। এর মানে হলো, উপরের আউটপুটটি সম্ভব, তবে আপনি নিজে এটি রান করে দেখলে যা পাবেন তার থেকে সেটি আলাদা হতে পারে। এই বিষয়ে আরও জানতে দেখুন Go Language Spec: range clause।

কী (key) বা মান বাদ দিয়ে ইটারেশন

Go-তে ব্যবহার না করা ভ্যারিয়েবল থাকলে বিল্ডের সময় এরর হয়। কখনও কখনও প্রথম উদাহরণের মতো আপনার শুধু মানটিই দরকার হয়:

xi := []int{10, 20, 30}
for i, x := range xi {
  fmt.Println(x)
}
// Go build failed: i declared but not used

আপনি i-এর বদলে _ বসাতে পারেন, যা কম্পাইলারকে জানায় যে আমরা ওই মানটি ব্যবহার করি না:

xi := []int{10, 20, 30}
for _, x := range xi {
  fmt.Println(x)
}
// outputs:
// 10
// 20
// 30

আপনি যদি শুধু ইনডেক্সটি প্রিন্ট করতে চান, তাহলে x-এর বদলে _ বসাতে পারেন, কিংবা ডিক্লারেশনটি একেবারে বাদ দিতে পারেন:

xi := []int{10, 20, 30}
// for i, _ := range xi {
for i := range xi {
  fmt.Println(i)
}
// outputs:
// 0
// 1
// 2

টাইপ ডিফাইন করা

একটি টাইপ ডেফিনিশন নতুন একটি নামযুক্ত টাইপ তৈরি করে, যা অন্য প্রতিটি টাইপ থেকে আলাদা, এমনকি একই অন্তর্নিহিত টাইপের হলেও।

type File []bool

এখানে File বলতে দাবাবোর্ডের একটি একক উল্লম্ব কলাম বোঝায়, যাকে সাধারণত A থেকে H পর্যন্ত লেবেল করা হয়। এই কলামের প্রতিটি ঘরকে একটি বুলিয়ান মান দিয়ে প্রকাশ করা হয়, যা বোঝায় ঘরটি দখল করা আছে কি না। এখন যেহেতু File ডিফাইন করা হয়েছে, আমরা এটিকে অন্য ডেফিনিশনের ভেতরে ব্যবহার করতে পারি:

type Chessboard map[string]File

board := Chessboard{
    "A": File{true, false, true},
    "B": File{false, true, false},
}

Chessboard ফাইল আইডেন্টিফায়ারগুলোকে File মানে ম্যাপ করে। প্রতিটি File হলো বুলিয়ানের একটি স্লাইস, যা একটি দাবা ফাইলের ঘরগুলোর প্রতিনিধিত্ব করে। এই টাইপ ডেফিনিশনগুলো ছাড়া board হতো একটি map[string][]bool, যা আমরা কী প্রকাশ করছি সেটি বোঝা আরও কঠিন করে তুলত।

নির্দেশনা

দাবার একজন অনুরাগী হিসেবে আপনি নিশ্চয়ই খেলাটির নিজের একটি সংস্করণ লিখতে চান। হ্যাঁ, অনলাইনে দাবার অনেক রকম ইমপ্লিমেন্টেশন হয়তো আগে থেকেই আছে, কিন্তু আপনারটি হবে একেবারেই অনন্য!

দাবার বোর্ডের প্রতিটি ঘর চিহ্নিত করা হয় একটি অক্ষর ও একটি সংখ্যার জোড়া দিয়ে:

  • ঘরগুলোর আনুভূমিক সারিগুলোকে বলা হয় র‍্যাঙ্ক, এগুলো ১ থেকে ৮ পর্যন্ত সংখ্যাযুক্ত।
  • আর খাড়া কলামগুলোকে বলা হয় ফাইল, এগুলো A থেকে H পর্যন্ত নামাঙ্কিত।
   A B C D E F G H
 8 # _ _ _ # _ _ # 8
 7 _ _ _ _ _ _ _ _ 7
 6 _ _ _ _ # _ _ # 6
 5 _ # _ _ _ _ _ # 5
 4 _ _ _ _ _ _ # # 4
 3 # _ # _ _ _ _ # 3
 2 _ _ _ _ _ _ _ # 2
 1 # _ _ _ _ _ _ # 1
   A B C D E F G H

1. একটি দাবার বোর্ড আর একটি ফাইল দেওয়া থাকলে, কতগুলো ঘর দখল করা আছে গণনা করুন

CountInFile(board Chessboard, file string) int ফাংশনটি ইমপ্লিমেন্ট করুন। এটি একটি ম্যাপের উপর range করে মোট কতগুলো ঘর দখল করা আছে তা গণনা করবে। একটি ইন্টিজার রিটার্ন করুন। প্রদত্ত ফাইলটি ম্যাপে না পাওয়া গেলে শূন্য (0) রিটার্ন করুন।

CountInFile(board, "A")
// => 3

2. একটি দাবার বোর্ড আর একটি র‍্যাঙ্ক দেওয়া থাকলে, কতগুলো ঘর দখল করা আছে গণনা করুন

CountInRank(board Chessboard, rank int) int ফাংশনটি ইমপ্লিমেন্ট করুন। এটি প্রদত্ত র‍্যাঙ্কের উপর range করে মোট কতগুলো ঘর দখল করা আছে তা গণনা করবে। একটি ইন্টিজার রিটার্ন করুন। প্রদত্ত র‍্যাঙ্কটি বৈধ না হলে (অর্থাৎ 1 থেকে 8-এর মধ্যে না হলে, দুটো প্রান্তসহ) শূন্য (0) রিটার্ন করুন।

CountInRank(board, 2)
// => 1

3. প্রদত্ত দাবার বোর্ডে কতগুলো ঘর আছে গণনা করুন

CountAll(board Chessboard) int ফাংশনটি ইমপ্লিমেন্ট করুন। এটি দাবার বোর্ডে কতগুলো ঘর আছে তা গণনা করবে এবং একটি ইন্টিজার রিটার্ন করবে। যেহেতু ঘরগুলোর ভেতরের কনটেন্ট যাচাই করার দরকার নেই, তাই index ও value দুটোই বাদ দিয়ে range ব্যবহার করার কথা ভাবতে পারেন।

CountAll(board)
// => 64

4. প্রদত্ত দাবার বোর্ডে কতগুলো ঘর দখল করা আছে গণনা করুন

CountOccupied(board Chessboard) int ফাংশনটি ইমপ্লিমেন্ট করুন। এটি দাবার বোর্ডে কতগুলো ঘর দখল করা আছে তা গণনা করবে। একটি ইন্টিজার রিটার্ন করুন।

CountOccupied(board)
// => 15
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি একটি নতুন উইন্ডো বা ট্যাবে খোলে
Go Exercism

দাবা বোর্ড শুরু করতে প্রস্তুত?

Exercism-এ সাইন আপ করুন, Go ট্র্যাকের 34টি কনসেপ্ট166টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।