Initial commit on develop branch
This commit is contained in:
+549
@@ -0,0 +1,549 @@
|
||||
#include<iostream>
|
||||
#include<conio.h>
|
||||
#include<cstdlib>
|
||||
#include<ctime>
|
||||
#include<string>
|
||||
#include<algorithm>
|
||||
#include<fstream>
|
||||
#include<windows.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct game_history{
|
||||
string p1_name;
|
||||
string p2_name;
|
||||
int black_score;
|
||||
int white_score;
|
||||
string winner_name;
|
||||
string time;
|
||||
};
|
||||
|
||||
game_history game_h[100];
|
||||
int cu =0;
|
||||
//تعداد بازی های انجام شده
|
||||
|
||||
void enter_data();
|
||||
void add_data(game_history game_history);
|
||||
void report_data();
|
||||
void load_data();
|
||||
void save_data();
|
||||
|
||||
const int BOARD_SIZE = 8;
|
||||
const char EMPTY = '-';
|
||||
const char BLACK = 'B';
|
||||
const char WHITE = 'W';
|
||||
|
||||
char board [BOARD_SIZE][BOARD_SIZE];
|
||||
|
||||
struct coordinate{
|
||||
int r;
|
||||
int c;
|
||||
};
|
||||
|
||||
void Initialize_Board(){
|
||||
for (int r=0 ; r<BOARD_SIZE ; r++){
|
||||
for(int c=0 ; c<BOARD_SIZE ; c++){
|
||||
board[r][c]=EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
board[3][3] = WHITE;
|
||||
board[4][4] = WHITE;
|
||||
board[3][4] = BLACK;
|
||||
board[4][3] = BLACK;
|
||||
}
|
||||
|
||||
void clear_screen(){
|
||||
system("cls");
|
||||
}
|
||||
|
||||
void print_board(char current_player , const bool valid_moves[BOARD_SIZE][BOARD_SIZE] ,int cursor_r ,int cursor_c){
|
||||
cout << "\n ~~~~~~~~~~~~~~~~~~~~ " << endl;
|
||||
cout << "turn :" << (current_player == BLACK ? "B" : "W") << endl;
|
||||
|
||||
cout << " ";
|
||||
for(int c=0 ; c<BOARD_SIZE ; c++){
|
||||
cout << " " << c+1;
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
for (int r=0; r<BOARD_SIZE; r++){
|
||||
cout << r+1 << (r<9 ? " " : " ");
|
||||
for(int c=0 ; c<BOARD_SIZE ; c++){
|
||||
char display_char = board[r][c];
|
||||
|
||||
if(valid_moves[r][c]){
|
||||
display_char ='*';
|
||||
}
|
||||
|
||||
if(r == cursor_r && c == cursor_c){
|
||||
if(display_char == EMPTY || display_char == '*'){
|
||||
display_char = (current_player== BLACK ? 'b' : 'w');
|
||||
}
|
||||
}
|
||||
|
||||
cout << " " << display_char;
|
||||
}
|
||||
cout << " |" <<endl;
|
||||
}
|
||||
cout << "~~~~~~~~~~~~~~~~~~~~" << endl;
|
||||
}
|
||||
|
||||
bool is_valid_move(int r , int c , char player , char opponent){
|
||||
|
||||
if ( r<0 || r>= BOARD_SIZE || c<0 || c>= BOARD_SIZE || board[r][c] != EMPTY) return false;
|
||||
|
||||
int direct_r [] = {0 , 1 , 1 , 1 , 0 , -1 , -1 , -1 };
|
||||
int direct_c [] = {1 , 1 , 0 , -1 , -1 , -1 , 0 , 1 };
|
||||
|
||||
for (int i = 0; i < 8; i++){
|
||||
int next_r = r+ direct_r[i];
|
||||
int next_c = c+ direct_c[i];
|
||||
|
||||
bool found_opponent = false;
|
||||
while(next_r>=0 && next_r<BOARD_SIZE && next_c>=0 && next_r<BOARD_SIZE){
|
||||
if(board[next_r][next_c] == opponent){
|
||||
found_opponent = true;
|
||||
}
|
||||
|
||||
else if(board[next_r][next_c] == player){
|
||||
if(found_opponent) return true;
|
||||
break;
|
||||
}
|
||||
|
||||
else if(board[next_r][next_c] == EMPTY) break;
|
||||
|
||||
next_r += direct_r[i];
|
||||
next_c += direct_c[i];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void get_valid_moves(char player , char opponent , bool valid_moves[BOARD_SIZE][BOARD_SIZE]){
|
||||
|
||||
for (int r= 0; r < BOARD_SIZE; r++){
|
||||
for (int c = 0; c < BOARD_SIZE; c++){
|
||||
valid_moves[r][c] = is_valid_move(r ,c , player , opponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int make_move(int r, int c , char player , char opponent){
|
||||
|
||||
board[r][c] = player;
|
||||
int flipped_count = 0;
|
||||
|
||||
int direct_r [] = {0 , 1 , 1 , 1 , 0 , -1 , -1 , -1 };
|
||||
int direct_c [] = {1 , 1 , 0 , -1 , -1 , -1 , 0 , 1 };
|
||||
|
||||
for (int i = 0; i < 8; i++){
|
||||
int next_r = r + direct_r[i];
|
||||
int next_c = c + direct_c[i];
|
||||
|
||||
bool found_opponent = false;
|
||||
int temp_r = next_r;
|
||||
int temp_c = next_c;
|
||||
|
||||
|
||||
while(temp_r>=0 && temp_r<BOARD_SIZE && temp_c>=0 && temp_c < BOARD_SIZE){
|
||||
if (board[temp_r][temp_c] == opponent){
|
||||
found_opponent = true;
|
||||
}
|
||||
|
||||
else if(board[temp_r][temp_c] == player){
|
||||
if(found_opponent){
|
||||
int flip_r = next_r;
|
||||
int flip_c = next_c;
|
||||
while(flip_r != temp_r || flip_c !=temp_c){
|
||||
if(board[flip_r][flip_c] == opponent){
|
||||
board[flip_r][flip_c] = player;
|
||||
flipped_count++;
|
||||
}
|
||||
if(flip_r<temp_r) flip_r++;
|
||||
else if(flip_r>temp_r) flip_r--;
|
||||
if(flip_c<temp_c) flip_c++;
|
||||
else if(flip_c>temp_c) flip_c--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
else if(board[temp_r][temp_c] == EMPTY){
|
||||
break;
|
||||
}
|
||||
|
||||
if(temp_r < temp_r +direct_r[i]) temp_r++;
|
||||
else if(temp_r > temp_r +direct_r[i]) temp_r--;
|
||||
|
||||
if(temp_c < temp_c +direct_c[i]) temp_c++;
|
||||
else if(temp_c > temp_c +direct_c[i]) temp_c--;
|
||||
}
|
||||
}
|
||||
return flipped_count;
|
||||
}
|
||||
|
||||
void run_game_flow(const string & player1_name ,const string &player2_name, bool is_single_player ){
|
||||
Initialize_Board();
|
||||
char current_player =BLACK;
|
||||
string p1_name = player1_name;
|
||||
string p2_name = player2_name;
|
||||
string time;
|
||||
|
||||
int current_row = BOARD_SIZE/2-1;
|
||||
int current_col = BOARD_SIZE/2-1;
|
||||
|
||||
bool valid_moves [BOARD_SIZE][BOARD_SIZE] = {false};
|
||||
get_valid_moves(current_player , (current_player == BLACK ? WHITE : BLACK) , valid_moves);
|
||||
|
||||
bool initial_cursor_set = false;
|
||||
for (int r= 0; r < BOARD_SIZE; r++){
|
||||
for (int c = 0; c < BOARD_SIZE; c++){
|
||||
if(valid_moves[r][c]){
|
||||
current_row = r;
|
||||
current_col = c;
|
||||
initial_cursor_set = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
char opponent =(current_player == BLACK ? WHITE : BLACK);
|
||||
get_valid_moves(current_player , opponent , valid_moves);
|
||||
|
||||
int black_score =0;
|
||||
int white_score =0;
|
||||
bool current_can_move = false;
|
||||
|
||||
for (int r= 0; r < BOARD_SIZE; r++){
|
||||
for (int c = 0; c < BOARD_SIZE; c++){
|
||||
if(board[r][c]== BLACK) black_score++;
|
||||
if(board[r][c]== WHITE) white_score++;
|
||||
if(valid_moves[r][c]) current_can_move = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool temp_moves[BOARD_SIZE][BOARD_SIZE] ={false};
|
||||
get_valid_moves(opponent, current_player , temp_moves);
|
||||
bool opponent_can_move = false;
|
||||
|
||||
for (int r= 0; r < BOARD_SIZE; r++){
|
||||
for (int c = 0; c < BOARD_SIZE; c++){
|
||||
if(temp_moves[r][c]){
|
||||
opponent_can_move =true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(opponent_can_move) break;
|
||||
}
|
||||
|
||||
if(!current_can_move && !opponent_can_move){
|
||||
clear_screen();
|
||||
cout << "\n ~~~~~The End of Game~~~~~"<<endl;
|
||||
cout <<" final black score : ( " << black_score <<" )"<<endl;
|
||||
cout <<" final white score : ( " << white_score <<" )"<<endl;
|
||||
|
||||
if(black_score > white_score) cout <<"The winner : " << p1_name << endl;
|
||||
else if(white_score > black_score) cout << "The winner : " << p2_name<<endl;
|
||||
else if(white_score == black_score) cout << "it is a draw!" <<endl;
|
||||
|
||||
game_history gh;
|
||||
gh.p1_name = p1_name;
|
||||
gh.p2_name = p2_name;
|
||||
gh.black_score = black_score;
|
||||
gh.white_score = white_score;
|
||||
gh.winner_name = (black_score>white_score) ? p1_name : (black_score>white_score) ? p2_name : "Draw";
|
||||
gh.time = time;
|
||||
add_data(gh);
|
||||
|
||||
cout << "\n press Enter to return to meno ...";
|
||||
getch();
|
||||
break;
|
||||
}
|
||||
|
||||
if(!current_can_move){
|
||||
cout << current_player <<"pass!" << endl;
|
||||
current_player = opponent;
|
||||
continue;
|
||||
}
|
||||
|
||||
clear_screen();
|
||||
print_board(current_player, valid_moves ,current_row , current_col);
|
||||
cout <<"current black_score: "<< black_score <<endl;
|
||||
cout <<"current white_score: "<< white_score <<endl;
|
||||
|
||||
string current_name = (current_player == BLACK? p1_name : p2_name);
|
||||
|
||||
int row = -1 , col = -1;
|
||||
bool valid_input = false;
|
||||
|
||||
if(is_single_player && current_player == WHITE){
|
||||
cout << "Bot is thinking ... "<< endl;
|
||||
|
||||
coordinate possible_moves[BOARD_SIZE*BOARD_SIZE];
|
||||
int move_count_found = 0;
|
||||
|
||||
for (int r= 0; r < BOARD_SIZE; r++){
|
||||
for (int c = 0; c < BOARD_SIZE; c++){
|
||||
if(valid_moves[r][c]){
|
||||
possible_moves[move_count_found].r = r;
|
||||
possible_moves[move_count_found].c = c;
|
||||
move_count_found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(move_count_found > 0){
|
||||
int index = rand() % move_count_found;
|
||||
row = possible_moves[index].r;
|
||||
col = possible_moves[index].c;
|
||||
valid_input = true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
cout <<"Turn : "<< current_name <<endl ;
|
||||
|
||||
while(!valid_input){
|
||||
cout << "enter move( W / A / S / D , P/SPACE/Enter to place , Q to quit) : ";
|
||||
char input_char;
|
||||
input_char = getch();
|
||||
|
||||
input_char = toupper(input_char);
|
||||
|
||||
if(input_char == 'W' || input_char == 'A' || input_char == 'S' || input_char == 'D'){
|
||||
|
||||
int temp_row = current_row;
|
||||
int temp_col = current_col;
|
||||
|
||||
switch (input_char){
|
||||
case 'W':
|
||||
if (current_row > 0) temp_row--;
|
||||
break;
|
||||
case 'S':
|
||||
if(current_row < BOARD_SIZE-1) temp_row++;
|
||||
break;
|
||||
case 'A':
|
||||
if(current_col > 0) temp_col--;
|
||||
break;;
|
||||
case 'D':
|
||||
if(current_col < BOARD_SIZE-1) temp_col++;
|
||||
break;
|
||||
}
|
||||
|
||||
current_row = temp_row;
|
||||
current_col = temp_col;
|
||||
|
||||
clear_screen();
|
||||
print_board(current_player , valid_moves , current_row , current_col);
|
||||
|
||||
cout << "current black_score : " << black_score << endl;
|
||||
cout << "current white_score : " << white_score << endl;
|
||||
cout << " Turn : " <<current_name << endl;
|
||||
}
|
||||
|
||||
else if(input_char == 'P' || input_char == 13 || input_char == 32){ // 13=Enter , 32=space
|
||||
row = current_row;
|
||||
col = current_col;
|
||||
|
||||
if(valid_moves[row][col]) valid_input = true;
|
||||
}
|
||||
|
||||
else if (input_char == 'Q'){
|
||||
cout <<"returning to meno ..."<<endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_input){
|
||||
make_move(row , col , current_player ,opponent);
|
||||
current_player = opponent;
|
||||
|
||||
clear_screen();
|
||||
print_board(current_player , valid_moves , current_row , current_col);
|
||||
cout << "current black_score : " << black_score << endl;
|
||||
cout << "current white_score : " << white_score << endl;
|
||||
cout << " Turn : " <<current_name << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display_menu(){
|
||||
cout << "~~~~~ menu ~~~~~"<< endl;
|
||||
cout << "choose one option please" << endl << "~~~~~~~~~~~~~~~~~~~~~"<<endl;
|
||||
cout << "1.New Game" << endl;
|
||||
cout << "2.Help" << endl;
|
||||
cout << "3.Game History" << endl;
|
||||
cout << "4.Enter Game Data" << endl;
|
||||
cout << "5.Exit" << endl;
|
||||
cout << " choice : ";
|
||||
}
|
||||
|
||||
void handle_new_game(){
|
||||
string p1_name , p2_name ;
|
||||
int choice;
|
||||
|
||||
cout << " \n please choose :"<<endl;
|
||||
cout << "1.tow_player"<<endl;
|
||||
cout << "2.single player" << endl;
|
||||
cout << " choice : ";
|
||||
|
||||
cin >> choice;
|
||||
|
||||
if(choice==1){
|
||||
cout << "p1.name : ";
|
||||
cin >> p1_name;
|
||||
|
||||
cout << " \n p2.name : ";
|
||||
cin >> p2_name;
|
||||
|
||||
run_game_flow(p1_name, p2_name ,false);
|
||||
}
|
||||
else{
|
||||
cout << "p.name : ";
|
||||
cin >> p1_name;
|
||||
|
||||
run_game_flow(p1_name , "Bot" , true);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_help(){
|
||||
cout << "\n=== HOW TO PLAY OTHELLO ===" << endl;
|
||||
cout << "\nOBJECTIVE:" << endl;
|
||||
cout << "Have more discs of your color than your opponent at the end." << endl;
|
||||
|
||||
cout << "\nRULES:" << endl;
|
||||
cout << "1. Black always starts first" << endl;
|
||||
cout << "2. Place your disc so that it traps opponent's discs between your discs" << endl;
|
||||
cout << "3. All trapped opponent discs flip to your color" << endl;
|
||||
cout << "4. You can trap discs in any direction: horizontal, vertical, diagonal" << endl;
|
||||
cout << "5. If you have no valid moves, you must pass" << endl;
|
||||
cout << "6. Game ends when both players have no valid moves" << endl;
|
||||
|
||||
cout << "\nCONTROLS:" << endl;
|
||||
cout << "W - Move cursor up" << endl;
|
||||
cout << "S - Move cursor down" << endl;
|
||||
cout << "A - Move cursor left" << endl;
|
||||
cout << "D - Move cursor right" << endl;
|
||||
cout << "P - Place disc" << endl;
|
||||
cout << "Q - Quit game" << endl;
|
||||
|
||||
cout << "\nBOARD SYMBOLS:" << endl;
|
||||
cout << "B - Black disc" << endl;
|
||||
cout << "W - White disc" << endl;
|
||||
cout << "* - Valid move position" << endl;
|
||||
cout << "b/w - Cursor position (empty cell)" << endl;
|
||||
|
||||
cout << "\nPress any key to return to menu...";
|
||||
getch();
|
||||
}
|
||||
|
||||
void load_data(){
|
||||
ifstream file("data.text");
|
||||
if(file.is_open()){
|
||||
cu=0;
|
||||
|
||||
while (cu <100 && file >> game_h[cu].p1_name && file >> game_h[cu].p2_name && file >> game_h[cu].black_score && file >> game_h[cu].white_score && file >> game_h[cu].time){
|
||||
cu++;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
void save_data(){
|
||||
ofstream file("data.text");
|
||||
|
||||
if(file.is_open()){
|
||||
for (int i = 0; i < cu; i++){
|
||||
file << game_h[i].p1_name <<" "<<game_h[i].p2_name << " " << game_h[i].black_score << " " << game_h[i].white_score << " " << game_h[i].time << endl;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void enter_data(){
|
||||
|
||||
game_history gh;
|
||||
|
||||
cout << "~~~~~~~~~~~ Enter Data~~~~~~~~~~~\n";
|
||||
cout << "Enter Black name: ";
|
||||
cin >> gh.p1_name;
|
||||
|
||||
cout << "Enter White name: ";
|
||||
cin >> gh.p2_name;
|
||||
|
||||
cout << "Enter Black score : ";
|
||||
cin >> gh.black_score;
|
||||
|
||||
cout << "Enter White score : ";
|
||||
cin >> gh.white_score;
|
||||
|
||||
if(gh.black_score > gh.white_score) gh.winner_name = gh.p1_name;
|
||||
else if(gh.white_score < gh.black_score) gh.winner_name = gh.p2_name;
|
||||
else gh.winner_name = "Draw!";
|
||||
|
||||
cout << "Enter the time of the game : ";
|
||||
cin >> gh.time;
|
||||
|
||||
add_data(gh);
|
||||
getch();
|
||||
}
|
||||
|
||||
void report_data(){
|
||||
cout << "\n~~~~~~~~~~~Data~~~~~~~~~~~\n";
|
||||
|
||||
if(cu ==0) cout <<" no game history available";
|
||||
|
||||
else{
|
||||
for (int i = 0; i < cu; i++){
|
||||
game_history gah = game_h[i];
|
||||
cout << "\n ~~~~~~~~~~~~~~ The History ~~~~~~~~~~~~~~";
|
||||
cout << "p1_name : " << gah.p1_name <<endl;
|
||||
cout << "p2_name : " << gah.p2_name <<endl;
|
||||
cout << "black_score : " << gah.black_score << endl;
|
||||
cout << "white_score : " << gah.white_score << endl;
|
||||
cout << "date : " <<gah.time << endl;
|
||||
}
|
||||
}
|
||||
getch();
|
||||
}
|
||||
|
||||
void add_data(game_history gh){
|
||||
game_h[cu] = gh;
|
||||
cu++;
|
||||
save_data();
|
||||
}
|
||||
|
||||
int main(){
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
load_data();
|
||||
|
||||
int choice;
|
||||
bool running = true;
|
||||
|
||||
while(running){
|
||||
|
||||
display_menu();
|
||||
cin >> choice;
|
||||
|
||||
switch (choice)
|
||||
{
|
||||
case 1:
|
||||
handle_new_game();
|
||||
break;
|
||||
case 2:
|
||||
handle_help();
|
||||
break;
|
||||
case 3:
|
||||
report_data();
|
||||
break;
|
||||
case 4:
|
||||
enter_data();
|
||||
break;
|
||||
case 5:
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user