Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View 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()