采用二维数组保存棋盘信息,棋盘上面的任何一个位置,里面可以放置三类信息。
下棋就是在二维数组中找对应的空位置,进行落子落完子之后下来就要考虑该落子位置是否有”五子连珠“,进而进行输赢判定,每一次走棋,多会有四种情况
#include
#include
#include
void Menu() //游戏菜单
{
printf("############################\n");
printf("## 0. Exit 1. Play ##\n");
printf("############################\n");
printf("Please Select# ");
}
int main()
{
int quit = 0;
int select = 0;
while (!quit) {
Menu();
scanf("%d", &select);
switch (select) { //根据用户选择,执行合适的游戏逻辑代码
case 0:
quit = 1;
break;
case 1:
Game();
break;
defalut:
printf("Please Select Again!\n");
break;
}
}
}
#define ROW 20 //数组行数,可以按照需求调整
#define COL 20 //数组列数,可以按照需求调整
#define PLAYER1 1 //玩家1编号,默认棋盘数据是0,玩家1落子,该位置被改成2
#define PLAYER2 2 //玩家2编号,默认棋盘数据是0,玩家1落子,该位置被改成2
#define NEXT 0 //游戏继续
#define PLAYER1_WIN 1 //玩家1赢了
#define PLAYER2_WIN 2 //玩家2赢了
#define DRAW 3 //平局
void Game()
{
int board[ROW][COL]; //采用ROW * COL型的二维数组,来进行游戏信息的保存
memset(board, '\0', sizeof(board)); //默认棋盘数据都是0
int result = NEXT;
do {
ShowBoard(board); //显示棋盘
PlayerMove(board, PLAYER1); //PLAYER1先走,也可以随机让一个人先走
result = IsOver(board); //判定游戏是否结束
if (NEXT != result) {
break;
}
ShowBoard(board);
PlayerMove(board, PLAYER2);
result = IsOver(board);
if (NEXT != result) {
break;
}
} while (1);
ShowBoard(board);
switch (result) {
case PLAYER1_WIN:
printf("Player1 win!\n");
break;
case PLAYER2_WIN:
printf("Player2 win!\n");
break;
case DRAW:
printf("Player1 darw Player2!\n");
break;
}
}
//computer or player move postion,just for simple
//当前用户的落子位置,相对而言这样设计,能够简化游戏逻辑
int x = 0;
int y = 0;
void PlayerMove(int board[ROW][COL], int who)
{
}
int ChessCount(int board[ROW][COL], enum Dir d)
{
return 0;
}
int IsOver(int board[ROW][COL])
{
return NEXT;
}
void ShowBoard(int board[ROW][COL])
{
}
gobang:gobang.c
gcc -o $@ $^ -g -std=c99
.PHONY:clean
clean:
rm -f gobang *.o
void PlayerMove(int board[ROW][COL], int who)
{
while (1) {
printf("\nPlayer[ %d ] Please Enter Your Postion# ", who);
scanf("%d%d", &x, &y);
if (x<0 || y > COL) { //这里的x,y是全局的,每次都记录着当前用户的落子位置
printf("Postion Error!\n");
}
else if (board[x][y] != 0) {
printf("Postion Is Occupied!\n");
}
else {
board[x][y] = who; //谁落子,就放置谁的数据
break;
}
}
}
void ShowBoard(int board[ROW][COL])
{
printf("\033c");
printf("\n\n ");
for (int i = 0; i < COL; i++) {
printf("%3d", i);
}
printf("\n");
for (int i = 0; i < ROW; i++) {
printf("%-3d", i);
for (int j = 0; j < COL; j++) {
if (board[i][j] == PLAYER1) {
//player1
printf(" ● ");
}
else if (board[i][j] == PLAYER2) {
//player2
printf(" ○ ");
}
else {
//Space
printf(" . ");
}
}
printf("\n");
}
}
//默认符号比较丑陋,我们需要使用美化后的符号,可以在下面的链接处获取符号,直接复制粘贴就行
//https://www.jiuwa.net/fuhao/daquan/
任何落子位置都有八个方向,所以判定五子连珠,本质是判定1,5方向之和,2,6方向之和,3,7方向之和,4,8方向之和,其中任意一个出现相同的连续五个棋子,即游戏结束
enum Dir { // 枚举八个方向
LEFT,
RIGHT,
UP,
DOWN,
LEFT_UP,
RIGHT_DOWN,
RIGHT_UP,
LEFT_DOWN
};
int ChessCount(int board[ROW][COL], enum Dir d) //这个函数是重点
{
int _x = x;
int _y = y;
int count = 0;
while (1) {
switch (d) {
case LEFT:
_y--;
break;
case RIGHT:
_y++;
break;
case UP:
_x--;
break;
case DOWN:
_x++;
break;
case LEFT_UP:
_x--, _y--;
break;
case RIGHT_DOWN:
_x++, _y++;
break;
case RIGHT_UP:
_x--, _y++;
break;
case LEFT_DOWN:
_x++, _y--;
break;
}
if (_x < 0 || _x > ROW - 1 || _y < 0 || _y > COL - 1) { //坐标移动完毕,一定要先保证没有越界
break;
}
if (board[x][y] == board[_x][_y]) { //判定指定位置和原始位置的棋子是否相同,“连珠”就体现在这里
count++;
}
else {
break;
}
}
return count;
}
int IsOver(int board[ROW][COL])
{
//见上图,注意,每次统计的时候,都没有统计当前节点,需要单独+1
int count1 = ChessCount(board, LEFT) + ChessCount(board, RIGHT) + 1;
int count2 = ChessCount(board, UP) + ChessCount(board, DOWN) + 1;
int count3 = ChessCount(board, LEFT_UP) + ChessCount(board, RIGHT_DOWN) + 1;
int count4 = ChessCount(board, LEFT_DOWN) + ChessCount(board, RIGHT_UP) + 1; if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5) {
if (board[x][y] == PLAYER1) {
return PLAYER1_WIN;
}
else {
return PLAYER2_WIN;
}
}
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (board[i][j] == 0) {
return NEXT;
}
}
}
return DRAW;
}
引入进度条
尝试人机对战
功能扩展:颜色提示,步数记录,先手随机交换等
网络版本?
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#define ROW 20
#define COL 20
#define NEXT 0
#define PLAYER1_WIN 1
#define PLAYER2_WIN 2
#define DRAW 3
#define PLAYER1 1
#define PLAYER2 2
enum Dir {
LEFT,
RIGHT,
UP,
DOWN,
LEFT_UP,
RIGHT_DOWN,
RIGHT_UP,
LEFT_DOWN
};
//computer or player move postion,just for simple
int x = 0;
int y = 0;
void Menu()
{
printf("############################\n");
printf("## 0. Exit 1. Play ##\n");
printf("############################\n");
printf("Please Select# ");
}
void PlayerMove(int board[ROW][COL], int who)
{
while (1) {
printf("\nPlayer[ %d ] Please Enter Your Postion# ", who);
scanf("%d%d", &x, &y);
if (x<0 || y > COL) {
printf("Postion Error!\n");
}
else if (board[x][y] != 0) {
printf("Postion Is Occupied!\n");
}
else {
board[x][y] = who;
break;
}
}
}
int ChessCount(int board[ROW][COL], enum Dir d)
{
int _x = x;
int _y = y;
int count = 0;
while (1) {
switch (d) {
case LEFT:
_y--;
break;
case RIGHT:
_y++;
break;
case UP:
_x--;
break;
case DOWN:
_x++;
break;
case LEFT_UP:
_x--, _y--;
break;
case RIGHT_DOWN:
_x++, _y++;
break;
case RIGHT_UP:
_x--, _y++;
break;
case LEFT_DOWN:
_x++, _y--;
break;
}
if (_x < 0 || _x > ROW - 1 || _y < 0 || _y > COL - 1) {
break;
}
if (board[x][y] == board[_x][_y]) {
count++;
}
else {
break;
}
}
return count;
}
int IsOver(int board[ROW][COL])
{
int count1 = ChessCount(board, LEFT) + ChessCount(board, RIGHT) + 1;
int count2 = ChessCount(board, UP) + ChessCount(board, DOWN) + 1;
int count3 = ChessCount(board, LEFT_UP) + ChessCount(board, RIGHT_DOWN) + 1;
int count4 = ChessCount(board, LEFT_DOWN) + ChessCount(board, RIGHT_UP) + 1;
if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5) {
if (board[x][y] == PLAYER1) {
return PLAYER1_WIN;
}
else {
return PLAYER2_WIN;
}
}
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (board[i][j] == 0) {
return NEXT;
}
}
}
return DRAW;
}
void ShowBoard(int board[ROW][COL])
{
printf("\033c");
printf("\n\n ");
for (int i = 0; i < COL; i++) {
printf("%3d", i);
}
printf("\n");
for (int i = 0; i < ROW; i++) {
printf("%-3d", i);
for (int j = 0; j < COL; j++) {
if (board[i][j] == PLAYER1) {
//player1
printf(" ● ");
}
else if (board[i][j] == PLAYER2) {
//player2
printf(" ○ ");
}
else {
//Space
printf(" . ");
}
}
printf("\n");
}
}
void Game()
{
int board[ROW][COL];
memset(board, '\0', sizeof(board));
int result = NEXT;
do {
ShowBoard(board);
PlayerMove(board, PLAYER1);
result = IsOver(board);
if (NEXT != result) {
break;
}
ShowBoard(board);
PlayerMove(board, PLAYER2);
result = IsOver(board);
if (NEXT != result) {
break;
}
} while (1);
ShowBoard(board);
switch (result) {
case PLAYER1_WIN:
printf("Player1 win!\n");
break;
case PLAYER2_WIN:
printf("Player2 win!\n");
break;
case DRAW:
printf("Player1 darw Player2!\n");
break;
}
}
int main()
{
int quit = 0;
int select = 0;
while (!quit) {
Menu();
scanf("%d", &select);
switch (select) {
case 0:
quit = 1;
break;
case 1:
Game();
break;
defalut:
printf("Please Select Again!\n");
break;
}
}
}