#ifndef _GO_BANG_
#define _GO_BANG_
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define ROW 15
#define COL 15
#define BLACK 'B'
#define WHITE 'O'
/**
* 棋盘初始化函数,提供当前函数的参数是个 char 类型二维数组,
* 数组的一维下标和二维下标由 ROW 和 COL 两个宏常量控制
*
* @param chess_board 用户提供的 char 类型二维数组
*/
void gobang_ui_init(char chess_board[][COL]);
/**
* 棋盘展示函数,,提供当前函数的参数是个 char 类型二维数组,
* 数组的一维下标和二维下标由 ROW 和 COL 两个宏常量控制
*
* @param chess_board 用户提供的 char 类型二维数组
*/
void show_chess_board(char chess_board[][COL]);
/**
* 落子函数,根据当前玩家提供的行列下标位置,落子对应玩家的棋子
*
* @param chess_board 当前五子棋对应的棋盘 char 类型二维数组
* @param row_index 用户指定落子的行下标位置
* @param col_index 用户指定落子的列下标位置
* @param player 对应用户,利用 BLACK 和 WHITE 两个宏区分用户玩家
* @return 落子成功返回 1,否则返回 0
*/
int place_stone(char chess_board[][COL], int row_index, int col_index, char player);
/**
* 判断是否游戏获胜条件
*
* @param chess_board 当前五子棋对应的棋盘 char 类型二维数组
* @param row_index 用户指定落子的行下标位置
* @param col_index 用户指定落子的列下标位置
* @param player 对应用户,利用 BLACK 和 WHITE 两个宏区分用户玩家
* @return 游戏胜利返回 1,否则返回 0
*/
int is_win(char chess_board[][COL], int row_index, int col_index, char player);
#endif
#include "gobang.h"
using namespace std;
void gobang_ui_init(char chess_board[][COL])
{
memset(chess_board, '+', ROW * COL);
}
void show_chess_board(char chess_board[][COL])
{
cout << " 1 2 3 4 5 6 7 8 9 A B C D E F" << endl;
for (int i = 0; i < ROW; i++)
{
if (i + 1 < 10)
{
cout << i + 1;
}
else
{
cout << (char)('A' + i - 9);
}
for (int j = 0; j < COL; j++)
{
cout << ' ' << chess_board[i][j];
}
cout << endl;
}
}
int place_stone(char chess_board[][COL], int row_index, int col_index, char player)
{
row_index -= 1;
col_index -= 1;
if (row_index < 0 || row_index > ROW - 1 || col_index < 0 || col_index > COL - 1 || chess_board[row_index][col_index] != '+')
{
cout << "您落子的下标位置不符合游戏规则" << endl;
return 0;
}
chess_board[row_index][col_index] = player;
return 1;
}
int is_win(char chess_board[][COL], int row_index, int col_index, char player)
{
row_index -= 1;
col_index -= 1;
/*
横向判断
row_index 不变
col_index 在不超过合理下标范围以内的情况下,-4 作为左侧限制,+4 作为右侧限制
*/
/*
count 记录当前玩家对应棋子的连续总个数。
*/
int count = 0;
for (int j = (col_index - 4 > 0 ? col_index - 4 : 0);
j <= (col_index + 4 > COL - 1 ? COL - 1 : col_index + 4);
j++)
{
if (chess_board[row_index][j] == player)
{
count += 1;
if (5 == count)
{
return 1;
}
}
else
{
count = 0;
}
}
count = 0;
/*
纵向判断
col_index 不变
row_index 在不超过合理下标范围以内的情况下,-4 作为顶部限制,+4 作为底部限制
*/
for (int i = (row_index - 4 > 0 ? row_index - 4 : 0);
i <= (row_index + 4 > ROW - 1 ? ROW - 1 : row_index + 4);
i++)
{
if (chess_board[i][col_index] == player)
{
count += 1;
if (5 == count)
{
return 1;
}
}
else
{
count = 0;
}
}
/*
\ 正对角方向
需要明确
1. 左上角起始下标位置
2. 右下角终止下标位置
3. row_index 和 col_index 下标都是递增关系。
*/
// 左上角起始下标位置
int left_row_dist = row_index - 4 > 0 ? 4 : row_index - 0;
int left_col_dist = col_index - 4 > 0 ? 4 : col_index - 0;
int left_min_dist = left_row_dist > left_col_dist ? left_col_dist : left_row_dist;
/*
左侧起始下标位置是
[row_index - left_min_dist][col_index - left_min_dist]
*/
// 右下角终止下标位置
int right_row_dist = row_index + 4 > ROW - 1 ? ROW - 1 - row_index : 4;
int right_col_dist = col_index + 4 > COL - 1 ? COL - 1 - col_index : 4;
int right_min_dist = right_row_dist > right_col_dist ? right_col_dist : right_row_dist;
/*
右侧终止下标位置是
[row_index + right_min_dist][col_index + right_min_dist]
*/
count = 0;
for (int i = row_index - left_min_dist, j = col_index - left_min_dist;
i <= row_index + right_min_dist && j <= col_index + right_min_dist;
i++, j++)
{
if (chess_board[i][j] == player)
{
count += 1;
if (5 == count)
{
return 1;
}
}
else
{
count = 0;
}
}
/*
/ 反对角方向
需要明确
1. 左下角起始下标位置
row_index + 4 判断
col_index - 4 判断
2. 右上角终止下标位置
row_index - 4 判断
col_index + 4 判断
3. row_index 行下标递减关系,col_index 列下标递增关系
*/
left_row_dist = row_index + 4 > ROW - 1 ? ROW - 1 - row_index : 4;
left_col_dist = col_index - 4 > 0 ? 4 : col_index - 0;
left_min_dist = left_row_dist > left_col_dist ? left_col_dist : left_row_dist;
/*
左下角起始下标位置
[row_index + left_nmin_dist][col_index - left_min_dist];
*/
right_row_dist = row_index - 4 > 0 ? 4 : row_index - 0;
right_col_dist = col_index + 4 > COL - 1 ? COL - 1 - row_index : 4;
right_min_dist = right_row_dist > right_col_dist ? right_col_dist : right_row_dist;
/*
右上角终止下标位置
[row_index - right_min_dist][col_index + right_min_dist];
*/
for (int i = row_index + left_min_dist, j = col_index - left_min_dist;
i >= row_index - right_min_dist, j <= col_index + right_min_dist;
i--, j++)
{
if (chess_board[i][j] == player)
{
count += 1;
if (5 == count)
{
return 1;
}
}
else
{
count = 0;
}
}
return 0;
}
#include <iostream>
#include "gobang.h"
using namespace std;
int main(int argc, char const *argv[])
{
int ret = 0;
/**
* flag 是一个游戏胜利判断条件
*/
int flag = 0;
/**
* 记录当前落子的总个数,同时可以利用 % 2 判断
* 落子的玩家是哪一个玩家
*/
int count = 0;
int row_index = 0;
int col_index = 0;
char player = '\0';
char chess_board[ROW][COL] = {'\0'};
gobang_ui_init(chess_board);
while (1)
{
show_chess_board(chess_board);
if (count % 2 == 0)
{
cout << "执黑落子";
player = BLACK;
}
else
{
cout << "执白落子";
player = WHITE;
}
cout << ",请输入对应的下标位置, 例如 : 2 3 : ";
cin >> row_index >> col_index;
ret = place_stone(chess_board, row_index, col_index, player);
if (ret)
{
flag = is_win(chess_board, row_index, col_index, player);
cout << "flag = " << flag << endl;
}
count += ret;
if (flag)
{
cout << (player == BLACK ? "执黑获胜" : "执白获胜") << endl;
break;
}
}
return 0;
}