英文:
The game of 23 matches in SWIPROLOG
问题
我尝试在SWIPROLOG中创建23匹配游戏(在此处编译:https://swish.swi-prolog.org/)。
这个游戏代表什么?
桌子上有23根火柴。有两名玩家,每名玩家都必须从桌子上拿几根火柴。每位玩家可以拿1、2或3根火柴。拿到倒数第二根火柴的玩家输掉游戏。
我已经将这个游戏实现为与计算机对战的游戏(一次计算机选择,一次用户选择,通过键盘输入匹配数量)。计算机选择匹配数量的特殊策略,以使用户输掉,即以一种方式拾取火柴,迫使用户选择倒数第二根火柴并输掉。这两者交替选择,直到其中一方输掉。
这基本上是我设法实现的内容。
在这段代码中的问题在于策略。我无法确定一种策略,使计算机总是赢。以下是一个示例。
如果桌子上有3根火柴,轮到计算机选择时,它拿走2根,从而输掉了比赛,而它应该拿走1根,用户输掉了比赛。
我的问题是:是否有可能确定一种更有效的策略,使计算机总是赢(或几乎总是赢)?如果可能的话,我将非常感谢您的建议,如果可能的话,还有代码。我是Prolog的初学者,也许有些东西我还没有理解。
(注意:代码部分已省略)
英文:
I tried to make the 23 matches game in SWIPROLOG (compiled here : https://swish.swi-prolog.org/).
What does this game represent?
There are 23 matches on the table. There are two players and each of them has to take a few matches from the table.
matches. Each player is allowed to take 1, 2, or 3 matches. The player who takes the last but one match loses the game.
I have implemented this as a game against the computer (once the computer chooses, once the user chooses, by entering the number of matches on the keyboard). It chooses the number of matches by a special strategy, in such a way, as to make the user lose, i.e. pick up matches in such a way, as to force the user to choose the penultimate match and lose. The 2 make choices until one of them loses.
That's pretty much what I managed to implement:
% Start game with 23 matches and computer as first player
joc :- joc(23, calculator, in_progress).
% Player's turn
joc(N, player, State) :-
nl,
write('There are '), write(N), write(' matches on the table.'), nl,
(State == finished ->
write('The game has ended.'), nl
;
write('It is your turn. '), nl,
read(M),
(valid_move(M, N) ->
N1 is N - M,
write('You chose '), write(M), write(' matches.'), nl,
(N1 =< 1 ->
write('The game has ended. You '), (State == won -> write('won!'), nl ; write('lost!'), nl),
joc(N1, calculator, finished)
;
joc(N1, calculator, in_progress)
)
;
write('Invalid move. Please try again.'), nl,
joc(N, player, State)
)
).
% Computer's turn
joc(N, calculator, State) :-
nl,
write('There are '), write(N), write(' matches on the table.'), nl,
(State == finished ->
write('The game has ended.'), nl
;
write('It is the computer\'s turn. '), nl,
optimal_move(N, M),
N1 is N - M,
write('The computer chose '), write(M), write(' matches.'), nl,
(N1 =< 1 ->
write('The game has ended. The computer '), (State == won -> write('won!'), nl ; write('lost!'), nl),
joc(N1, player, finished)
;
joc(N1, player, in_progress)
)
).
% Check if move is valid (between 1 and 3 matches, and not more than available matches)
valid_move(M, N) :-
M >= 1,
M =< 3,
M =< N.
% Calculate computer's optimal move
optimal_move(N, M) :-
X is N mod 4,
(X > 1 -> M is min(X-1, 3) ; M is max(min(N-2, 3), 1)).
The problem in this code, is strategy. I could not identify a strategy, in which the computer would always win.
Here's an example.
If there are 3 matches on the table and it is the computer's turn to pick, it picks 2 and thus loses, while it should pick 1 and the user loses.
My question : is it possible to identify a more efficient startegy, in which the calcualtor would always win(or almost always?) If so, I would be grateful for suggestions, and if possible, code. I'm a beginner in prologue, maybe something will escape me.
答案1
得分: 0
以下是翻译好的部分:
快速分析:
matches23(N, T) :-
between(1, 23, N),
matches23_(N, T).
matches23_(N, T) :-
% 我的步骤
take_matches(N, T, N0),
% 对手的步骤,确保对手不能获胜
\+ matches23_(N0, _).
take_matches(N, T, N0) :-
between(1, 3, T),
N0 is N - T,
% 确保至少剩下1个
N0 @>= 1.
在swi-prolog中的结果:
?- findall(N-T, matches23(N, T), Ps).
Ps = [2-1, 3-2, 4-3, 6-1, 7-2, 8-3, 10-1, 11-2, 12-3,
14-1, 15-2, 16-3, 18-1, 19-2, 20-3, 22-1, 23-2].
所以,通过移除2根火柴开始23游戏,如果您遵循其他步骤,您将确保获胜
英文:
A quick analysis:
matches23(N, T) :-
between(1, 23, N),
matches23_(N, T).
matches23_(N, T) :-
% My move
take_matches(N, T, N0),
% Opponent's move, ensuring opponent cannot win
\+ matches23_(N0, _).
take_matches(N, T, N0) :-
between(1, 3, T),
N0 is N - T,
% Leave at least 1 remaining
N0 @>= 1.
Results in swi-prolog:
?- findall(N-T, matches23(N, T), Ps).
Ps = [2-1, 3-2, 4-3, 6-1, 7-2, 8-3, 10-1, 11-2, 12-3,
14-1, 15-2, 16-3, 18-1, 19-2, 20-3, 22-1, 23-2].
So, start the 23 game by removing 2 matches, and you have a guaranteed win if you follow the other steps
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论