Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
379
Task/Tic-tac-toe/Scilab/tic-tac-toe.scilab
Normal file
379
Task/Tic-tac-toe/Scilab/tic-tac-toe.scilab
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
function [] = startGame()
|
||||
//Board size and marks
|
||||
N = 3;
|
||||
marks = ["X" "O"];
|
||||
|
||||
//Creating empty board
|
||||
board = string(zeros(N,N));
|
||||
for i = 1:(N*N)
|
||||
board(i) = "";
|
||||
end
|
||||
|
||||
//Initialising players
|
||||
clc();
|
||||
players= [%F %F];
|
||||
players = playerSetup(marks);
|
||||
|
||||
//Console header
|
||||
header = [strsplit(marks(1)+" is ----")';...
|
||||
strsplit(marks(2)+" is ----")'];
|
||||
for i = 1:2
|
||||
if players(i) then
|
||||
header(i,6:10) = strsplit("P"+string(i)+". ");
|
||||
else
|
||||
header(i,6:10) = strsplit("COMP.");
|
||||
end
|
||||
end
|
||||
|
||||
//Game loop
|
||||
sleep(1000);
|
||||
win_flag = %F;
|
||||
count = 0;
|
||||
while count<N*N
|
||||
//Clear console, and print header and board
|
||||
clc();
|
||||
printf("%s\n %s\n",strcat(header(1,:)),strcat(header(2,:)));
|
||||
dispBoard(board);
|
||||
|
||||
//Find which player should move
|
||||
player_n = modulo(count,2) + 1;
|
||||
|
||||
if players(player_n) == %T then
|
||||
//Human plays
|
||||
pos = [];
|
||||
valid_move = %F;
|
||||
disp(marks(player_n)+"''s turn.");
|
||||
while valid_move ~= %T
|
||||
[pos,valid_move] = readHumanMove(board);
|
||||
if ~valid_move then
|
||||
disp("You should input a valid cell number.");
|
||||
end
|
||||
end
|
||||
|
||||
if valid_move then
|
||||
board = updateBoard(board,pos,marks(player_n));
|
||||
else
|
||||
error("Invalid move.");
|
||||
end
|
||||
else
|
||||
//Computer plays
|
||||
disp("Computer is playing.");
|
||||
board = ComputerMove(board,marks(player_n),marks);
|
||||
sleep(800);
|
||||
end
|
||||
|
||||
//Count number of movements
|
||||
count = count + 1;
|
||||
|
||||
//Check if the game has finished
|
||||
[win_flag,winning_mark] = detectWin(board)
|
||||
if win_flag then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
//Clear screen at the end of game
|
||||
clc();
|
||||
disp("Game finished:");
|
||||
dispBoard(board);
|
||||
|
||||
//Print results
|
||||
if win_flag then
|
||||
disp(winning_mark+" won!");
|
||||
else
|
||||
disp("It''s a tie.");
|
||||
end
|
||||
|
||||
//Play again?
|
||||
play_again = "";
|
||||
while play_again ~= "Y" & play_again ~= "N"
|
||||
play_again = input("Would you like to play again? (Y/N)","s");
|
||||
play_again = strsplit(play_again);
|
||||
play_again = convstr(play_again(1),"u");
|
||||
|
||||
if play_again ~= "Y" & play_again ~= "N" then
|
||||
disp("Invalid answer.");
|
||||
end
|
||||
end
|
||||
|
||||
if play_again == "Y" then
|
||||
startGame();
|
||||
else
|
||||
disp("Quit game.");
|
||||
end
|
||||
endfunction
|
||||
|
||||
function players = playerSetup(marks)
|
||||
//Determines who plays which mark
|
||||
players = [%F %F]; //True for human, Flase for computer
|
||||
|
||||
printf("\n%s always starts.\n",marks(1));
|
||||
for i = 1:2
|
||||
user_input = "";
|
||||
while user_input ~= "Y" & user_input ~= "N"
|
||||
user_input = input("Would you like to play as "+marks(i)+"? (Y/N)","s");
|
||||
user_input = strsplit(user_input);
|
||||
user_input = convstr(user_input(1),"u");
|
||||
|
||||
if user_input ~= "Y" & user_input ~= "N" then
|
||||
disp("Invalid answer.");
|
||||
end
|
||||
end
|
||||
|
||||
//Print choice
|
||||
if user_input == "Y" then
|
||||
players(i) = %T;
|
||||
printf("%s shall be player %d (P%d).\n\n",marks(i),i,i);
|
||||
else
|
||||
printf("%s shall be the computer (COMP).\n\n",marks(i));
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function [] = dispBoard(board)
|
||||
//Print ASCII board on console
|
||||
|
||||
//Get board marks
|
||||
marks = [" " " "];
|
||||
mark_inds = find(board ~= "");
|
||||
if mark_inds ~= [] then
|
||||
marks(1) = board(mark_inds(1));
|
||||
mark_inds = find( (board ~= "") & (board ~= marks(1)) );
|
||||
if mark_inds ~= [] then
|
||||
marks(2) = board(mark_inds(1));
|
||||
end
|
||||
end
|
||||
|
||||
//Transpose to display for humans
|
||||
//[compatibility with readHumanMove()]
|
||||
disp_board = board';
|
||||
|
||||
rows = 3*size(board,'r');
|
||||
cols = 4*size(board,'c');
|
||||
ascii_board = string(zeros(rows, cols));
|
||||
|
||||
mark_1=[...
|
||||
strsplit(" |")';...
|
||||
strsplit(" "+marks(1)+" |")';...
|
||||
strsplit("___|")'];
|
||||
|
||||
mark_2=[...
|
||||
strsplit(" |")';...
|
||||
strsplit(" "+marks(2)+" |")';...
|
||||
strsplit("___|")'];
|
||||
|
||||
Blank_mark=[...
|
||||
strsplit(" |")';...
|
||||
strsplit(" |")';...
|
||||
strsplit("___|")'];
|
||||
|
||||
for r = ([1:size(board,'r')] - 1 )
|
||||
for c = ([1:size(board,'c')] - 1)
|
||||
if disp_board(r+1,c+1) == marks(1) then
|
||||
ascii_board((r*3 + 1):((r+1)*3),...
|
||||
(c*4 + 1):((c+1)*4)) = mark_1;
|
||||
elseif disp_board(r+1,c+1) == marks(2) then
|
||||
ascii_board((r*3 + 1):((r+1)*3),...
|
||||
(c*4 + 1):((c+1)*4)) = mark_2;
|
||||
else
|
||||
ascii_board((r*3 + 1):((r+1)*3),...
|
||||
(c*4 + 1):((c+1)*4)) = Blank_mark;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1:cols
|
||||
if modulo(i,4)>0 then
|
||||
ascii_board(rows,i) = " ";
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1:rows
|
||||
ascii_board(i,cols) = " ";
|
||||
end
|
||||
|
||||
printf("\n");
|
||||
for i = 1:size(ascii_board,'r')
|
||||
printf("%s\n",strcat(ascii_board(i,:)))
|
||||
end
|
||||
endfunction
|
||||
|
||||
function moves_board = availableMoves(board)
|
||||
//Find empty cells on the board
|
||||
moves_board = board;
|
||||
|
||||
for i = 1:(size(board,'r')*size(board,'c'))
|
||||
if board(i) == "" then
|
||||
moves_board(i) = string(i);
|
||||
else
|
||||
moves_board(i) = "_";
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function varargout = readHumanMove(board)
|
||||
//Read human input
|
||||
printf("\nAvailable cells:");
|
||||
moves_board = availableMoves(board);
|
||||
disp(moves_board');
|
||||
|
||||
x = input("\nEnter a move (0 to quit game): ");
|
||||
|
||||
valid = %F;
|
||||
pos = 0;
|
||||
total = size(moves_board,'r') * size(moves_board,'c');
|
||||
|
||||
//Check if it is a valid move
|
||||
if x == 0 then
|
||||
disp("Quit game.")
|
||||
abort
|
||||
elseif (x>=1 & x<=total) then
|
||||
if (moves_board(x) == string(x)) then
|
||||
valid = %T;
|
||||
pos = x;
|
||||
end
|
||||
end
|
||||
|
||||
varargout = list(pos,valid);
|
||||
endfunction
|
||||
|
||||
function varargout = updateBoard(board,pos,player)
|
||||
//Add move to the board
|
||||
if board(pos) ~= "" then
|
||||
error('Error: Invalid move.');
|
||||
end
|
||||
|
||||
board(pos) = player
|
||||
|
||||
varargout = list(board);
|
||||
endfunction
|
||||
|
||||
function varargout = detectWin(board)
|
||||
//Detect if there is a winner or not
|
||||
win_flag = %F;
|
||||
winner = "";
|
||||
|
||||
//Get board marks
|
||||
marks = ["" ""];
|
||||
mark_inds = find(board ~= "");
|
||||
marks(1) = board(mark_inds(1))
|
||||
mark_inds = find( (board ~= "") & (board ~= marks(1)) );
|
||||
marks(2) = board(mark_inds(1));
|
||||
|
||||
//If there is a minimum number of moves, check if there is a winner
|
||||
n_moves = find(~(board == ""));
|
||||
n_moves = length(n_moves)
|
||||
|
||||
if n_moves >= size(board,'r') then
|
||||
board_X = (board == marks(1));
|
||||
board_O = (board == marks(2));
|
||||
|
||||
for i = 1:size(board,'r')
|
||||
//Check rows
|
||||
if find(~board_X(i,:)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(1);
|
||||
break
|
||||
end
|
||||
if find(~board_O(i,:)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(2);
|
||||
break
|
||||
end
|
||||
|
||||
//Check columns
|
||||
if find(~board_X(:,i)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(1);
|
||||
break
|
||||
end
|
||||
if find(~board_O(:,i)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(2);
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
//Check diagonal
|
||||
if ~win_flag then
|
||||
if find(~diag(board_X)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(1);
|
||||
elseif find(~diag(board_O)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(2);
|
||||
end
|
||||
end
|
||||
|
||||
//Check anti-diagonal
|
||||
if ~win_flag then
|
||||
board_X = board_X(:,$:-1:1);
|
||||
board_O = board_O(:,$:-1:1);
|
||||
|
||||
if find(~diag(board_X)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(1);
|
||||
elseif find(~diag(board_O)) == [] then
|
||||
win_flag = %T;
|
||||
winner = marks(2);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
varargout = list(win_flag,winner)
|
||||
endfunction
|
||||
|
||||
function threat_pos = findThreat(board,player)
|
||||
//Returns a list of moves that can finish the game
|
||||
|
||||
//Available moves
|
||||
move_inds = find(~( availableMoves(board) == "_" ));
|
||||
|
||||
//If there is a minimum number of moves, check if there is a threat
|
||||
threat_pos = [];
|
||||
if (size(board,'r')*size(board,'c')) - length(move_inds) >...
|
||||
(size(board,'r') - 1) then
|
||||
for i = 1:length(move_inds)
|
||||
temp_board = updateBoard(board,move_inds(i),player);
|
||||
[win_flag,winner] = detectWin(temp_board);
|
||||
if win_flag & winner == player then
|
||||
threat_pos = [threat_pos move_inds(i)];
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function varargout = ComputerMove(board,mark,all_marks)
|
||||
//Atomatically add a move to the board with no human input
|
||||
|
||||
//Find winning moves moves
|
||||
move_inds = findThreat(board,mark);
|
||||
|
||||
//If there are no winning moves, find opponent's winning moves
|
||||
//to block opponent's victory
|
||||
if move_inds == [] then
|
||||
if mark == all_marks(1) then
|
||||
opponent = all_marks(2);
|
||||
elseif mark == all_marks(2) then
|
||||
opponent = all_marks(1);
|
||||
end
|
||||
|
||||
move_inds = findThreat(board,opponent);
|
||||
end
|
||||
|
||||
//If there are no winning moves or threats, find all possible moves
|
||||
if move_inds == [] then
|
||||
move_inds = find(~( availableMoves(board) == "_" ));
|
||||
end
|
||||
|
||||
//Choose a random move among the selected possible moves
|
||||
pos = grand(1,"prm",move_inds);
|
||||
pos = pos(1);
|
||||
|
||||
//Update board by adding a new mark
|
||||
board(pos) = mark;
|
||||
|
||||
varargout = list(board);
|
||||
endfunction
|
||||
|
||||
startGame()
|
||||
Loading…
Add table
Add a link
Reference in a new issue