問題描述
沒有人工智能的井字遊戲 (Tic‑Tac‑Toe without AI)
我正在為 UNI 做作業,我必須在沒有玩家做出任何決定的情況下進行井字遊戲,所有動作都是隨機選擇的。因此,如果矩陣上的字符是“”,則表示它是免費的,而如果它是“X”或“O”,則應該生成另一個移動。這是代碼(C語言):
if (playerTurn == 1){
playerSymb = 'X';
}
else if (playerTurn == 2){
playerSymb = 'O';
}
if (matrix[rand1][rand2] == ' '){
matrix[rand1][rand2] = playerSymb;
} else if(matrix[rand1][rand2] == 'X' || matrix[rand1][rand2] == 'O'){
do{
randAlt1 = MINRND + rand()%(MAXRND ‑ MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND ‑ MINRND +1);
}while (matrix[randAlt1][randAlt2] != 'X' && matrix[randAlt1][randAlt2] != 'O');
matrix[randAlt1][randAlt2] = playerSymb;
}
我沒有復制整個代碼,因為它根本沒有完成,我只需要幫助解決這個問題。但是如果我嘗試運行它,符號可能會被覆蓋,例如如果我在 matrix[1][2]
處有一個“X”,那麼它可能會在一段時間後變成一個“O”轉身。那麼我怎樣才能使動作不覆蓋?(抱歉英語不好)。
參考解法
方法 1:
Just put correct condition:
while (matrix[randAlt1][randAlt2] == 'X' || matrix[randAlt1][randAlt2] == 'O')
(i.e. try again if this cell is not empty)
Also it is easy to simplify your code without loosing of anything:
randAlt1 = rand1;
randAlt2 = rand2;
while (matrix[randAlt1][randAlt2] != ' ') {
randAlt1 = MINRND + rand()%(MAXRND ‑ MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND ‑ MINRND +1);
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';
And it is better to add loop guard to prevent infinite loop (or to add special checks for this case):
randAlt1 = rand1;
randAlt2 = rand2;
int nbAttempts = 0;
while (matrix[randAlt1][randAlt2] != ' ' && nbAttempts < 100) {
randAlt1 = MINRND + rand()%(MAXRND ‑ MINRND +1);
randAlt2 = MINRND + rand()%(MAXRND ‑ MINRND +1);
nbAttempts++;
}
if (matrix[randAlt1][randAlt2] != ' ') {
// show error message and stop the game
}
matrix[randAlt1][randAlt2] = (playerTurn == 1) ? 'X' : 'O';
方法 2:
You choose an arbitrary position and then test if it is free – possibly multiple times. But you can also choose a number of a free position and then find it.
First set up a turn counter
int turnNo = 0;
then make a loop for alternate moves, which chooses one of 9‑turnNo
unused positions, finds it, marks is with a player mark and tests if the move made a line of three:
while(turnNo < 9)
{
char currPlayerMark = ...choose 'X' or 'O';
int freePos = 9 ‑ turnNo;
int currPos = rand() % freePos; // 0 .. freePos‑1
for(x=0; x<3; x++)
{
for(y=0; y<3; y++)
{
if(matrix[x][y] == ' ') // a free position
if(‑‑currPos < 0) // the sought one
break; // break the inner loop
}
if(currPos < 0)
break; // break the outer loop
}
matrix[x][y] = currPlayerMark;
if(test_for_win_position(x,y))
{
message_a_win_of_player(currPlayerMark);
break; // turnNo < 9 here
}
turnNo ++;
}
Finally test if the loop terminated with no 'win':
if(turnNo == 9)
message_its_a_draw(); // no‑one wins
A function to test the win position might look like this:
int test_for_win_position(int x, int y)
{
char mark = matrix[x][y];
// check a column
if(matrix[x][0] == mark && matrix[x][1] == mark && matrix[x][2] == mark)
return 1;
// check a row
if(matrix[0][y] == mark && matrix[1][y] == mark && matrix[2][y] == mark)
return 1;
// check one diagonal
if(x==y)
if(matrix[0][0] == mark && matrix[1][1] == mark && matrix[2][2] == mark)
return 1;
// check another diagonal
if(x+y==2)
if(matrix[0][2] == mark && matrix[1][1] == mark && matrix[2][0] == mark)
return 1;
// current player has not won (yet)
return 0;
}