OCaml

2012-11-10 12 views
6

में गेम बोर्ड का ट्रैक रखने के लिए डेटा संरचना मैं ओकैमल के लिए बिल्कुल नया हूं और मैं एक गेम को कार्यान्वित करना चाहता हूं जो चार-इन-लाइन के समान है। मुझे गेम स्थिति रखने के लिए कुछ डेटा संरचना की आवश्यकता है। गेम बोर्ड कुल 16 टाइल्स के साथ 4x4 वर्ग है। मैं ओकैमल में इसके लिए एक प्रस्तुति की तलाश कर रहा हूं जो पूरे स्तंभ, पंक्ति या विकर्ण में सभी तत्वों को पुनर्प्राप्त करने (या कुछ ऑपरेशन करने) को आसान और तेज़ बना देगा। मैं इस गेम पर मिनीमैक्स खोज कर रहा हूं, यही कारण है कि गति महत्वपूर्ण है।OCaml

अब तक मैंने एक आयामी सूची माना है। सूची के साथ समस्या यह है कि यह पता लगाने में कठिनाई होती है कि कौन से तत्व प्रत्येक पंक्ति/कॉलम/विकर्ण से संबंधित हैं, और फिर उदाहरण के लिए उन्हें List.map से पुनर्प्राप्त करें।

मैंने Array.make 4 (Array.make 4 Empty);; का उपयोग करने के बारे में सोचा। जब पंक्तियों की बात आती है तो यह बिल्कुल सही है। उन्हें प्राप्त करना और उस पर एक पैटर्न मैच करना आसान है। लेकिन यह व्यक्तिगत कॉलम और विकर्णों पर पैटर्न मिलान करने के लिए एक कोर है।

मैं जो करने में सक्षम होना चाहता हूं वह एक ऐसा फ़ंक्शन है जो गेम बोर्ड लेता है और सभी पंक्तियों/कॉलम/विकर्णों वाली सूचियों की एक सूची देता है। मैं फिर करना चाहूंगा, उदाहरण के लिए, match (rows,columns,diagonals) with (Empty, Empty, Empty, Empty) -> something

+4

आप लालित्य या कच्चे गति के लिए जा रहे हैं? अगर कच्ची गति, ऐसा लगता है कि आपका पूरा गेम बोर्ड 32 बिट्स में फिट बैठता है। लेकिन अगर आप ओकैमल सीखना चाहते हैं तो लालित्य शायद बेहतर है। हैंडलिंग बिट्स हर भाषा में समान दिखते हैं। –

उत्तर

1

कभी-कभी मिलान काम नहीं करता है। यहां, मुझे लगता है कि आपको जितना संभव हो सके कार्यों का उपयोग करने की कोशिश करनी चाहिए, और फिर अपनी कोशिकाओं की पंक्ति को पहले प्राप्त करना या पहले कॉलम जटिल नहीं होगा, और आप इंडेक्स ऑर्डर को उलटकर एक प्रतिनिधित्व से दूसरे में भी जा सकते हैं।

अगर मैं निम्नलिखित प्रकार का उपयोग करें:

type color = Red | Yellow;; 
type cell = Empty | Color of color;; 
type board = Array.make 4 (Array.make 4 Empty);; 

और पहले स्तंभ के लिए निर्णय लेते हैं, तो निम्नलिखित कार्य मुझे पंक्तियों या स्तंभों मिल जाएगा:

let column (b: board) i j = b.(i).(j) 
let row (b: board) i j = b.(j).(i) 

विकर्णों के लिए, वहाँ 2 सेट हैं उनमें से एक, नीचे-दायीं तरफ ऊपर की तरफ जा रहा है, और दूसरी तरफ दूसरी दिशा में (शीर्ष-दाएं से नीचे-बाएं):

let ldiag (b: board) i j = b.((i + j) mod 4).(j) 
let rdiag (b: board) i j = b.((i - j + 4) mod 4).(j) 

तब मुझे लगता है कि एक पंक्ति, कॉलम, या विकर्ण की जांच करना उस रेखा की 4 कोशिकाओं की जांच करना है।

let check predicate linef k = predicate (linef b k 0) && 
           predicate (linef b k 1) && 
           predicate (linef b k 2) && 
           predicate (linef b k 3) 

तो उदाहरण के लिए, जाँच लाल के एक विकर्ण हो, तो:

let has_line linef b color = 
    let cmp x = x = color in 
    let check k = check cmp linef b k in 
    check 0 || check 1 || check 2 || check 3 

let has_ldiag b color = has_line ldiag b color 
let has_rdiag b color = has_line rdiag b color 

let has_red_diagonal b = has_ldiag b Red | has_rdiag b Red 

आदि

+0

अच्छी व्याख्या। ऐसा लगता है कि मैं कोड की तरह दिखने की अपेक्षा करता हूं, लेकिन मैं विचारों को कोड में रखने में पूरी तरह से सक्षम नहीं था। मैं थोड़ा दुखी हूं कि आप कॉलम के साथ पैटर्न मिलान नहीं कर सकते हैं, लेकिन मुझे लगता है कि आप इसे सब कुछ नहीं प्राप्त कर सकते हैं। धन्यवाद! – user1815201

2

चूंकि लंबाई तय की गई है, सूचियों पर सरणी पसंद करते हैं: वे कम स्मृति का उपयोग करते हैं और पढ़ने और लिखने के लिए तेज़ होते हैं।

मुझे डर है कि आपको विकर्ण प्राप्त करने के लिए एक फ़ंक्शन लिखने की आवश्यकता होगी, कोई साधारण पैटर्न मिलान नहीं है। जब आप लिखते हैं "[एक विकर्ण] पर कुछ ऑपरेशन करें", मुझे लगता है कि आप एक फ़ंक्शन f के बारे में सोच रहे हैं जो तत्वों को संग्रहीत करने की लंबाई 4 की एक सरणी लेता है, उदाहरण के लिए [|Empty;Empty;Empty;Empty|]। शायद f बदले में p की स्थिति के रूप में तर्क ले सकता है, और स्थिति के अंदर सूचकांक की एक सरणी: f p [|x1,y1; x2,y2; x3,y3; x4,y4|] वर्ग p.(x1).(y1) ... p.(x4).(y4) वर्ग निकालेगा। फिर और y को f बनाने के लिए अलग-अलग x और f को पंक्ति/कॉलम/विकर्णों पर संचालित करें।

एक बार कोड काम कर रहा है और आप ऑप्टिमाइज़ेशन में बदल रहे हैं, तो आप बिटवेक्टरों पर एक नज़र डालना चाहेंगे: यदि आपके पेड़ में मिनमैक्स खोज में बहुत सारी स्थितियां संग्रहीत हैं, तो स्मृति पदचिह्न को कम करने का मतलब है कैश हिट और तेज निष्पादन। आप घटना एक ही int में अपनी स्थिति को एन्कोड करना चाहते हैं, लेकिन यह कुछ मुश्किल काम है, आप इसे बहुत जल्दी नहीं करना चाहते हैं।

+0

क्या आपका मतलब है कि पी एक ऐसा कार्य है जो निर्देशांक लेता है और मूल्य देता है? लंबाई तय होने पर सरणी सूचियों के लिए बेहतर क्यों हैं? – user1815201

+0

(मैंने सरणी बनाम सूचियों के बारे में उत्तर अपडेट किया है)। 'f' (' p' नहीं) एक ऐसा फ़ंक्शन है जो निर्देशांक लेता है और "मान" देता है, उदा। 'सत्य 'iff दिए गए निर्देशांक पर सभी 4 वर्ग' खाली 'हैं। 'f' को दिए गए निर्देशांक पर वर्गों की सामग्री को देखना है, और इस प्रकार इसे स्थिति के रूप में स्थिति 'पी' प्राप्त करने की आवश्यकता है। तो 'f' प्रकार 'स्थिति -> (int * int) सरणी -> बूल' है। – jrouquie

1

संबंधित समन्वय के साथ अपनी टाईल्स को अनुक्रमणित करने के बारे में कैसे?

पंक्ति n:(पूर्व शर्त: 0 <

(int * int * ref tile) 

तो फिर तुम इस तरह फ़िल्टर कर सकते हैं पंक्तियां/स्तंभ/विकर्ण: तो, अपने एक घ सूची पर तत्वों फार्म की होगी = n, u, v < = 3)

List.filter tiles (fun x -> match x with (u, v, _) -> u = n);; 

स्तंभ n:(पूर्व शर्त: 0 < = n, u, v < = 3)

List.filter tiles (fun x -> match x with (u, v, _) -> v = n);; 

विकर्ण 1:(पूर्व शर्त: 0 < = u, v < = 3)

List.filter tiles (fun x -> match x with (u, v, _) -> u = v);; 

विकर्ण 2:(पूर्व शर्त: 0 < = u, v < = 3)

List.filter tiles (fun x -> match x with (u, v, _) -> u + v = 3);; 

टाइल्स को केवल एक पूर्णांक (एक-डी सूची में टाइल की अनुक्रमणिका) के साथ इंडेक्स करना संभव होना चाहिए, लेकिन फ़िल्टर फ़ंक्शन में कुछ गणना की आवश्यकता होगी (इंडेक्स दिया गया है, पता लगाएं समन्वयित करें और फिर तय करें कि यह वांछित पंक्ति/कॉलम/विकर्ण से संबंधित है)।

 संबंधित मुद्दे