मिनीमैक्स के सबसे सरल संस्करण में, पहला खिलाड़ी अपने स्कोर को अधिकतम करना चाहता है, और दूसरा खिलाड़ी पहले खिलाड़ी के स्कोर को कम करना चाहता है। चूंकि पहले और दूसरे खिलाड़ी केवल पहले खिलाड़ी के स्कोर के बारे में परवाह करते हैं, EvaluateStaticPosition
को यह मानना चाहिए कि बोर्ड के पहले खिलाड़ी के लिए कितना अच्छा है। यह किसकी बारी है प्रासंगिक नहीं है।
int EvaluateStaticPosition(stateT state)
{
if(CheckForWin(state, FIRST_PLAYER))
{
return WINNING_POSITION;
}
if(CheckForWin(state, Opponent(FIRST_PLAYER)))
{
return LOSING_POSITION;
}
return NEUTRAL_POSITION;
}
अब, जब आप पहले खिलाड़ी के लिए सबसे अच्छा कदम चाहते हैं, तो MaxMove पर कॉल करें। जब आप दूसरे खिलाड़ी के लिए सबसे अच्छा कदम चाहते हैं, तो मिनमोव को कॉल करें।
moveT MiniMax(stateT state)
{
moveT bestMove;
int i = 0;
if (state.whoseTurn == FIRST_PLAYER){
i = MaxMove(state, bestMove);
}
else{
i = MinMove(state,bestMove);
}
cout<<"i is "<<i<<endl;
return bestMove;
}
अंत में, आप MinMove
और MaxMove
के अंदर कुछ समस्याएं हैं। जब आप किसी एक में curRating
असाइन करते हैं, तो आपको bestMove
में MaxMove
या MinMove
पर दूसरे तर्क के रूप में पास नहीं करना चाहिए। इसके बाद प्रतिद्वंद्वी केbestMove
में सबसे अच्छा स्थानांतरित होगा, जो समझ में नहीं आता है। इसके बजाय, opponentsBestMove
ऑब्जेक्ट घोषित करें और दूसरी तर्क के रूप में पास करें। (आप वास्तव में ऑब्जेक्ट का उपयोग नहीं करेंगे या इसके बाद भी इसके मूल्य को देख नहीं पाएंगे, लेकिन यह ठीक है)। उस परिवर्तन के साथ, आप कभी भी bestMove
पर MinMove
के भीतर कुछ भी असाइन नहीं करते हैं, इसलिए आपको if(curRating < v)
ब्लॉक के अंदर ऐसा करना चाहिए।
int MaxMove(stateT state, moveT &bestMove)
{
if(GameIsOver(state))
{
return EvaluateStaticPosition(state);
}
vector<moveT> moveList;
GenerateMoveList(state, moveList);
int nMoves = moveList.size();
int v = -1000;
for(int i = 0 ;i<nMoves; i++)
{
moveT move = moveList[i];
MakeMove(state, move);
moveT opponentsBestMove;
int curRating = MinMove(state, opponentsBestMove);
if (curRating > v)
{
v = curRating;
bestMove = move;
}
RetractMove(state, move);
}
return v;
}
int MinMove(stateT state, moveT &bestMove)
{
if(GameIsOver(state))
{
return EvaluateStaticPosition(state);
}
vector<moveT>moveList;
GenerateMoveList(state, moveList);
int nMoves = moveList.size();
int v = 1000;
for(int i = 0 ; i<nMoves; i++)
{
moveT move = moveList[i];
MakeMove(state , move);
moveT opponentsBestMove;
int curRating = MaxMove(state,opponentsBestMove);
if(curRating < v)
{
v = curRating;
bestMove = move;
}
RetractMove(state, move);
}
return v;
}
इस बिंदु पर आपको एक अजेय एआई होना चाहिए!
The final position looks like this:
O | O | X
---+---+---
X | X | O
---+---+---
O | X | X
Cat's game.
एक वैकल्पिक पद्धति तथ्य टिक टीएसी को पैर की अंगुली एक शून्य राशि खेल है कि का लाभ लेता है। दूसरे शब्दों में, खेल के अंत में, खिलाड़ियों के स्कोर शून्य के बराबर होगा। दो खिलाड़ी गेम के लिए, इसका मतलब है कि एक खिलाड़ी का स्कोर हमेशा दूसरे खिलाड़ी का नकारात्मक होगा। यह हमारे लिए सुविधाजनक है, क्योंकि दूसरे खिलाड़ी के स्कोर को कम करने के बाद से किसी के अपने स्कोर को अधिकतम करने के समान होता है। तो एक खिलाड़ी के बजाय अपने स्कोर को अधिकतम करने और दूसरे खिलाड़ी के स्कोर को कम करने वाले एक खिलाड़ी के बजाय, हम दोनों खिलाड़ी अपने स्कोर को अधिकतम करने का प्रयास कर सकते हैं।
EvaluateStaticPosition
अपने मूल रूप में वापस बदलें, ताकि यह वर्तमान प्लेयर के लिए बोर्ड राज्य कितना अच्छा है, इस पर आधारित स्कोर प्रदान करता है।
int EvaluateStaticPosition(stateT state)
{
if(CheckForWin(state, state.whoseTurn))
{
return WINNING_POSITION;
}
if(CheckForWin(state, Opponent(state.whoseTurn)))
{
return LOSING_POSITION;
}
return NEUTRAL_POSITION;
}
MinMove
हटाएं, क्योंकि हम केवल अधिकतम करने की परवाह करते हैं। MaxMove
पुनर्लेखन करें ताकि यह उस कदम को चुन सके जो प्रतिद्वंद्वी को सबसे खराब संभव स्कोर देता है। सबसे अच्छे कदम के लिए स्कोर दूसरे खिलाड़ी के सबसे खराब स्कोर का नकारात्मक है।
int MaxMove(stateT state, moveT &bestMove)
{
if(GameIsOver(state))
{
return EvaluateStaticPosition(state);
}
vector<moveT> moveList;
GenerateMoveList(state, moveList);
int nMoves = moveList.size();
int v = -1000;
for(int i = 0 ;i<nMoves; i++)
{
moveT move = moveList[i];
MakeMove(state, move);
moveT opponentsBestMove;
int curRating = -MaxMove(state, opponentsBestMove);
if (curRating > v)
{
v = curRating;
bestMove = move;
}
RetractMove(state, move);
}
return v;
}
MaxMove
के बाद से दोनों खिलाड़ियों के लिए प्रयोग किया जाता है, हम अब MiniMax
समारोह में खिलाड़ियों के बीच भेद करने के लिए की जरूरत है।
moveT MiniMax(stateT state)
{
moveT bestMove;
int i = 0;
i = MaxMove(state, bestMove);
cout<<"i is "<<i<<endl;
return bestMove;
}
क्या आपके द्वारा अद्यतित कोड पोस्ट किया गया है? क्योंकि ऐसा नहीं लगता है कि इसे संकलित करना चाहिए। 'Min_move' में आप तीन तर्कों के साथ' max_move' को कॉल करते हैं, लेकिन max_move केवल दो तर्क ले सकता है। – Kevin
@ केविन: ओह, अब यह अपडेट हो गया है। मैंने कुछ बिंदु पर गहराई को सीमित करने की कोशिश की। – motiur
अद्यतन करने के लिए धन्यवाद, लेकिन गलत रेखा अभी भी वहां है: 'int curValue = max_move (राज्य, गहराई + 1, bestMove); 'यह मुझे चिंता करने का कारण बन रहा है; यह मुझे संदेह करता है कि जिस कोड को आप पोस्ट कर रहे हैं वह वह कोड नहीं है जिसे आप संकलित कर रहे हैं। यह समस्या को खोजने के लिए संभावित उत्तरदाताओं के लिए दोगुना चुनौतीपूर्ण बनाता है। हम पोस्ट कोड में बग की पहचान करेंगे जो वास्तविक कोड में नहीं हैं, और यदि हम पोस्ट कोड में नहीं हैं तो हम वास्तविक कोड में बग नहीं पाएंगे। – Kevin