othello.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 234 行
ERL
234 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(othello).-export([start/0,new_game/4,start1/5]).%%----------------------------------------------------------------------%% The Othello program now uses the gs graphical package instead of the %% pxw package. See module othello_board for details%%%%----------------------------------------------------------------------start() -> othello_board:start().new_game(Computer,Player,Depth,Init) -> spawn_link(othello,start1,[self(),Computer,Player,Depth,Init]).start1(Win,Computer,Player,Depth,Init) -> Board = othello_adt:new(t), random:seed(), init_display(Board,Win,Init), play(Computer,Player,Board,Depth,Win,1).play(Computer,Player,Board,Depth,Win,NoDs) -> tell_win(Win,Computer,Player), case catch continue(Player,Board) of {game_over,Result} -> game_over(Board,Player,Result,Win); {omit_draw,Player} -> omit(Player,Win), play(Computer,swap(Player),Board,Depth,Win,NoDs); ok -> Draw = choose_draw(Computer,Player,Board,Depth,Win,NoDs), Win ! {self(),draw,Draw}, Board1 = othello_adt:set(Draw,Player,Board), display(Board1,Board,Win), play(Computer,swap(Player),Board1,Depth,Win,NoDs+1) end.continue(Player,Board) -> Draws = game_over(Player,Board), not_allowed(Draws,Player), ok.choose_draw(Computer,Computer,Board,Depth,_Win,NoDs) -> % Depth > 0 !! {Draw,_Value} = alpha_beta(Depth,Board,-11000,11000,Computer,NoDs),% io:format('Choosen draw is {~w,~w} : (~w)~n',% [othello_adt:col(Draw),othello_adt:row(Draw),Value]),% io:format('=====================~n',[]), Draw;choose_draw(Computer,Player,Board,Depth,Win,NoDs) -> receive {Win,position,Draw} -> flush(Win), case othello_adt:is_draw(Draw,Player,Board) of false -> Win ! {self(),illegal_draw,Draw}, choose_draw(Computer,Player,Board,Depth,Win,NoDs); true -> Draw end end.flush(Win) -> receive {Win,position,_} -> flush(Win) after 1 -> true end.tell_win(Win,Computer,Player) -> Win ! {self(),player,Computer,Player}, receive {Win,go_on_play} -> true end.alpha_beta(0,Board,_,_,Player,_) -> {-1,othello_adt:evaluate_board(Player,Board)};alpha_beta(Depth,Board,Alpha,Beta,Player,NoDs) -> case compute(Player,Board,NoDs) of [] -> Player1 = swap(Player), case compute(Player1,Board,NoDs) of [] -> dead_lock(Board,Player); PosDraws1 -> choose(PosDraws1,Board,Depth-1,-Beta,-Alpha,-1, Player1,NoDs) end; PosDraws -> choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs)% A = choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs),% io:format('Alpha-Beta (~w) ==> ~w~n',[Depth,A]),% A end.choose([Draw|Draws],Board,Depth,Alpha,Beta,Record,Player,NoDs) -> Player1 = swap(Player), Board1 = othello_adt:set(Draw,Player,Board),% io:format('Alpha <~w> Beta <~w> ~n',[Alpha,Beta]), {_,Value} = alpha_beta(Depth,Board1,Alpha,Beta,Player1,NoDs+1), Value1 = -Value, cutoff(Draw,Value1,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs);choose([],_,_,Alpha,_,Draw,_,_) -> {Draw,Alpha}. cutoff(Draw,Value,_,_,Beta,_,_,_,_,_) when Value >= Beta -> {Draw,Value};cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,_,Player,NoDs) when Alpha < Value, Value < Beta -> choose(Draws,Board,Depth,Value,Beta,Draw,Player,NoDs);cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs) when Value == Alpha, NoDs < 13 -> choose(Draws,Board,Depth,Alpha,Beta,random_choice(Draw,Record), Player,NoDs);cutoff(_Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs) when Value =< Alpha -> choose(Draws,Board,Depth,Alpha,Beta,Record,Player,NoDs).compute(Player,Board,NoOfDraws) when NoOfDraws < 13 -> case othello_adt:possible_draws(Player,Board,begin_play) of [] -> othello_adt:possible_draws(Player,Board,playing); Draws -> Draws end;compute(Player,Board,_) -> othello_adt:possible_draws(Player,Board,playing).%%----------------------------------------------------------%% Randomly choose between two draws with the same value.%%---------------------------------------------------------- random_choice(Draw,Draw1) -> case random:uniform(2) of 1 -> Draw; 2 -> Draw1 end.dead_lock(Board,Player) -> case win_or_loose(Board,Player) of 0 -> {-1,0}; Value when Value > 0 -> {-1,10000}; _ -> {-1,-10000} end.win_or_loose(Board,Player) -> Player1 = swap(Player), othello_adt:pieces(Player,Board) - othello_adt:pieces(Player1,Board).game_over(Player,Board) -> case othello_adt:possible_draws(Player,Board,playing) of [] -> Player1 = swap(Player), case othello_adt:possible_draws(Player1,Board,playing) of [] -> throw({game_over,{{Player,othello_adt:pieces(Player,Board)}, {Player1,othello_adt:pieces(Player1,Board)}}}); _ -> [] % Player`s Draws !! end; Draws -> Draws end.game_over(_Board,_Player,Result,Win) -> Win ! {self(),game_over,white_res(Result),black_res(Result)}.white_res({{white,Res},_}) -> Res;white_res({_,{white,Res}}) -> Res. black_res({{black,Res},_}) -> Res;black_res({_,{black,Res}}) -> Res.not_allowed([],Player) -> throw({omit_draw, Player});not_allowed(_,_Player) -> ok.omit(Player,Win) -> Win ! {self(),omit_draw,Player}, receive {Win,continue} -> ok end.init_display(_Board,_Win,first_time) -> true;init_display(Board,Win,_) -> display(Board,Win).display(Board,Win) -> All = othello_adt:all_pos(Board), display1(All,Win), Win ! {self(),score,othello_adt:pieces(white,Board), othello_adt:pieces(black,Board)}.display(Board,OldB,Win) -> Diff = othello_adt:diff(Board,OldB), display1(Diff,Win), Win ! {self(),score,othello_adt:pieces(white,Board), othello_adt:pieces(black,Board)}. display1([{Pos,Colour}|Diff],Win) -> Win ! {self(),new_mark,Pos,Colour}, display1(Diff,Win);display1(_,_) -> true.swap(white) -> black;swap(black) -> white.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?